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

1.562     foxr        1: #
1.389     foxr        2: # The LearningOnline Network
1.1       www         3: # Printout
                      4: #
1.575.2.1! foxr        5: # $Id: lonprintout.pm,v 1.575 2010/04/19 10:29:40 foxr Exp $
1.11      albertel    6: #
                      7: # Copyright Michigan State University Board of Trustees
                      8: #
                      9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                     10: #
                     11: # LON-CAPA is free software; you can redistribute it and/or modify
                     12: # it under the terms of the GNU General Public License as published by
                     13: # the Free Software Foundation; either version 2 of the License, or
                     14: # (at your option) any later version.
                     15: #
                     16: # LON-CAPA is distributed in the hope that it will be useful,
                     17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     19: # GNU General Public License for more details.
                     20: #
                     21: # You should have received a copy of the GNU General Public License
                     22: # along with LON-CAPA; if not, write to the Free Software
                     23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     24: #
                     25: # /home/httpd/html/adm/gpl.txt
                     26: # http://www.lon-capa.org/
                     27: #
1.3       sakharuk   28: #
1.1       www        29: package Apache::lonprintout;
                     30: use strict;
1.10      albertel   31: use Apache::Constants qw(:common :http);
1.2       sakharuk   32: use Apache::lonxml;
                     33: use Apache::lonnet;
1.54      sakharuk   34: use Apache::loncommon;
1.13      sakharuk   35: use Apache::inputtags;
1.54      sakharuk   36: use Apache::grades;
1.13      sakharuk   37: use Apache::edit;
1.5       sakharuk   38: use Apache::File();
1.68      sakharuk   39: use Apache::lonnavmaps;
1.511     foxr       40: use Apache::admannotations;
1.521     foxr       41: use Apache::lonenc;
1.531     foxr       42: use Apache::entities;
1.550     foxr       43: use Apache::londefdef;
                     44: 
                     45: use File::Basename;
1.531     foxr       46: 
1.515     foxr       47: use HTTP::Response;
1.511     foxr       48: 
1.491     albertel   49: use LONCAPA::map();
1.34      sakharuk   50: use POSIX qw(strftime);
1.255     www        51: use Apache::lonlocal;
1.429     foxr       52: use Carp;
1.439     www        53: use LONCAPA;
1.60      sakharuk   54: 
1.397     albertel   55: my %perm;
1.454     foxr       56: my %parmhash;
1.459     foxr       57: my $resources_printed;
1.454     foxr       58: 
1.515     foxr       59: # Global variables that describe errors in ssi calls detected  by ssi_with_retries.
                     60: #
                     61: 
1.575.2.1! foxr       62: my $ssi_error;                  # True if there was an ssi error.
        !            63: my $ssi_last_error_resource;    # The resource URI that could not be fetched.
        !            64: my $ssi_last_error
        !            65:   ;    # The error text from the server. (e.g. 500 Server timed out).
1.515     foxr       66: 
                     67: #
                     68: #  Our ssi max retry count.
                     69: #
                     70: 
1.575.2.1! foxr       71: my $ssi_retry_count = 5;    # Some arbitrary value.
1.515     foxr       72: 
1.556     foxr       73: #  Font size:
                     74: 
1.575.2.1! foxr       75: my $font_size = 'normalsize';    # Default is normalsize...
1.556     foxr       76: 
1.562     foxr       77: #----------------------------  Helper helpers. -------------------------
                     78: 
                     79: #  Returns the text needd for a student chooser.
                     80: #  that text must still be parsed by the helper xml parser.
                     81: # Parameters:
                     82: #   this_state   - State name of the chooser.
                     83: #   sort_choice  - variable to hold the sorting choice.
                     84: #   variable     - Name of variable to hold students.
                     85: #   next_state   - State after chooser.
                     86: 
                     87: sub generate_student_chooser {
1.575.2.1! foxr       88:     my ( $this_state, $sort_choice, $variable, $next_state ) = @_;
1.562     foxr       89:     my $result = <<CHOOSE_STUDENTS;
                     90:   <state name="$this_state" title="Select Students and Resources">
                     91:       <message><b>Select sorting order of printout</b> </message>
                     92: 
                     93:     <choices variable="$sort_choice">
                     94:       <choice computer='0'>Sort by section then student</choice>
                     95:       <choice computer='1'>Sort by students across sections.</choice>
                     96:     </choices>
                     97: 
                     98:       <message><br /><hr /><br /> </message>
                     99:       <student multichoice='1' 
                    100:                variable="$variable" 
                    101:                nextstate="$next_state" 
                    102:                coursepersonnel="1" />
                    103:   </state>
                    104: 
                    105: CHOOSE_STUDENTS
                    106: 
1.575.2.1! foxr      107:     return $result;
1.562     foxr      108: }
                    109: 
                    110: # Generate the text needed for a resource chooser given the top level of
                    111: # the sequence/page
                    112: #
                    113: # Parameters:
                    114: #     this_state    - State name of the chooser.
                    115: #     prompt_text   - Text to use to prompt user.
                    116: #     resource_options - Resource tag options e.g.
                    117: #                        "multichoice='1', toponly='1', addstatus='1'"
                    118: #                     that control the selection and appearance of the
                    119: #                     resource selector.
                    120: #     variable      - Name of the variable to hold the choice
                    121: #     next_state    - Name of the next state the helper should transition
                    122: #                     to
                    123: #     top_url       - Top level URL within which to make the selector.
                    124: #                     If empty the top level sequence is shown.
                    125: #     filter        - How to filter the resources.
                    126: #     value_func    - <valuefunc> function.
                    127: #     choice_func   - If not empty generates a <choicefunc> with this function.
1.575.2.1! foxr      128: #     start_new_option
1.562     foxr      129: #                   - Fragment appended after valuefunc.
                    130: #
                    131: #
                    132: sub generate_resource_chooser {
1.575.2.1! foxr      133:     my (
        !           134:         $this_state, $prompt_text, $resource_options,
        !           135:         $variable,   $next_state,  $top_url,
        !           136:         $filter,     $choice_func, $value_func,
        !           137:         $start_new_option
        !           138:     ) = @_;
1.562     foxr      139: 
                    140:     my $result = <<CHOOSE_RESOURCES;
                    141: <state name="$this_state" title="$prompt_text">
                    142:     <resource variable="$variable" $resource_options
                    143:               closeallpages="1">
                    144:       <nextstate>$next_state</nextstate>
                    145:       <filterfunc>return $filter;</filterfunc>
                    146: CHOOSE_RESOURCES
1.575.2.1! foxr      147:     if ( $choice_func ne '' ) {
        !           148:         $result .= "<choicefunc>return $choice_func;</choicefunc>";
1.562     foxr      149:     }
1.575.2.1! foxr      150:     if ( $top_url ne '' ) {
        !           151:         $result .= "<mapurl>$top_url</mapurl>";
1.562     foxr      152:     }
                    153:     $result .= <<CHOOSE_RESOURCES;
                    154:       <valuefunc>return $value_func;</valuefunc>
                    155:       $start_new_option
                    156:       </resource>
                    157:     </state>
                    158: CHOOSE_RESOURCES
                    159: 
                    160:     return $result;
                    161: }
1.575.2.1! foxr      162: 
1.562     foxr      163: #
                    164: #   Generate the helper XML for a code choice helper dialog:
                    165: #
                    166: # Paramters:
                    167: #   $helper       - Reference to the helper.
                    168: #   $state        - Name of the state for the chooser.
                    169: #   $next_state   - Name fo the state to follow the chooser.
                    170: #   $bubble_types - Populates the bubble sheet type dropt down.
                    171: #   $code_selections - Provides set of code choices that have been used
                    172: #   $saved_codes  - Provides the list of saved codes.
                    173: #
                    174: # Returns;
                    175: #   The Xml of the code chooser.
                    176: #
                    177: sub generate_code_selector {
1.575.2.1! foxr      178:     my ( $helper, $state, $next_state, $bubble_types, $code_selections,
        !           179:         $saved_codes )
        !           180:       = @_;    # Unpack the parameters.
1.562     foxr      181: 
                    182:     my $result = <<CHOOSE_ANON1;
                    183:   <state name="$state" title="Specify CODEd Assignments">
                    184:     <nextstate>$next_state</nextstate>
                    185:     <message><h4>Fill out one of the forms below</h4></message>
                    186:     <message><br /><hr /> <br /></message>
                    187:     <message><h3>Generate new CODEd Assignments</h3></message>
                    188:     <message><table><tr><td><b>Number of CODEd assignments to print:</b></td><td></message>
                    189:     <string variable="NUMBER_TO_PRINT_TOTAL" maxlength="5" size="5">
                    190:        <validator>
                    191: 	if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) &&
                    192: 	    !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                &&
                    193:             !\$helper->{'VARS'}{'SINGLE_CODE'}                    &&
                    194: 	    !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
                    195: 	    return "You need to specify the number of assignments to print";
                    196: 	}
                    197: 	return undef;
                    198:        </validator>
                    199:     </string>
                    200:     <message></td></tr><tr><td></message>
                    201:     <message><b>Names to save the CODEs under for later:</b></message>
                    202:     <message></td><td></message>
                    203:     <string variable="ANON_CODE_STORAGE_NAME" maxlength="50" size="20" />
                    204:     <message></td></tr><tr><td></message>
                    205:     <message><b>Bubble sheet type:</b></message>
                    206:     <message></td><td></message>
                    207:     <dropdown variable="CODE_OPTION" multichoice="0" allowempty="0">
                    208:     $bubble_types
                    209:     </dropdown>
                    210:     <message></td></tr><tr><td colspan="2"></td></tr><tr><td></message>
                    211:     <message></td></tr><tr><td></table></message>
                    212:     <message><br /><hr /><h3>Print a Specific CODE </h3><br /><table></message>
                    213:     <message><tr><td><b>Enter a CODE to print:</b></td><td></message>
                    214:     <string variable="SINGLE_CODE" size="10">
                    215:         <validator>
                    216: 	   if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}           &&
                    217: 	      !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                 &&
                    218: 	      !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
                    219: 	      return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'},
                    220: 						      \$helper->{'VARS'}{'CODE_OPTION'});
                    221: 	   } else {
                    222: 	       return undef;	# Other forces control us.
                    223: 	   }
                    224:         </validator>
                    225:     </string>
                    226:     <message></td></tr><tr><td></message>
                    227:         $code_selections
                    228:     <message></td></tr></table></message>
                    229:     <message><hr /><h3>Reprint a Set of Saved CODEs</h3><table><tr><td></message>
                    230:     <message><b>Select saved CODEs:</b></message>
                    231:     <message></td><td></message>
                    232:     <dropdown variable="REUSE_OLD_CODES">
                    233:         $saved_codes
                    234:     </dropdown>
                    235:     <message></td></tr></table></message>
                    236:   </state>
                    237: CHOOSE_ANON1
                    238: 
1.575.2.1! foxr      239:     return $result;
1.562     foxr      240: }
                    241: 
                    242: #-----------------------------------------------------------------------
                    243: 
1.498     foxr      244: # Fetch the contents of a resource, uninterpreted.
                    245: # This is used here to fetch a latex file to be included
                    246: # verbatim into the printout<
                    247: # NOTE: Ask Guy if there is a lonnet function similar to this?
                    248: #
                    249: # Parameters:
                    250: #   URL of the file
                    251: #
                    252: sub fetch_raw_resource {
                    253:     my ($url) = @_;
                    254: 
1.575.2.1! foxr      255:     my $filename = &Apache::lonnet::filelocation( "", $url );
        !           256:     my $contents = &Apache::lonnet::getfile($filename);
1.498     foxr      257: 
1.575.2.1! foxr      258:     if ( $contents == -1 ) {
        !           259:         return "File open failed for $filename";    # This will bomb the print.
1.498     foxr      260:     }
1.500     foxr      261:     return $contents;
1.498     foxr      262: 
                    263: }
                    264: 
1.575.2.1! foxr      265: #  Fetch the annotations associated with a URL and
1.511     foxr      266: #  put a centered 'annotations:' title.
                    267: #  This is all suppressed if the annotations are empty.
                    268: #
                    269: sub annotate {
                    270:     my ($symb) = @_;
                    271: 
1.575.2.1! foxr      272:     my $annotation_text = &Apache::loncommon::get_annotation( $symb, 1 );
1.511     foxr      273: 
                    274:     my $result = "";
                    275: 
1.575.2.1! foxr      276:     if ( length($annotation_text) > 0 ) {
        !           277:         $result .=
        !           278:           '\\hspace*{\\fill} \\\\[\\baselineskip] \textbf{Annotations:} \\\\ ';
        !           279:         $result .= "\n";
        !           280:         $result .=
        !           281:           &Apache::lonxml::latex_special_symbols( $annotation_text, "" )
        !           282:           ;    # Escape latex.
        !           283:         $result .= "\n\n";
1.511     foxr      284:     }
                    285:     return $result;
                    286: }
                    287: 
1.556     foxr      288: #
                    289: #   Set a global document font size:
                    290: #   This is done by replacing \begin{document}
                    291: #   with \begin{document}{\some-font-directive
                    292: #   and \end{document} with
                    293: #   }\end{document
                    294: #
                    295: sub set_font_size {
                    296: 
                    297:     my ($text) = @_;
                    298: 
1.575     foxr      299:     # There appear to be cases where the font directive is empty.. in which
                    300:     # case the first substituion would  insert a spurious \ oh happy day.
                    301:     # as this has been the cause of much mystery and hair pulling _sigh_
                    302: 
1.575.2.1! foxr      303:     if ( $font_size ne '' ) {
1.575     foxr      304: 
1.575.2.1! foxr      305:         $text =~ s/\\begin{document}/\\begin{document}{\\$font_size/;
1.575     foxr      306:     }
1.556     foxr      307:     $text =~ s/\\end{document}/}\\end{document}/;
                    308:     return $text;
                    309: 
                    310: }
                    311: 
1.575.2.1! foxr      312: # include_pdf - PDF files are included into the
1.550     foxr      313: # output as follows:
                    314: #  - The PDF, if necessary, is replicated.
                    315: #  - The PDF is added to the list of files to convert to postscript (along with the images).
                    316: #  - The LaTeX is added to include the final converted postscript in the file as an included
                    317: #    job.  The assumption is that the includedpsheader.ps header will be included.
                    318: #
                    319: # Parameters:
                    320: #   pdf_uri   - URI of the PDF file to include.
1.575.2.1! foxr      321: #
1.550     foxr      322: # Returns:
                    323: #  The LaTeX to include.
                    324: #
                    325: # Assumptions:
                    326: #    The uri is actually a PDF file
                    327: #    The postscript will have the includepsheader.ps included.
                    328: #
                    329: #
                    330: sub include_pdf {
                    331:     my ($pdf_uri) = @_;
                    332: 
                    333:     # Where is the file? If not local we'll need to repcopy it:'
                    334: 
1.575.2.1! foxr      335:     my $file = &Apache::lonnet::filelocation( '', $pdf_uri );
        !           336:     if ( !-e $file ) {
        !           337:         &Apache::lonnet::repcopy($file);
        !           338:         $file = &Apache::lonnet::filelocation( '', $pdf_uri );
1.550     foxr      339:     }
                    340: 
1.575.2.1! foxr      341:   #  The file isn ow replicated locally.. or it did not exist in the first place
        !           342:   # (unlikely).  If it did exist, add the pdf to the set of files/images that
        !           343:   # need tob e converted for this print job:
1.550     foxr      344: 
                    345:     $file =~ s|(.*)/res/|/home/httpd/html/res/|;
                    346: 
1.575.2.1! foxr      347:     open( FILE,
        !           348: ">>/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat"
        !           349:     );
1.550     foxr      350:     print FILE ("$file\n");
1.575.2.1! foxr      351:     close(FILE);
1.550     foxr      352: 
                    353:     # Construct the special to put out.  To do this we need to get the
                    354:     # resulting filename after conversion.  The file will have the same name
                    355:     # but will be in the user's spool directory with converted images.
                    356: 
                    357:     my $dirname = "/home/httpd/prtspool/$env{'user.name'}/";
1.575.2.1! foxr      358:     my ( $base, $path, $ext ) = &fileparse( $file, '.pdf' );
        !           359: 
1.550     foxr      360: #    my $destname = $dirname.'/'.$base.'.eps'; # Not really an eps but easier in printout.pl
                    361:     $base =~ s/ /\_/g;
                    362: 
1.551     foxr      363:     my $output = &print_latex_header();
1.575.2.1! foxr      364:     $output .=
        !           365:       '\special{ps: _begin_job_ (' . $base . '.pdf.eps' . ')run _end_job_}';
1.550     foxr      366: 
                    367:     return $output;
                    368: 
                    369: }
                    370: 
1.515     foxr      371: #
1.559     foxr      372: #   ssi_with_retries- Does the server side include of a resource.
1.515     foxr      373: #                      if the ssi call returns an error we'll retry it up to
                    374: #                      the number of times requested by the caller.
                    375: #                      If we still have a proble, no text is appended to the
                    376: #                      output and we set some global variables.
1.575.2.1! foxr      377: #                      to indicate to the caller an SSI error occurred.
1.515     foxr      378: #                      All of this is supposed to deal with the issues described
                    379: #                      in LonCAPA BZ 5631 see:
                    380: #                      http://bugs.lon-capa.org/show_bug.cgi?id=5631
                    381: #                      by informing the user that this happened.
                    382: #
                    383: # Parameters:
                    384: #   resource   - The resource to include.  This is passed directly, without
                    385: #                interpretation to lonnet::ssi.
                    386: #   form       - The form hash parameters that guide the interpretation of the resource
1.575.2.1! foxr      387: #
1.515     foxr      388: #   retries    - Number of retries allowed before giving up completely.
                    389: # Returns:
                    390: #   On success, returns the rendered resource identified by the resource parameter.
                    391: # Side Effects:
                    392: #   The following global variables can be set:
1.523     raeburn   393: #    ssi_error                - If an unrecoverable error occurred this becomes true.
1.515     foxr      394: #                               It is up to the caller to initialize this to false
                    395: #                               if desired.
1.523     raeburn   396: #    ssi_last_error_resource  - If an unrecoverable error occurred, this is the value
1.515     foxr      397: #                               of the resource that could not be rendered by the ssi
                    398: #                               call.
                    399: #    ssi_last_error           - The error string fetched from the ssi response
                    400: #                               in the event of an error.
                    401: #
                    402: sub ssi_with_retries {
1.575.2.1! foxr      403:     my ( $resource, $retries, %form ) = @_;
1.515     foxr      404: 
1.559     foxr      405:     my $target = $form{'grade_target'};
                    406:     my $aom    = $form{'answer_output_mode'};
                    407: 
1.575.2.1! foxr      408:     my ( $content, $response ) =
        !           409:       &Apache::loncommon::ssi_with_retries( $resource, $retries, %form );
        !           410:     if ( !$response->is_success ) {
        !           411:         $ssi_error               = 1;
        !           412:         $ssi_last_error_resource = $resource;
        !           413:         $ssi_last_error          = $response->code . " " . $response->message;
        !           414:         $content                 = '\section*{!!! An error occurred !!!}';
        !           415:         &Apache::lonnet::logthis(
        !           416:             "Error in SSI resource: $resource Error: $ssi_last_error");
1.515     foxr      417:     }
1.516     foxr      418: 
                    419:     return $content;
                    420: 
1.515     foxr      421: }
                    422: 
1.524     www       423: sub get_student_view_with_retries {
1.575.2.1! foxr      424:     my (
        !           425:         $curresline, $retries, $username, $userdomain,
        !           426:         $courseid,   $target,  $moreenv
        !           427:     ) = @_;
        !           428: 
        !           429:     my ( $content, $response ) =
        !           430:       &Apache::loncommon::get_student_view_with_retries(
        !           431:         $curresline, $retries, $username, $userdomain,
        !           432:         $courseid,   $target,  $moreenv
        !           433:       );
        !           434:     if ( !$response->is_success ) {
        !           435:         $ssi_error = 1;
        !           436:         $ssi_last_error_resource =
        !           437:           $curresline . ' for user ' . $username . ':' . $userdomain;
        !           438:         $ssi_last_error = $response->code . " " . $response->message;
        !           439:         $content        = '\section*{!!! An error occurred !!!}';
        !           440:         &Apache::lonnet::logthis(
        !           441: "Error in SSI (student view) resource: $curresline Error: $ssi_last_error User: $username:$userdomain"
        !           442:         );
1.524     www       443:     }
                    444:     return $content;
                    445: 
                    446: }
                    447: 
1.486     foxr      448: #
                    449: #   printf_style_subst  item format_string repl
1.575.2.1! foxr      450: #
1.486     foxr      451: # Does printf style substitution for a format string that
                    452: # can have %[n]item in it.. wherever, %[n]item occurs,
                    453: # rep is substituted in format_string.  Note that
                    454: # [n] is an optional integer length.  If provided,
1.575.2.1! foxr      455: # repl is truncated to at most [n] characters prior to
1.486     foxr      456: # substitution.
                    457: #
                    458: sub printf_style_subst {
1.575.2.1! foxr      459:     my ( $item, $format_string, $repl ) = @_;
1.490     foxr      460:     my $result = "";
1.575.2.1! foxr      461:     while ( $format_string =~ /(%)(\d*)\Q$item\E/g ) {
        !           462:         my $fmt   = $1;
        !           463:         my $size  = $2;
        !           464:         my $subst = $repl;
        !           465:         if ( $size ne "" ) {
        !           466:             $subst = substr( $subst, 0, $size );
        !           467: 
        !           468:             #  Here's a nice edge case.. supose the end of the
        !           469:             #  substring is a \.  In that case may have  just
        !           470:             #  chopped off a TeX escape... in that case, we append
        !           471:             #   " " for the trailing character, and let the field
        !           472:             #  spill over a bit (sigh).
        !           473:             #  We don't just chop off the last character in order to deal
        !           474:             #  with one last pathology, and that would be if substr had
        !           475:             #  trimmed us to e.g. \\\
        !           476: 
        !           477:             if ( $subst =~ /\\$/ ) {
        !           478:                 $subst .= " ";
        !           479:             }
        !           480:         }
        !           481:         my $item_pos = pos($format_string);
        !           482:         $result .=
        !           483:           substr( $format_string, 0, $item_pos - length($size) - 2 ) . $subst;
        !           484:         $format_string = substr( $format_string, pos($format_string) );
1.486     foxr      485:     }
1.490     foxr      486: 
                    487:     # Put the residual format string into the result:
                    488: 
                    489:     $result .= $format_string;
                    490: 
                    491:     return $result;
1.486     foxr      492: }
                    493: 
1.575.2.1! foxr      494: # Format a header according to a format.
        !           495: #
1.454     foxr      496: 
                    497: # Substitutions:
                    498: #     %a    - Assignment name.
                    499: #     %c    - Course name.
                    500: #     %n    - Student name.
1.537     foxr      501: #     %s    - The section if it is supplied.
1.454     foxr      502: #
                    503: sub format_page_header {
1.575.2.1! foxr      504:     my ( $width, $format, $assignment, $course, $student, $section ) = @_;
1.565     foxr      505: 
1.575.2.1! foxr      506:     $width = &recalcto_mm($width);    # Get width in mm.
        !           507:     my $chars_per_line = int( $width / 1.6 );    # Character/textline.
1.565     foxr      508: 
1.454     foxr      509:     #  Default format?
                    510: 
1.575.2.1! foxr      511:     if ( $format eq '' ) {
1.537     foxr      512: 
1.575.2.1! foxr      513:         # For the default format, we may need to truncate
        !           514:         # elements..  To do this we need to get the page width.
        !           515:         # we assume that each character is about 2mm in width.
        !           516:         # (correct for the header text size??).  We ignore
        !           517:         # any formatting (e.g. boldfacing in this).
        !           518:         #
        !           519:         # - Allow the student/course to be one line.
        !           520:         #   but only truncate the course.
        !           521:         # - Allow the assignment to be 2 lines (wrapped).
        !           522:         #
1.486     foxr      523: 
1.575.2.1! foxr      524:         my $name_length = int( $chars_per_line * 3 / 4 );
        !           525:         my $sec_length  = int( $chars_per_line / 5 );
1.486     foxr      526: 
1.575.2.1! foxr      527:         $format = "%$name_length" . 'n';
1.489     foxr      528: 
1.575.2.1! foxr      529:         if ($section) {
        !           530:             $format .= ' - Sec: ' . "%$sec_length" . 's';
        !           531:         }
        !           532: 
        !           533:         $format .= '\\\\%c \\\\ %a';
1.490     foxr      534: 
1.454     foxr      535:     }
1.575.2.1! foxr      536: 
1.537     foxr      537:     # An open question is how to handle long user formatted page headers...
                    538:     # A possible future is to support e.g. %na so that the user can control
                    539:     # the truncation of the elements that can appear in the header.
                    540:     #
1.575.2.1! foxr      541:     $format = &printf_style_subst( "a", $format, $assignment );
        !           542:     $format = &printf_style_subst( "c", $format, $course );
        !           543:     $format = &printf_style_subst( "n", $format, $student );
        !           544:     $format = &printf_style_subst( "s", $format, $section );
        !           545: 
1.537     foxr      546:     # If the user put %'s in the format string, they  must be escaped
                    547:     # to \% else LaTeX will think they are comments and terminate
                    548:     # the line.. which is bad!!!
1.575.2.1! foxr      549: 
1.538     onken     550:     # If the user has role author, $course and $assignment are empty so
                    551:     # there is '\\ \\ ' in the page header. That's cause a error in LaTeX
1.575.2.1! foxr      552:     if ( $format =~ /\\\\\s\\\\\s/ ) {
        !           553: 
1.538     onken     554:         #TODO find sensible caption for page header
1.575.2.1! foxr      555:         my $testPrintout =
        !           556:           '\\\\' . &mt('Construction Space') . ' \\\\' . &mt('Test-Printout ');
1.538     onken     557:         $format =~ s/\\\\\s\\\\\s/$testPrintout/;
                    558:     }
1.575.2.1! foxr      559: 
1.565     foxr      560:     #
                    561:     #  We're going to trust LaTeX to break lines appropriately, but
                    562:     #  we'll truncate anything that's more than 3 lines worth of
                    563:     # text.  This is also assuming (which will probably end badly)
                    564:     # nobody's going to embed LaTeX control sequences in the title
                    565:     # header or rather that those control sequences won't get broken
                    566:     # by the stuff below.
                    567:     #
1.575.2.1! foxr      568:     my $total_length = 3 * $chars_per_line;
        !           569:     if ( length($format) > $total_length ) {
        !           570:         $format = substr( $format, 0, $total_length );
1.565     foxr      571:     }
                    572: 
1.454     foxr      573:     return $format;
1.575.2.1! foxr      574: 
1.454     foxr      575: }
1.397     albertel  576: 
1.385     foxr      577: #
                    578: #   Convert a numeric code to letters
                    579: #
                    580: sub num_to_letters {
                    581:     my ($num) = @_;
1.575.2.1! foxr      582:     my @nums = split( '', $num );
        !           583:     my @num_to_let = ( 'A' .. 'Z' );
1.385     foxr      584:     my $word;
1.575.2.1! foxr      585:     foreach my $digit (@nums) { $word .= $num_to_let[$digit]; }
1.385     foxr      586:     return $word;
                    587: }
1.575.2.1! foxr      588: 
1.385     foxr      589: #   Convert a letter code to numeric.
                    590: #
                    591: sub letters_to_num {
                    592:     my ($letters) = @_;
1.575.2.1! foxr      593:     my @letters = split( '', uc($letters) );
        !           594:     my %substitution;
1.385     foxr      595:     my $digit = 0;
1.575.2.1! foxr      596:     foreach my $letter ( 'A' .. 'J' ) {
        !           597:         $substitution{$letter} = $digit;
        !           598:         $digit++;
1.385     foxr      599:     }
1.575.2.1! foxr      600: 
1.385     foxr      601:     #  The substitution is done as below to preserve leading
                    602:     #  zeroes which are needed to keep the code size exact
                    603:     #
1.575.2.1! foxr      604:     my $result = "";
1.385     foxr      605:     foreach my $letter (@letters) {
1.575.2.1! foxr      606:         $result .= $substitution{$letter};
1.385     foxr      607:     }
                    608:     return $result;
                    609: }
                    610: 
1.383     foxr      611: #  Determine if a code is a valid numeric code.  Valid
                    612: #  numeric codes must be comprised entirely of digits and
1.384     albertel  613: #  have a correct number of digits.
1.383     foxr      614: #
                    615: #  Parameters:
                    616: #     value      - proposed code value.
1.384     albertel  617: #     num_digits - Number of digits required.
1.383     foxr      618: #
                    619: sub is_valid_numeric_code {
1.575.2.1! foxr      620:     my ( $value, $num_digits ) = @_;
        !           621: 
1.383     foxr      622:     #   Remove leading/trailing whitespace;
1.387     foxr      623:     $value =~ s/^\s*//g;
                    624:     $value =~ s/\s*$//g;
1.575.2.1! foxr      625: 
1.383     foxr      626:     #  All digits?
1.575.2.1! foxr      627:     if ( $value !~ /^[0-9]+$/ ) {
        !           628:         return
        !           629:           "Numeric code $value has invalid characters - must only be digits";
        !           630:     }
        !           631:     if ( length($value) != $num_digits ) {
        !           632:         return
        !           633: "Numeric code $value incorrect number of digits (correct = $num_digits)";
1.384     albertel  634:     }
1.385     foxr      635:     return undef;
1.383     foxr      636: }
1.575.2.1! foxr      637: 
1.383     foxr      638: #   Determines if a code is a valid alhpa code.  Alpha codes
                    639: #   are ciphers that map  [A-J,a-j] -> 0..9 0..9.
1.384     albertel  640: #   They also have a correct digit count.
1.383     foxr      641: # Parameters:
                    642: #     value          - Proposed code value.
1.384     albertel  643: #     num_letters    - correct number of letters.
1.383     foxr      644: # Note:
                    645: #    leading and trailing whitespace are ignored.
                    646: #
                    647: sub is_valid_alpha_code {
1.575.2.1! foxr      648:     my ( $value, $num_letters ) = @_;
        !           649: 
        !           650:     # strip leading and trailing spaces.
1.383     foxr      651: 
                    652:     $value =~ s/^\s*//g;
                    653:     $value =~ s/\s*$//g;
                    654: 
                    655:     #  All alphas in the right range?
1.575.2.1! foxr      656:     if ( $value !~ /^[A-J,a-j]+$/ ) {
        !           657:         return "Invalid letter code $value must only contain A-J";
1.383     foxr      658:     }
1.575.2.1! foxr      659:     if ( length($value) != $num_letters ) {
        !           660:         return
        !           661: "Letter code $value has incorrect number of letters (correct = $num_letters)";
1.384     albertel  662:     }
1.385     foxr      663:     return undef;
1.383     foxr      664: }
                    665: 
1.382     foxr      666: #   Determine if a code entered by the user in a helper is valid.
                    667: #   valid depends on the code type and the type of code selected.
1.575.2.1! foxr      668: #   The type of code selected can either be numeric or
1.382     foxr      669: #   Alphabetic.  If alphabetic, the code, in fact is a simple
                    670: #   substitution cipher for the actual numeric code: 0->A, 1->B ...
                    671: #   We'll be nice and be case insensitive for alpha codes.
                    672: # Parameters:
                    673: #    code_value    - the value of the code the user typed in.
                    674: #    code_option   - The code type selected from the set in the scantron format
                    675: #                    table.
                    676: # Returns:
                    677: #    undef         - The code is valid.
                    678: #    other         - An error message indicating what's wrong.
                    679: #
                    680: sub is_code_valid {
1.575.2.1! foxr      681:     my ( $code_value, $code_option ) = @_;
        !           682:     my ( $code_type, $code_length ) = ( 'letter', 6 );    # defaults.
1.542     raeburn   683:     my @lines = &Apache::grades::get_scantronformat_file();
                    684:     foreach my $line (@lines) {
1.575.2.1! foxr      685:         my ( $name, $type, $length ) = ( split( /:/, $line ) )[ 0, 2, 4 ];
        !           686:         if ( $name eq $code_option ) {
        !           687:             $code_length = $length;
        !           688:             if ( $type eq 'number' ) {
        !           689:                 $code_type = 'number';
        !           690:             }
        !           691:         }
1.383     foxr      692:     }
                    693:     my $valid;
1.575.2.1! foxr      694:     if ( $code_type eq 'number' ) {
        !           695:         return &is_valid_numeric_code( $code_value, $code_length );
        !           696:     }
        !           697:     else {
        !           698:         return &is_valid_alpha_code( $code_value, $code_length );
1.383     foxr      699:     }
1.382     foxr      700: 
                    701: }
                    702: 
1.341     foxr      703: #   Compare two students by name.  The students are in the form
                    704: #   returned by the helper:
                    705: #      user:domain:section:last,   first:status
                    706: #   This is a helper function for the perl sort built-in  therefore:
                    707: # Implicit Inputs:
                    708: #    $a     - The first element to compare (global)
                    709: #    $b     - The second element to compare (global)
                    710: # Returns:
                    711: #   -1   - $a < $b
                    712: #    0   - $a == $b
                    713: #   +1   - $a > $b
                    714: #   Note that the initial comparison is done on the last names with the
                    715: #   first names only used to break the tie.
                    716: #
                    717: #
                    718: sub compare_names {
1.575.2.1! foxr      719: 
1.341     foxr      720:     #  First split the names up into the primary fields.
                    721: 
1.575.2.1! foxr      722:     my ( $u1, $d1, $s1, $n1, $stat1 ) = split( /:/, $a );
        !           723:     my ( $u2, $d2, $s2, $n2, $stat2 ) = split( /:/, $b );
1.341     foxr      724: 
                    725:     # Now split the last name and first name of each n:
                    726:     #
                    727: 
1.575.2.1! foxr      728:     my ( $l1, $f1 ) = split( /,/, $n1 );
        !           729:     my ( $l2, $f2 ) = split( /,/, $n2 );
1.341     foxr      730: 
                    731:     # We don't bother to remove the leading/trailing whitespace from the
                    732:     # firstname, unless the last names compare identical.
                    733: 
1.575.2.1! foxr      734:     if ( $l1 lt $l2 ) {
        !           735:         return -1;
1.341     foxr      736:     }
1.575.2.1! foxr      737:     if ( $l1 gt $l2 ) {
        !           738:         return 1;
1.341     foxr      739:     }
                    740: 
                    741:     # Break the tie on the first name, but there are leading (possibly trailing
1.575.2.1! foxr      742:     # whitespaces to get rid of first
1.341     foxr      743:     #
1.575.2.1! foxr      744:     $f1 =~ s/^\s+//;    # Remove leading...
        !           745:     $f1 =~ s/\s+$//;    # Trailing spaces from first 1...
        !           746: 
1.341     foxr      747:     $f2 =~ s/^\s+//;
1.575.2.1! foxr      748:     $f2 =~ s/\s+$//;    # And the same for first 2...
1.341     foxr      749: 
1.575.2.1! foxr      750:     if ( $f1 lt $f2 ) {
        !           751:         return -1;
1.341     foxr      752:     }
1.575.2.1! foxr      753:     if ( $f1 gt $f2 ) {
        !           754:         return 1;
1.341     foxr      755:     }
1.575.2.1! foxr      756: 
1.341     foxr      757:     #  Must be the same name.
                    758: 
                    759:     return 0;
                    760: }
                    761: 
1.71      sakharuk  762: sub latex_header_footer_remove {
                    763:     my $text = shift;
                    764:     $text =~ s/\\end{document}//;
                    765:     $text =~ s/\\documentclass([^&]*)\\begin{document}//;
                    766:     return $text;
                    767: }
1.575.2.1! foxr      768: 
1.423     foxr      769: #
1.575.2.1! foxr      770: #  If necessary, encapsulate text inside
1.423     foxr      771: #  a minipage env.
                    772: #  necessity is determined by the problem_split param.
                    773: #
                    774: sub encapsulate_minipage {
                    775:     my ($text) = @_;
1.575.2.1! foxr      776:     if ( !( $env{'form.problem.split'} =~ /yes/i ) ) {
        !           777:         $text = '\begin{minipage}{\textwidth}' . $text . '\end{minipage}';
1.423     foxr      778:     }
                    779:     return $text;
                    780: }
1.575.2.1! foxr      781: 
1.429     foxr      782: #
                    783: #  The NUMBER_TO_PRINT and SPLIT_PDFS
                    784: #  variables interact, this sub looks at these two parameters
                    785: #  and comes up with a final value for NUMBER_TO_PRINT which can be:
                    786: #     all     - if SPLIT_PDFS eq 'all'.
                    787: #     1       - if SPLIT_PDFS eq 'oneper'
                    788: #     section - if SPLIT_PDFS eq 'sections'
                    789: #     <unchanged> - if SPLIT_PDFS eq 'usenumber'
                    790: #
                    791: sub adjust_number_to_print {
                    792:     my $helper = shift;
1.71      sakharuk  793: 
1.429     foxr      794:     my $split_pdf = $helper->{'VARS'}->{'SPLIT_PDFS'};
                    795: 
1.575.2.1! foxr      796:     if ( $split_pdf eq 'all' ) {
        !           797:         $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 'all';
1.429     foxr      798:     }
1.575.2.1! foxr      799:     elsif ( $split_pdf eq 'oneper' ) {
        !           800:         $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 1;
        !           801:     }
        !           802:     elsif ( $split_pdf eq 'sections' ) {
        !           803:         $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 'section';
        !           804:     }
        !           805:     elsif ( $split_pdf eq 'usenumber' ) {
        !           806: 
        !           807:         #  Unmodified.
        !           808:     }
        !           809:     else {
1.71      sakharuk  810: 
1.575.2.1! foxr      811:         # Error!!!!
        !           812: 
        !           813:         croak
        !           814:           "bad SPLIT_PDFS: $split_pdf in lonprintout::adjust_number_to_print";
        !           815: 
        !           816:     }
        !           817: }
1.531     foxr      818: 
1.37      sakharuk  819: sub character_chart {
1.531     foxr      820:     my $result = shift;
1.575.2.1! foxr      821:     return &Apache::entities::replace_entities($result);
1.531     foxr      822: }
                    823: 
                    824: sub old_character_chart {
1.575.2.1! foxr      825:     my $result = shift;
1.116     sakharuk  826:     $result =~ s/&\#0?0?(7|9);//g;
                    827:     $result =~ s/&\#0?(10|13);//g;
                    828:     $result =~ s/&\#0?32;/ /g;
                    829:     $result =~ s/&\#0?33;/!/g;
                    830:     $result =~ s/&(\#0?34|quot);/\"/g;
                    831:     $result =~ s/&\#0?35;/\\\#/g;
                    832:     $result =~ s/&\#0?36;/\\\$/g;
1.575.2.1! foxr      833:     $result =~ s/&\#0?37;/\\%/g;
        !           834:     $result =~ s/&(\#0?38|amp);/\\&/g;
1.116     sakharuk  835:     $result =~ s/&\#(0?39|146);/\'/g;
                    836:     $result =~ s/&\#0?40;/(/g;
                    837:     $result =~ s/&\#0?41;/)/g;
                    838:     $result =~ s/&\#0?42;/\*/g;
                    839:     $result =~ s/&\#0?43;/\+/g;
                    840:     $result =~ s/&\#(0?44|130);/,/g;
                    841:     $result =~ s/&\#0?45;/-/g;
                    842:     $result =~ s/&\#0?46;/\./g;
                    843:     $result =~ s/&\#0?47;/\//g;
                    844:     $result =~ s/&\#0?48;/0/g;
                    845:     $result =~ s/&\#0?49;/1/g;
                    846:     $result =~ s/&\#0?50;/2/g;
                    847:     $result =~ s/&\#0?51;/3/g;
                    848:     $result =~ s/&\#0?52;/4/g;
                    849:     $result =~ s/&\#0?53;/5/g;
                    850:     $result =~ s/&\#0?54;/6/g;
                    851:     $result =~ s/&\#0?55;/7/g;
                    852:     $result =~ s/&\#0?56;/8/g;
                    853:     $result =~ s/&\#0?57;/9/g;
1.269     albertel  854:     $result =~ s/&\#0?58;/:/g;
1.116     sakharuk  855:     $result =~ s/&\#0?59;/;/g;
                    856:     $result =~ s/&(\#0?60|lt|\#139);/\$<\$/g;
1.281     sakharuk  857:     $result =~ s/&\#0?61;/\\ensuremath\{=\}/g;
                    858:     $result =~ s/&(\#0?62|gt|\#155);/\\ensuremath\{>\}/g;
1.116     sakharuk  859:     $result =~ s/&\#0?63;/\?/g;
                    860:     $result =~ s/&\#0?65;/A/g;
                    861:     $result =~ s/&\#0?66;/B/g;
                    862:     $result =~ s/&\#0?67;/C/g;
                    863:     $result =~ s/&\#0?68;/D/g;
                    864:     $result =~ s/&\#0?69;/E/g;
                    865:     $result =~ s/&\#0?70;/F/g;
                    866:     $result =~ s/&\#0?71;/G/g;
                    867:     $result =~ s/&\#0?72;/H/g;
                    868:     $result =~ s/&\#0?73;/I/g;
                    869:     $result =~ s/&\#0?74;/J/g;
                    870:     $result =~ s/&\#0?75;/K/g;
                    871:     $result =~ s/&\#0?76;/L/g;
                    872:     $result =~ s/&\#0?77;/M/g;
                    873:     $result =~ s/&\#0?78;/N/g;
                    874:     $result =~ s/&\#0?79;/O/g;
                    875:     $result =~ s/&\#0?80;/P/g;
                    876:     $result =~ s/&\#0?81;/Q/g;
                    877:     $result =~ s/&\#0?82;/R/g;
                    878:     $result =~ s/&\#0?83;/S/g;
                    879:     $result =~ s/&\#0?84;/T/g;
                    880:     $result =~ s/&\#0?85;/U/g;
                    881:     $result =~ s/&\#0?86;/V/g;
                    882:     $result =~ s/&\#0?87;/W/g;
                    883:     $result =~ s/&\#0?88;/X/g;
                    884:     $result =~ s/&\#0?89;/Y/g;
                    885:     $result =~ s/&\#0?90;/Z/g;
                    886:     $result =~ s/&\#0?91;/[/g;
1.281     sakharuk  887:     $result =~ s/&\#0?92;/\\ensuremath\{\\setminus\}/g;
1.116     sakharuk  888:     $result =~ s/&\#0?93;/]/g;
1.281     sakharuk  889:     $result =~ s/&\#(0?94|136);/\\ensuremath\{\\wedge\}/g;
1.116     sakharuk  890:     $result =~ s/&\#(0?95|138|154);/\\underline{\\makebox[2mm]{\\strut}}/g;
                    891:     $result =~ s/&\#(0?96|145);/\`/g;
                    892:     $result =~ s/&\#0?97;/a/g;
                    893:     $result =~ s/&\#0?98;/b/g;
                    894:     $result =~ s/&\#0?99;/c/g;
                    895:     $result =~ s/&\#100;/d/g;
                    896:     $result =~ s/&\#101;/e/g;
                    897:     $result =~ s/&\#102;/f/g;
                    898:     $result =~ s/&\#103;/g/g;
                    899:     $result =~ s/&\#104;/h/g;
                    900:     $result =~ s/&\#105;/i/g;
                    901:     $result =~ s/&\#106;/j/g;
                    902:     $result =~ s/&\#107;/k/g;
                    903:     $result =~ s/&\#108;/l/g;
                    904:     $result =~ s/&\#109;/m/g;
                    905:     $result =~ s/&\#110;/n/g;
                    906:     $result =~ s/&\#111;/o/g;
                    907:     $result =~ s/&\#112;/p/g;
                    908:     $result =~ s/&\#113;/q/g;
                    909:     $result =~ s/&\#114;/r/g;
                    910:     $result =~ s/&\#115;/s/g;
                    911:     $result =~ s/&\#116;/t/g;
                    912:     $result =~ s/&\#117;/u/g;
                    913:     $result =~ s/&\#118;/v/g;
                    914:     $result =~ s/&\#119;/w/g;
                    915:     $result =~ s/&\#120;/x/g;
                    916:     $result =~ s/&\#121;/y/g;
                    917:     $result =~ s/&\#122;/z/g;
                    918:     $result =~ s/&\#123;/\\{/g;
                    919:     $result =~ s/&\#124;/\|/g;
                    920:     $result =~ s/&\#125;/\\}/g;
                    921:     $result =~ s/&\#126;/\~/g;
                    922:     $result =~ s/&\#131;/\\textflorin /g;
                    923:     $result =~ s/&\#132;/\"/g;
1.281     sakharuk  924:     $result =~ s/&\#133;/\\ensuremath\{\\ldots\}/g;
                    925:     $result =~ s/&\#134;/\\ensuremath\{\\dagger\}/g;
                    926:     $result =~ s/&\#135;/\\ensuremath\{\\ddagger\}/g;
1.116     sakharuk  927:     $result =~ s/&\#137;/\\textperthousand /g;
                    928:     $result =~ s/&\#140;/{\\OE}/g;
                    929:     $result =~ s/&\#147;/\`\`/g;
                    930:     $result =~ s/&\#148;/\'\'/g;
1.281     sakharuk  931:     $result =~ s/&\#149;/\\ensuremath\{\\bullet\}/g;
1.494     albertel  932:     $result =~ s/&(\#150|\#8211);/--/g;
1.116     sakharuk  933:     $result =~ s/&\#151;/---/g;
1.281     sakharuk  934:     $result =~ s/&\#152;/\\ensuremath\{\\sim\}/g;
1.116     sakharuk  935:     $result =~ s/&\#153;/\\texttrademark /g;
                    936:     $result =~ s/&\#156;/\\oe/g;
                    937:     $result =~ s/&\#159;/\\\"Y/g;
1.283     albertel  938:     $result =~ s/&(\#160|nbsp);/~/g;
1.116     sakharuk  939:     $result =~ s/&(\#161|iexcl);/!\`/g;
                    940:     $result =~ s/&(\#162|cent);/\\textcent /g;
1.575.2.1! foxr      941:     $result =~ s/&(\#163|pound);/\\pounds /g;
1.116     sakharuk  942:     $result =~ s/&(\#164|curren);/\\textcurrency /g;
                    943:     $result =~ s/&(\#165|yen);/\\textyen /g;
                    944:     $result =~ s/&(\#166|brvbar);/\\textbrokenbar /g;
                    945:     $result =~ s/&(\#167|sect);/\\textsection /g;
1.530     foxr      946:     $result =~ s/&(\#168|uml);/\\"\{\} /g;
1.116     sakharuk  947:     $result =~ s/&(\#169|copy);/\\copyright /g;
                    948:     $result =~ s/&(\#170|ordf);/\\textordfeminine /g;
1.281     sakharuk  949:     $result =~ s/&(\#172|not);/\\ensuremath\{\\neg\}/g;
1.116     sakharuk  950:     $result =~ s/&(\#173|shy);/ - /g;
                    951:     $result =~ s/&(\#174|reg);/\\textregistered /g;
1.281     sakharuk  952:     $result =~ s/&(\#175|macr);/\\ensuremath\{^{-}\}/g;
                    953:     $result =~ s/&(\#176|deg);/\\ensuremath\{^{\\circ}\}/g;
                    954:     $result =~ s/&(\#177|plusmn);/\\ensuremath\{\\pm\}/g;
                    955:     $result =~ s/&(\#178|sup2);/\\ensuremath\{^2\}/g;
                    956:     $result =~ s/&(\#179|sup3);/\\ensuremath\{^3\}/g;
1.530     foxr      957:     $result =~ s/&(\#180|acute);/\\'\{\} /g;
1.281     sakharuk  958:     $result =~ s/&(\#181|micro);/\\ensuremath\{\\mu\}/g;
1.116     sakharuk  959:     $result =~ s/&(\#182|para);/\\P/g;
1.281     sakharuk  960:     $result =~ s/&(\#183|middot);/\\ensuremath\{\\cdot\}/g;
1.116     sakharuk  961:     $result =~ s/&(\#184|cedil);/\\c{\\strut}/g;
1.281     sakharuk  962:     $result =~ s/&(\#185|sup1);/\\ensuremath\{^1\}/g;
1.116     sakharuk  963:     $result =~ s/&(\#186|ordm);/\\textordmasculine /g;
                    964:     $result =~ s/&(\#188|frac14);/\\textonequarter /g;
                    965:     $result =~ s/&(\#189|frac12);/\\textonehalf /g;
                    966:     $result =~ s/&(\#190|frac34);/\\textthreequarters /g;
1.575.2.1! foxr      967:     $result =~ s/&(\#191|iquest);/?\`/g;
        !           968:     $result =~ s/&(\#192|Agrave);/\\\`{A}/g;
        !           969:     $result =~ s/&(\#193|Aacute);/\\\'{A}/g;
1.116     sakharuk  970:     $result =~ s/&(\#194|Acirc);/\\^{A}/g;
                    971:     $result =~ s/&(\#195|Atilde);/\\~{A}/g;
1.575.2.1! foxr      972:     $result =~ s/&(\#196|Auml);/\\\"{A}/g;
1.116     sakharuk  973:     $result =~ s/&(\#197|Aring);/{\\AA}/g;
                    974:     $result =~ s/&(\#198|AElig);/{\\AE}/g;
                    975:     $result =~ s/&(\#199|Ccedil);/\\c{c}/g;
1.575.2.1! foxr      976:     $result =~ s/&(\#200|Egrave);/\\\`{E}/g;
        !           977:     $result =~ s/&(\#201|Eacute);/\\\'{E}/g;
1.116     sakharuk  978:     $result =~ s/&(\#202|Ecirc);/\\^{E}/g;
                    979:     $result =~ s/&(\#203|Euml);/\\\"{E}/g;
                    980:     $result =~ s/&(\#204|Igrave);/\\\`{I}/g;
1.575.2.1! foxr      981:     $result =~ s/&(\#205|Iacute);/\\\'{I}/g;
1.116     sakharuk  982:     $result =~ s/&(\#206|Icirc);/\\^{I}/g;
1.575.2.1! foxr      983:     $result =~ s/&(\#207|Iuml);/\\\"{I}/g;
1.116     sakharuk  984:     $result =~ s/&(\#209|Ntilde);/\\~{N}/g;
                    985:     $result =~ s/&(\#210|Ograve);/\\\`{O}/g;
                    986:     $result =~ s/&(\#211|Oacute);/\\\'{O}/g;
                    987:     $result =~ s/&(\#212|Ocirc);/\\^{O}/g;
                    988:     $result =~ s/&(\#213|Otilde);/\\~{O}/g;
1.575.2.1! foxr      989:     $result =~ s/&(\#214|Ouml);/\\\"{O}/g;
1.281     sakharuk  990:     $result =~ s/&(\#215|times);/\\ensuremath\{\\times\}/g;
1.116     sakharuk  991:     $result =~ s/&(\#216|Oslash);/{\\O}/g;
1.575.2.1! foxr      992:     $result =~ s/&(\#217|Ugrave);/\\\`{U}/g;
1.116     sakharuk  993:     $result =~ s/&(\#218|Uacute);/\\\'{U}/g;
                    994:     $result =~ s/&(\#219|Ucirc);/\\^{U}/g;
                    995:     $result =~ s/&(\#220|Uuml);/\\\"{U}/g;
                    996:     $result =~ s/&(\#221|Yacute);/\\\'{Y}/g;
1.329     sakharuk  997:     $result =~ s/&(\#223|szlig);/{\\ss}/g;
1.116     sakharuk  998:     $result =~ s/&(\#224|agrave);/\\\`{a}/g;
                    999:     $result =~ s/&(\#225|aacute);/\\\'{a}/g;
                   1000:     $result =~ s/&(\#226|acirc);/\\^{a}/g;
                   1001:     $result =~ s/&(\#227|atilde);/\\~{a}/g;
                   1002:     $result =~ s/&(\#228|auml);/\\\"{a}/g;
                   1003:     $result =~ s/&(\#229|aring);/{\\aa}/g;
                   1004:     $result =~ s/&(\#230|aelig);/{\\ae}/g;
                   1005:     $result =~ s/&(\#231|ccedil);/\\c{c}/g;
                   1006:     $result =~ s/&(\#232|egrave);/\\\`{e}/g;
                   1007:     $result =~ s/&(\#233|eacute);/\\\'{e}/g;
                   1008:     $result =~ s/&(\#234|ecirc);/\\^{e}/g;
                   1009:     $result =~ s/&(\#235|euml);/\\\"{e}/g;
                   1010:     $result =~ s/&(\#236|igrave);/\\\`{i}/g;
                   1011:     $result =~ s/&(\#237|iacute);/\\\'{i}/g;
                   1012:     $result =~ s/&(\#238|icirc);/\\^{i}/g;
                   1013:     $result =~ s/&(\#239|iuml);/\\\"{i}/g;
1.281     sakharuk 1014:     $result =~ s/&(\#240|eth);/\\ensuremath\{\\partial\}/g;
1.116     sakharuk 1015:     $result =~ s/&(\#241|ntilde);/\\~{n}/g;
                   1016:     $result =~ s/&(\#242|ograve);/\\\`{o}/g;
                   1017:     $result =~ s/&(\#243|oacute);/\\\'{o}/g;
                   1018:     $result =~ s/&(\#244|ocirc);/\\^{o}/g;
                   1019:     $result =~ s/&(\#245|otilde);/\\~{o}/g;
                   1020:     $result =~ s/&(\#246|ouml);/\\\"{o}/g;
1.281     sakharuk 1021:     $result =~ s/&(\#247|divide);/\\ensuremath\{\\div\}/g;
1.116     sakharuk 1022:     $result =~ s/&(\#248|oslash);/{\\o}/g;
1.575.2.1! foxr     1023:     $result =~ s/&(\#249|ugrave);/\\\`{u}/g;
1.116     sakharuk 1024:     $result =~ s/&(\#250|uacute);/\\\'{u}/g;
                   1025:     $result =~ s/&(\#251|ucirc);/\\^{u}/g;
                   1026:     $result =~ s/&(\#252|uuml);/\\\"{u}/g;
                   1027:     $result =~ s/&(\#253|yacute);/\\\'{y}/g;
                   1028:     $result =~ s/&(\#255|yuml);/\\\"{y}/g;
1.399     albertel 1029:     $result =~ s/&\#295;/\\ensuremath\{\\hbar\}/g;
1.281     sakharuk 1030:     $result =~ s/&\#952;/\\ensuremath\{\\theta\}/g;
1.575.2.1! foxr     1031: 
        !          1032:     #Greek Alphabet
1.281     sakharuk 1033:     $result =~ s/&(alpha|\#945);/\\ensuremath\{\\alpha\}/g;
                   1034:     $result =~ s/&(beta|\#946);/\\ensuremath\{\\beta\}/g;
                   1035:     $result =~ s/&(gamma|\#947);/\\ensuremath\{\\gamma\}/g;
                   1036:     $result =~ s/&(delta|\#948);/\\ensuremath\{\\delta\}/g;
                   1037:     $result =~ s/&(epsilon|\#949);/\\ensuremath\{\\epsilon\}/g;
                   1038:     $result =~ s/&(zeta|\#950);/\\ensuremath\{\\zeta\}/g;
                   1039:     $result =~ s/&(eta|\#951);/\\ensuremath\{\\eta\}/g;
                   1040:     $result =~ s/&(theta|\#952);/\\ensuremath\{\\theta\}/g;
                   1041:     $result =~ s/&(iota|\#953);/\\ensuremath\{\\iota\}/g;
                   1042:     $result =~ s/&(kappa|\#954);/\\ensuremath\{\\kappa\}/g;
                   1043:     $result =~ s/&(lambda|\#955);/\\ensuremath\{\\lambda\}/g;
                   1044:     $result =~ s/&(mu|\#956);/\\ensuremath\{\\mu\}/g;
                   1045:     $result =~ s/&(nu|\#957);/\\ensuremath\{\\nu\}/g;
                   1046:     $result =~ s/&(xi|\#958);/\\ensuremath\{\\xi\}/g;
1.199     sakharuk 1047:     $result =~ s/&(omicron|\#959);/o/g;
1.281     sakharuk 1048:     $result =~ s/&(pi|\#960);/\\ensuremath\{\\pi\}/g;
                   1049:     $result =~ s/&(rho|\#961);/\\ensuremath\{\\rho\}/g;
                   1050:     $result =~ s/&(sigma|\#963);/\\ensuremath\{\\sigma\}/g;
                   1051:     $result =~ s/&(tau|\#964);/\\ensuremath\{\\tau\}/g;
                   1052:     $result =~ s/&(upsilon|\#965);/\\ensuremath\{\\upsilon\}/g;
                   1053:     $result =~ s/&(phi|\#966);/\\ensuremath\{\\phi\}/g;
                   1054:     $result =~ s/&(chi|\#967);/\\ensuremath\{\\chi\}/g;
                   1055:     $result =~ s/&(psi|\#968);/\\ensuremath\{\\psi\}/g;
                   1056:     $result =~ s/&(omega|\#969);/\\ensuremath\{\\omega\}/g;
                   1057:     $result =~ s/&(thetasym|\#977);/\\ensuremath\{\\vartheta\}/g;
                   1058:     $result =~ s/&(piv|\#982);/\\ensuremath\{\\varpi\}/g;
1.199     sakharuk 1059:     $result =~ s/&(Alpha|\#913);/A/g;
                   1060:     $result =~ s/&(Beta|\#914);/B/g;
1.281     sakharuk 1061:     $result =~ s/&(Gamma|\#915);/\\ensuremath\{\\Gamma\}/g;
                   1062:     $result =~ s/&(Delta|\#916);/\\ensuremath\{\\Delta\}/g;
1.199     sakharuk 1063:     $result =~ s/&(Epsilon|\#917);/E/g;
                   1064:     $result =~ s/&(Zeta|\#918);/Z/g;
                   1065:     $result =~ s/&(Eta|\#919);/H/g;
1.281     sakharuk 1066:     $result =~ s/&(Theta|\#920);/\\ensuremath\{\\Theta\}/g;
1.199     sakharuk 1067:     $result =~ s/&(Iota|\#921);/I/g;
                   1068:     $result =~ s/&(Kappa|\#922);/K/g;
1.281     sakharuk 1069:     $result =~ s/&(Lambda|\#923);/\\ensuremath\{\\Lambda\}/g;
1.199     sakharuk 1070:     $result =~ s/&(Mu|\#924);/M/g;
                   1071:     $result =~ s/&(Nu|\#925);/N/g;
1.281     sakharuk 1072:     $result =~ s/&(Xi|\#926);/\\ensuremath\{\\Xi\}/g;
1.199     sakharuk 1073:     $result =~ s/&(Omicron|\#927);/O/g;
1.281     sakharuk 1074:     $result =~ s/&(Pi|\#928);/\\ensuremath\{\\Pi\}/g;
1.199     sakharuk 1075:     $result =~ s/&(Rho|\#929);/P/g;
1.281     sakharuk 1076:     $result =~ s/&(Sigma|\#931);/\\ensuremath\{\\Sigma\}/g;
1.199     sakharuk 1077:     $result =~ s/&(Tau|\#932);/T/g;
1.281     sakharuk 1078:     $result =~ s/&(Upsilon|\#933);/\\ensuremath\{\\Upsilon\}/g;
                   1079:     $result =~ s/&(Phi|\#934);/\\ensuremath\{\\Phi\}/g;
1.199     sakharuk 1080:     $result =~ s/&(Chi|\#935);/X/g;
1.281     sakharuk 1081:     $result =~ s/&(Psi|\#936);/\\ensuremath\{\\Psi\}/g;
                   1082:     $result =~ s/&(Omega|\#937);/\\ensuremath\{\\Omega\}/g;
1.575.2.1! foxr     1083: 
        !          1084:     #Arrows (extended HTML 4.01)
1.281     sakharuk 1085:     $result =~ s/&(larr|\#8592);/\\ensuremath\{\\leftarrow\}/g;
                   1086:     $result =~ s/&(uarr|\#8593);/\\ensuremath\{\\uparrow\}/g;
                   1087:     $result =~ s/&(rarr|\#8594);/\\ensuremath\{\\rightarrow\}/g;
                   1088:     $result =~ s/&(darr|\#8595);/\\ensuremath\{\\downarrow\}/g;
                   1089:     $result =~ s/&(harr|\#8596);/\\ensuremath\{\\leftrightarrow\}/g;
                   1090:     $result =~ s/&(lArr|\#8656);/\\ensuremath\{\\Leftarrow\}/g;
                   1091:     $result =~ s/&(uArr|\#8657);/\\ensuremath\{\\Uparrow\}/g;
                   1092:     $result =~ s/&(rArr|\#8658);/\\ensuremath\{\\Rightarrow\}/g;
                   1093:     $result =~ s/&(dArr|\#8659);/\\ensuremath\{\\Downarrow\}/g;
                   1094:     $result =~ s/&(hArr|\#8660);/\\ensuremath\{\\Leftrightarrow\}/g;
1.575.2.1! foxr     1095: 
        !          1096:     #Mathematical Operators (extended HTML 4.01)
1.281     sakharuk 1097:     $result =~ s/&(forall|\#8704);/\\ensuremath\{\\forall\}/g;
                   1098:     $result =~ s/&(part|\#8706);/\\ensuremath\{\\partial\}/g;
                   1099:     $result =~ s/&(exist|\#8707);/\\ensuremath\{\\exists\}/g;
                   1100:     $result =~ s/&(empty|\#8709);/\\ensuremath\{\\emptyset\}/g;
                   1101:     $result =~ s/&(nabla|\#8711);/\\ensuremath\{\\nabla\}/g;
                   1102:     $result =~ s/&(isin|\#8712);/\\ensuremath\{\\in\}/g;
                   1103:     $result =~ s/&(notin|\#8713);/\\ensuremath\{\\notin\}/g;
                   1104:     $result =~ s/&(ni|\#8715);/\\ensuremath\{\\ni\}/g;
                   1105:     $result =~ s/&(prod|\#8719);/\\ensuremath\{\\prod\}/g;
                   1106:     $result =~ s/&(sum|\#8721);/\\ensuremath\{\\sum\}/g;
                   1107:     $result =~ s/&(minus|\#8722);/\\ensuremath\{-\}/g;
1.390     albertel 1108:     $result =~ s/–/\\ensuremath\{-\}/g;
1.281     sakharuk 1109:     $result =~ s/&(lowast|\#8727);/\\ensuremath\{*\}/g;
                   1110:     $result =~ s/&(radic|\#8730);/\\ensuremath\{\\surd\}/g;
                   1111:     $result =~ s/&(prop|\#8733);/\\ensuremath\{\\propto\}/g;
                   1112:     $result =~ s/&(infin|\#8734);/\\ensuremath\{\\infty\}/g;
                   1113:     $result =~ s/&(ang|\#8736);/\\ensuremath\{\\angle\}/g;
                   1114:     $result =~ s/&(and|\#8743);/\\ensuremath\{\\wedge\}/g;
                   1115:     $result =~ s/&(or|\#8744);/\\ensuremath\{\\vee\}/g;
                   1116:     $result =~ s/&(cap|\#8745);/\\ensuremath\{\\cap\}/g;
                   1117:     $result =~ s/&(cup|\#8746);/\\ensuremath\{\\cup\}/g;
                   1118:     $result =~ s/&(int|\#8747);/\\ensuremath\{\\int\}/g;
                   1119:     $result =~ s/&(sim|\#8764);/\\ensuremath\{\\sim\}/g;
                   1120:     $result =~ s/&(cong|\#8773);/\\ensuremath\{\\cong\}/g;
                   1121:     $result =~ s/&(asymp|\#8776);/\\ensuremath\{\\approx\}/g;
                   1122:     $result =~ s/&(ne|\#8800);/\\ensuremath\{\\not=\}/g;
                   1123:     $result =~ s/&(equiv|\#8801);/\\ensuremath\{\\equiv\}/g;
                   1124:     $result =~ s/&(le|\#8804);/\\ensuremath\{\\leq\}/g;
                   1125:     $result =~ s/&(ge|\#8805);/\\ensuremath\{\\geq\}/g;
                   1126:     $result =~ s/&(sub|\#8834);/\\ensuremath\{\\subset\}/g;
                   1127:     $result =~ s/&(sup|\#8835);/\\ensuremath\{\\supset\}/g;
                   1128:     $result =~ s/&(nsub|\#8836);/\\ensuremath\{\\not\\subset\}/g;
                   1129:     $result =~ s/&(sube|\#8838);/\\ensuremath\{\\subseteq\}/g;
                   1130:     $result =~ s/&(supe|\#8839);/\\ensuremath\{\\supseteq\}/g;
                   1131:     $result =~ s/&(oplus|\#8853);/\\ensuremath\{\\oplus\}/g;
                   1132:     $result =~ s/&(otimes|\#8855);/\\ensuremath\{\\otimes\}/g;
                   1133:     $result =~ s/&(perp|\#8869);/\\ensuremath\{\\perp\}/g;
                   1134:     $result =~ s/&(sdot|\#8901);/\\ensuremath\{\\cdot\}/g;
1.575.2.1! foxr     1135: 
        !          1136:     #Geometric Shapes (extended HTML 4.01)
1.281     sakharuk 1137:     $result =~ s/&(loz|\#9674);/\\ensuremath\{\\Diamond\}/g;
1.575.2.1! foxr     1138: 
        !          1139:     #Miscellaneous Symbols (extended HTML 4.01)
1.281     sakharuk 1140:     $result =~ s/&(spades|\#9824);/\\ensuremath\{\\spadesuit\}/g;
                   1141:     $result =~ s/&(clubs|\#9827);/\\ensuremath\{\\clubsuit\}/g;
                   1142:     $result =~ s/&(hearts|\#9829);/\\ensuremath\{\\heartsuit\}/g;
                   1143:     $result =~ s/&(diams|\#9830);/\\ensuremath\{\\diamondsuit\}/g;
1.575.2.1! foxr     1144: 
        !          1145:     #   Chemically useful 'things' contributed by Hon Kie (bug 4652).
1.515     foxr     1146: 
1.495     foxr     1147:     $result =~ s/&\#8636;/\\ensuremath\{\\leftharpoonup\}/g;
                   1148:     $result =~ s/&\#8637;/\\ensuremath\{\\leftharpoondown\}/g;
                   1149:     $result =~ s/&\#8640;/\\ensuremath\{\\rightharpoonup\}/g;
                   1150:     $result =~ s/&\#8641;/\\ensuremath\{\\rightharpoondown\}/g;
                   1151:     $result =~ s/&\#8652;/\\ensuremath\{\\rightleftharpoons\}/g;
                   1152:     $result =~ s/&\#8605;/\\ensuremath\{\\leadsto\}/g;
                   1153:     $result =~ s/&\#8617;/\\ensuremath\{\\hookleftarrow\}/g;
                   1154:     $result =~ s/&\#8618;/\\ensuremath\{\\hookrightarrow\}/g;
                   1155:     $result =~ s/&\#8614;/\\ensuremath\{\\mapsto\}/g;
                   1156:     $result =~ s/&\#8599;/\\ensuremath\{\\nearrow\}/g;
                   1157:     $result =~ s/&\#8600;/\\ensuremath\{\\searrow\}/g;
                   1158:     $result =~ s/&\#8601;/\\ensuremath\{\\swarrow\}/g;
                   1159:     $result =~ s/&\#8598;/\\ensuremath\{\\nwarrow\}/g;
1.513     foxr     1160: 
                   1161:     # Left/right quotations:
                   1162: 
                   1163:     $result =~ s/&(ldquo|#8220);/\`\`/g;
                   1164:     $result =~ s/&(rdquo|#8221);/\'\'/g;
                   1165: 
1.37      sakharuk 1166:     return $result;
                   1167: }
1.41      sakharuk 1168: 
1.575.2.1! foxr     1169: #width, height, oddsidemargin, evensidemargin, topmargin
        !          1170: my %page_formats = (
        !          1171:     'letter' => {
        !          1172:         'book' => {
        !          1173:             '1' => [ '7.1 in',  '9.8 in', '-0.57 in', '-0.57 in', '0.275 in' ],
        !          1174:             '2' => [ '3.66 in', '9.8 in', '-0.57 in', '-0.57 in', '0.275 in' ]
        !          1175:         },
        !          1176:         'album' => {
        !          1177:             '1' => [ '8.8 in', '6.8 in', '-0.55 in', '-0.55 in', '0.394 in' ],
        !          1178:             '2' => [ '4.8 in', '6.8 in', '-0.5 in',  '-1.0 in',  '3.5 in' ]
        !          1179:         },
        !          1180:     },
        !          1181:     'legal' => {
        !          1182:         'book' => {
        !          1183:             '1' => [ '7.1 in',  '13 in',, '-0.57 in', '-0.57 in', '-0.5 in' ],
        !          1184:             '2' => [ '3.66 in', '13 in',  '-0.57 in', '-0.57 in', '-0.5 in' ]
        !          1185:         },
        !          1186:         'album' => {
        !          1187:             '1' => [ '12 in',  '7.1 in',, '-0.57 in', '-0.57 in', '-0.5 in' ],
        !          1188:             '2' => [ '6.0 in', '7.1 in',  '-1 in',    '-1 in',    '5 in' ]
        !          1189:         },
        !          1190:     },
        !          1191:     'tabloid' => {
        !          1192:         'book' => {
        !          1193:             '1' => [ '9.8 in', '16 in', '-0.57 in', '-0.57 in', '-0.5 in' ],
        !          1194:             '2' => [ '4.9 in', '16 in', '-0.57 in', '-0.57 in', '-0.5 in' ]
        !          1195:         },
        !          1196:         'album' => {
        !          1197:             '1' => [ '16 in', '9.8 in', '-0.57 in', '-0.57 in', '-0.5 in' ],
        !          1198:             '2' => [ '16 in', '4.9 in', '-0.57 in', '-0.57 in', '-0.5 in' ]
        !          1199:         },
        !          1200:     },
        !          1201:     'executive' => {
        !          1202:         'book' => {
        !          1203:             '1' => [ '6.8 in', '9 in', '-0.57 in', '-0.57 in', '1.2 in' ],
        !          1204:             '2' => [ '3.1 in', '9 in', '-0.57 in', '-0.57 in', '1.2 in' ]
        !          1205:         },
        !          1206:         'album' => {
        !          1207:             '1' => [],
        !          1208:             '2' => []
        !          1209:         },
        !          1210:     },
        !          1211:     'a2' => {
        !          1212:         'book' => {
        !          1213:             '1' => [],
        !          1214:             '2' => []
        !          1215:         },
        !          1216:         'album' => {
        !          1217:             '1' => [],
        !          1218:             '2' => []
        !          1219:         },
        !          1220:     },
        !          1221:     'a3' => {
        !          1222:         'book' => {
        !          1223:             '1' => [],
        !          1224:             '2' => []
        !          1225:         },
        !          1226:         'album' => {
        !          1227:             '1' => [],
        !          1228:             '2' => []
        !          1229:         },
        !          1230:     },
        !          1231:     'a4' => {
        !          1232:         'book' => {
        !          1233:             '1' =>
        !          1234:               [ '17.6 cm', '27.2 cm', '-1.397 cm', '-2.11 cm', '-1.27 cm' ],
        !          1235:             '2' => [ '9.1 cm', '27.2 cm', '-1.397 cm', '-2.11 cm', '-1.27 cm' ]
        !          1236:         },
        !          1237:         'album' => {
        !          1238:             '1' => [ '21.59 cm', '19.558 cm', '-1.397cm',  '-2.11 cm', '0 cm' ],
        !          1239:             '2' => [ '9.91 cm',  '19.558 cm', '-1.397 cm', '-2.11 cm', '0 cm' ]
        !          1240:         },
        !          1241:     },
        !          1242:     'a5' => {
        !          1243:         'book' => {
        !          1244:             '1' => [],
        !          1245:             '2' => []
        !          1246:         },
        !          1247:         'album' => {
        !          1248:             '1' => [],
        !          1249:             '2' => []
        !          1250:         },
        !          1251:     },
        !          1252:     'a6' => {
        !          1253:         'book' => {
        !          1254:             '1' => [],
        !          1255:             '2' => []
        !          1256:         },
        !          1257:         'album' => {
        !          1258:             '1' => [],
        !          1259:             '2' => []
        !          1260:         },
        !          1261:     },
        !          1262: );
1.327     albertel 1263: 
1.177     sakharuk 1264: sub page_format {
1.575.2.1! foxr     1265: 
1.140     sakharuk 1266: #
1.326     sakharuk 1267: #Supported paper format: "Letter [8 1/2x11 in]",      "Legal [8 1/2x14 in]",
                   1268: #                        "Ledger/Tabloid [11x17 in]", "Executive [7 1/2x10 in]",
                   1269: #                        "A2 [420x594 mm]",           "A3 [297x420 mm]",
                   1270: #                        "A4 [210x297 mm]",           "A5 [148x210 mm]",
                   1271: #                        "A6 [105x148 mm]"
1.575.2.1! foxr     1272: #
        !          1273:     my ( $papersize, $layout, $numberofcolumns ) = @_;
        !          1274:     return @{ $page_formats{$papersize}->{$layout}->{$numberofcolumns} };
1.140     sakharuk 1275: }
1.76      sakharuk 1276: 
1.126     albertel 1277: sub get_name {
1.575.2.1! foxr     1278:     my ( $uname, $udom ) = @_;
        !          1279:     if ( !defined($uname) ) { $uname = $env{'user.name'}; }
        !          1280:     if ( !defined($udom) )  { $udom  = $env{'user.domain'}; }
        !          1281:     my $plainname = &Apache::loncommon::plainname( $uname, $udom );
        !          1282:     if ( $plainname =~ /^\s*$/ ) { $plainname = $uname . '@' . $udom; }
        !          1283:     $plainname = &Apache::lonxml::latex_special_symbols( $plainname, 'header' );
1.213     albertel 1284:     return $plainname;
1.126     albertel 1285: }
                   1286: 
1.213     albertel 1287: sub get_course {
                   1288:     my $courseidinfo;
1.575.2.1! foxr     1289:     if ( defined( $env{'request.course.id'} ) ) {
        !          1290:         $courseidinfo = &Apache::lonxml::latex_special_symbols(
        !          1291:             &unescape(
        !          1292:                 $env{ 'course.' . $env{'request.course.id'} . '.description' }
        !          1293:             ),
        !          1294:             'header'
        !          1295:         );
        !          1296:         my $sec = $env{'request.course.sec'};
        !          1297: 
1.213     albertel 1298:     }
                   1299:     return $courseidinfo;
                   1300: }
1.177     sakharuk 1301: 
1.76      sakharuk 1302: sub page_format_transformation {
1.575.2.1! foxr     1303:     my (
        !          1304:         $papersize,       $layout,    $numberofcolumns,
        !          1305:         $choice,          $text,      $assignment,
        !          1306:         $tableofcontents, $indexlist, $selectionmade
        !          1307:     ) = @_;
        !          1308:     my ( $textwidth, $textheight, $oddoffset, $evenoffset, $topmargin );
        !          1309: 
        !          1310:     if ( $selectionmade eq '4' ) {
        !          1311:         if ( $choice eq 'all_problems' ) {
        !          1312:             $assignment = &mt('Problems from the Whole Course');
        !          1313:         }
        !          1314:         else {
        !          1315:             $assignment = &mt('Resources from the Whole Course');
        !          1316:         }
1.312     sakharuk 1317:     }
1.575.2.1! foxr     1318:     else {
        !          1319:         $assignment =
        !          1320:           &Apache::lonxml::latex_special_symbols( $assignment, 'header' );
        !          1321:     }
        !          1322:     ( $textwidth, $textheight, $oddoffset, $evenoffset, $topmargin ) =
        !          1323:       &page_format( $papersize, $layout, $numberofcolumns, $topmargin );
1.454     foxr     1324: 
1.575.2.1! foxr     1325:     my $name         = &get_name();
1.213     albertel 1326:     my $courseidinfo = &get_course();
1.455     albertel 1327:     my $header_text  = $parmhash{'print_header_format'};
1.575.2.1! foxr     1328:     $header_text =
        !          1329:       &format_page_header( $textwidth, $header_text, $assignment, $courseidinfo,
        !          1330:         $name );
1.319     sakharuk 1331:     my $topmargintoinsert = '';
1.575.2.1! foxr     1332:     if ( $topmargin ne '0' ) {
        !          1333:         $topmargintoinsert = '\setlength{\topmargin}{' . $topmargin . '}';
        !          1334:     }
        !          1335:     my $fancypagestatement = '';
        !          1336:     if ( $numberofcolumns eq '2' ) {
        !          1337:         $fancypagestatement = "\\fancyhead{}\\fancyhead[LO]{$header_text}";
        !          1338:     }
        !          1339:     else {
        !          1340:         $fancypagestatement = "\\rhead{}\\chead{}\\lhead{$header_text}";
        !          1341:     }
        !          1342:     if ( $layout eq 'album' ) {
        !          1343:         $text =~
        !          1344: s/\\begin{document}/\\setlength{\\oddsidemargin}{$oddoffset}\\setlength{\\evensidemargin}{$evenoffset}$topmargintoinsert\n\\setlength{\\textwidth}{$textwidth}\\setlength{\\textheight}{$textheight}\\setlength{\\textfloatsep}{8pt plus 2\.0pt minus 4\.0pt}\n\\newlength{\\minipagewidth}\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\\usepackage{fancyhdr}\\addtolength{\\headheight}{\\baselineskip}\n\\pagestyle{fancy}$fancypagestatement\\usepackage{booktabs}\\begin{document}\\voffset=-0\.8 cm\\setcounter{page}{1}\n /;
        !          1345:     }
        !          1346:     elsif ( $layout eq 'book' ) {
        !          1347:         if ( $choice ne 'All class print' ) {
        !          1348:             $text =~
        !          1349: s/\\begin{document}/\\textheight $textheight\\oddsidemargin = $evenoffset\\evensidemargin = $evenoffset $topmargintoinsert\n\\textwidth= $textwidth\\newlength{\\minipagewidth}\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\n\\renewcommand{\\ref}{\\keephidden\}\\usepackage{fancyhdr}\\addtolength{\\headheight}{\\baselineskip}\\pagestyle{fancy}$fancypagestatement\\usepackage{booktabs}\\begin{document}\n\\voffset=-0\.8 cm\\setcounter{page}{1}\n/;
        !          1350:         }
        !          1351:         else {
        !          1352:             $text =~
        !          1353: s/\\pagestyle{fancy}\\rhead{}\\chead{}\s*\\begin{document}/\\textheight = $textheight\\oddsidemargin = $evenoffset\n\\evensidemargin = $evenoffset $topmargintoinsert\\textwidth= $textwidth\\newlength{\\minipagewidth}\n\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\\renewcommand{\\ref}{\\keephidden\}\\pagestyle{fancy}\\rhead{}\\chead{}\\usepackage{booktabs}\\begin{document}\\voffset=-0\.8cm\n\\setcounter{page}{1}  \\vskip 5 mm\n /;
        !          1354:         }
        !          1355:         if ( $papersize eq 'a4' ) {
        !          1356:             my $papersize_text;
        !          1357:             if ( $perm{'pav'} ) {
        !          1358:                 $papersize_text = '\\special{papersize=210mm,297mm}';
        !          1359:             }
        !          1360:             else {
        !          1361:                 $papersize_text = '\special{papersize=210mm,297mm}';
        !          1362:             }
        !          1363:             $text =~ s/(\\begin{document})/$1$papersize_text/;
        !          1364:         }
1.140     sakharuk 1365:     }
1.575.2.1! foxr     1366:     if ( $tableofcontents eq 'yes' ) {
        !          1367:         $text =~ s/(\\setcounter\{page\}\{1\})/$1 \\tableofcontents\\newpage /;
        !          1368:     }
        !          1369:     if ( $indexlist eq 'yes' ) {
        !          1370:         $text =~ s/(\\begin{document})/\\makeindex $1/;
        !          1371:         $text =~ s/(\\end{document})/\\strut\\\\\\strut\\printindex $1/;
1.214     sakharuk 1372:     }
1.140     sakharuk 1373:     return $text;
                   1374: }
                   1375: 
1.33      sakharuk 1376: sub page_cleanup {
1.575.2.1! foxr     1377:     my $result = shift;
        !          1378: 
1.65      sakharuk 1379:     $result =~ m/\\end{document}(\d*)$/;
1.34      sakharuk 1380:     my $number_of_columns = $1;
1.575.2.1! foxr     1381:     my $insert            = '{';
        !          1382:     for ( my $id = 1 ; $id <= $number_of_columns ; $id++ ) { $insert .= 'l'; }
1.33      sakharuk 1383:     $insert .= '}';
1.575.2.1! foxr     1384:     $result =~
        !          1385: s/(\\begin{longtable})INSERTTHEHEADOFLONGTABLE\\endfirsthead\\endhead/$1$insert/g;
1.34      sakharuk 1386:     $result =~ s/&\s*REMOVETHEHEADOFLONGTABLE\\\\/\\\\/g;
1.575.2.1! foxr     1387:     return $result, $number_of_columns;
1.7       sakharuk 1388: }
1.5       sakharuk 1389: 
1.60      sakharuk 1390: sub details_for_menu {
1.575.2.1! foxr     1391:     my ($helper) = @_;
        !          1392:     my $postdata = $env{'form.postdata'};
        !          1393:     if ( !$postdata ) { $postdata = $helper->{VARS}{'postdata'}; }
1.335     albertel 1394:     my $name_of_resource = &Apache::lonnet::gettitle($postdata);
1.575.2.1! foxr     1395:     my $symbolic         = &Apache::lonnet::symbread($postdata);
        !          1396:     return if ( $symbolic eq '' );
1.482     albertel 1397: 
1.575.2.1! foxr     1398:     my ( $map, $id, $resource ) = &Apache::lonnet::decode_symb($symbolic);
        !          1399:     $map = &Apache::lonnet::clutter($map);
1.269     albertel 1400:     my $name_of_sequence = &Apache::lonnet::gettitle($map);
1.575.2.1! foxr     1401:     if ( $name_of_sequence =~ /^\s*$/ ) {
        !          1402:         $map =~ m|([^/]+)$|;
        !          1403:         $name_of_sequence = $1;
        !          1404:     }
        !          1405:     my $name_of_map = &Apache::lonnet::gettitle( $env{'request.course.uri'} );
        !          1406:     if ( $name_of_map =~ /^\s*$/ ) {
        !          1407:         $env{'request.course.uri'} =~ m|([^/]+)$|;
        !          1408:         $name_of_map = $1;
1.123     albertel 1409:     }
1.575.2.1! foxr     1410:     return ( $name_of_resource, $name_of_sequence, $name_of_map );
1.76      sakharuk 1411: }
                   1412: 
1.476     albertel 1413: sub copyright_line {
1.575.2.1! foxr     1414:     return
        !          1415: '\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 } ';
1.476     albertel 1416: }
1.575.2.1! foxr     1417: my $end_of_student = "\n" . '\special{ps:ENDOFSTUDENTSTAMP}' . "\n";
1.76      sakharuk 1418: 
                   1419: sub latex_corrections {
1.575.2.1! foxr     1420:     my ( $number_of_columns, $result, $selectionmade, $answer_mode ) = @_;
        !          1421: 
1.185     sakharuk 1422: #    $result =~ s/\\includegraphics{/\\includegraphics\[width=\\minipagewidth\]{/g;
1.476     albertel 1423:     my $copyright = &copyright_line();
1.575.2.1! foxr     1424:     if ( $selectionmade eq '1' || $answer_mode eq 'only' ) {
        !          1425:         $result =~
        !          1426: s/(\\end{document})/\\strut\\vskip 0 mm $copyright $end_of_student $1/;
        !          1427:     }
        !          1428:     else {
        !          1429:         $result =~
        !          1430: s/(\\end{document})/\\strut\\vspace\*{-4 mm}\\newline $copyright $end_of_student $1/;
1.316     sakharuk 1431:     }
1.476     albertel 1432:     $result =~ s/\$number_of_columns/$number_of_columns/g;
1.575.2.1! foxr     1433:     $result =~
        !          1434: s/(\\end{longtable}\s*)(\\strut\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill})/$2$1/g;
1.91      sakharuk 1435:     $result =~ s/(\\end{longtable}\s*)\\strut\\newline/$1/g;
1.575.2.1! foxr     1436: 
        !          1437:     #-- LaTeX corrections
        !          1438:     my $first_comment = index( $result, '<!--', 0 );
        !          1439:     while ( $first_comment != -1 ) {
        !          1440:         my $end_comment = index( $result, '-->', $first_comment );
        !          1441:         substr( $result, $first_comment, $end_comment - $first_comment + 3 ) =
        !          1442:           '';
        !          1443:         $first_comment = index( $result, '<!--', $first_comment );
1.76      sakharuk 1444:     }
1.575.2.1! foxr     1445:     $result =~ s/^\s+$//gm;    #remove empty lines
        !          1446:                                #removes more than one empty space
1.377     albertel 1447:     $result =~ s|(\s\s+)|($1=~/[\n\r]/)?"\n":" "|ge;
1.76      sakharuk 1448:     $result =~ s/\\\\\s*\\vskip/\\vskip/gm;
                   1449:     $result =~ s/\\\\\s*\\noindent\s*(\\\\)+/\\\\\\noindent /g;
                   1450:     $result =~ s/{\\par }\s*\\\\/\\\\/gm;
1.313     sakharuk 1451:     $result =~ s/\\\\\s+\[/ \[/g;
1.575.2.1! foxr     1452: 
1.76      sakharuk 1453:     #conversion of html characters to LaTeX equivalents
1.575.2.1! foxr     1454:     if ( $result =~ m/&(\w+|#\d+);/ ) {
        !          1455:         $result = &character_chart($result);
1.76      sakharuk 1456:     }
                   1457:     $result =~ s/(\\end{tabular})\s*\\vskip 0 mm/$1/g;
                   1458:     $result =~ s/(\\begin{enumerate})\s*\\noindent/$1/g;
                   1459:     return $result;
1.60      sakharuk 1460: }
                   1461: 
1.214     sakharuk 1462: sub index_table {
1.575.2.1! foxr     1463:     my $currentURL   = shift;
        !          1464:     my $insex_string = '';
        !          1465:     $currentURL =~ s/\.([^\/+])$/\.$1\.meta/;
        !          1466:     $insex_string = &Apache::lonnet::metadata( $currentURL, 'keywords' );
1.214     sakharuk 1467:     return $insex_string;
                   1468: }
                   1469: 
1.215     sakharuk 1470: sub IndexCreation {
1.575.2.1! foxr     1471:     my ( $texversion, $currentURL ) = @_;
        !          1472:     my @key_words = split( /,/, &index_table($currentURL) );
        !          1473:     my $chunk     = '';
        !          1474:     my $st        = index $texversion, '\addcontentsline{toc}{subsection}{';
        !          1475:     if ( $st > 0 ) {
        !          1476:         for ( my $i = 0 ; $i < 3 ; $i++ ) {
        !          1477:             $st = ( index $texversion, '}', $st + 1 );
        !          1478:         }
        !          1479:         $chunk = substr( $texversion, 0, $st + 1 );
        !          1480:         substr( $texversion, 0, $st + 1 ) = ' ';
1.215     sakharuk 1481:     }
                   1482:     foreach my $key_word (@key_words) {
1.575.2.1! foxr     1483:         if ( $key_word =~ /\S+/ ) {
        !          1484:             $texversion =~ s/\b($key_word)\b/$1 \\index{$key_word} /i;
        !          1485:         }
        !          1486:     }
        !          1487:     if ( $st > 0 ) { substr( $texversion, 0, 1 ) = $chunk; }
1.215     sakharuk 1488:     return $texversion;
                   1489: }
                   1490: 
1.242     sakharuk 1491: sub print_latex_header {
1.575.2.1! foxr     1492:     my $mode = shift;
1.550     foxr     1493: 
                   1494:     return &Apache::londefdef::latex_header($mode);
1.242     sakharuk 1495: }
                   1496: 
                   1497: sub path_to_problem {
1.575.2.1! foxr     1498:     my ( $urlp, $colwidth ) = @_;
        !          1499:     $urlp = &Apache::lonnet::clutter($urlp);
1.404     albertel 1500: 
1.242     sakharuk 1501:     my $newurlp = '';
1.575.2.1! foxr     1502:     $colwidth =~ s/\s*mm\s*$//;
        !          1503: 
        !          1504:     #characters average about 2 mm in width
        !          1505:     if ( length($urlp) * 2 > $colwidth ) {
        !          1506:         my @elements = split( '/', $urlp );
        !          1507:         my $curlength = 0;
        !          1508:         foreach my $element (@elements) {
        !          1509:             if ( $element eq '' ) { next; }
        !          1510:             if ( $curlength + ( length($element) * 2 ) > $colwidth ) {
        !          1511:                 $newurlp .= '|\vskip -1 mm \verb|';
        !          1512:                 $curlength = length($element) * 2;
        !          1513:             }
        !          1514:             else {
        !          1515:                 $curlength += length($element) * 2;
        !          1516:             }
        !          1517:             $newurlp .= '/' . $element;
        !          1518:         }
        !          1519:     }
        !          1520:     else {
        !          1521:         $newurlp = $urlp;
1.242     sakharuk 1522:     }
1.575.2.1! foxr     1523:     return '{\small\noindent\verb|' . $newurlp . '|\vskip 0 mm}';
1.242     sakharuk 1524: }
1.215     sakharuk 1525: 
1.275     sakharuk 1526: sub recalcto_mm {
1.575.2.1! foxr     1527:     my $textwidth = shift;
1.275     sakharuk 1528:     my $LaTeXwidth;
1.575.2.1! foxr     1529:     if ( $textwidth =~ /(-?\d+\.?\d*)\s*cm/ ) {
        !          1530:         $LaTeXwidth = $1 * 10;
1.275     sakharuk 1531:     }
1.575.2.1! foxr     1532:     elsif ( $textwidth =~ /(-?\d+\.?\d*)\s*mm/ ) {
        !          1533:         $LaTeXwidth = $1;
        !          1534:     }
        !          1535:     elsif ( $textwidth =~ /(-?\d+\.?\d*)\s*in/ ) {
        !          1536:         $LaTeXwidth = $1 * 25.4;
        !          1537:     }
        !          1538:     $LaTeXwidth .= ' mm';
1.275     sakharuk 1539:     return $LaTeXwidth;
                   1540: }
                   1541: 
1.285     albertel 1542: sub get_textwidth {
1.575.2.1! foxr     1543:     my ( $helper, $LaTeXwidth ) = @_;
        !          1544:     my $textwidth = $LaTeXwidth;
        !          1545:     if (   $helper->{'VARS'}->{'pagesize.width'} =~ /\d+/
        !          1546:         && $helper->{'VARS'}->{'pagesize.widthunit'} =~ /\w+/ )
        !          1547:     {
        !          1548:         $textwidth =
        !          1549:           &recalcto_mm( $helper->{'VARS'}->{'pagesize.width'} . ' '
        !          1550:               . $helper->{'VARS'}->{'pagesize.widthunit'} );
1.285     albertel 1551:     }
1.286     albertel 1552:     return $textwidth;
1.285     albertel 1553: }
                   1554: 
1.296     sakharuk 1555: sub unsupported {
1.575.2.1! foxr     1556:     my ( $currentURL, $mode, $symb ) = @_;
        !          1557:     if ( $mode ne '' ) { $mode = '\\' . $mode }
        !          1558:     my $result .= &print_latex_header($mode);
        !          1559:     if ( $currentURL =~ m|^(/adm/wrapper/)?ext/| ) {
        !          1560:         $currentURL =~ s|^(/adm/wrapper/)?ext/|http://|;
        !          1561:         my $title = &Apache::lonnet::gettitle($symb);
        !          1562:         $title = &Apache::lonxml::latex_special_symbols($title);
        !          1563:         $result .=
        !          1564:           ' \strut \\\\ ' . $title . ' \strut \\\\ ' . $currentURL . ' ';
1.296     sakharuk 1565:     }
1.575.2.1! foxr     1566:     else {
        !          1567:         $result .= $currentURL;
        !          1568:     }
        !          1569:     $result .=
        !          1570: '\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill} \end{document}';
1.296     sakharuk 1571:     return $result;
                   1572: }
                   1573: 
1.559     foxr     1574: #
                   1575: #  Map from helper layout style to the book/album:
                   1576: #
                   1577: sub map_laystyle {
                   1578:     my ($laystyle) = @_;
1.575.2.1! foxr     1579:     if ( $laystyle eq 'L' ) {
        !          1580:         $laystyle = 'album';
        !          1581:     }
        !          1582:     else {
        !          1583:         $laystyle = 'book';
1.559     foxr     1584:     }
                   1585:     return $laystyle;
                   1586: }
                   1587: 
                   1588: sub print_page_in_course {
1.575.2.1! foxr     1589:     my ( $helper, $rparmhash, $currentURL, $resources ) = @_;
1.559     foxr     1590:     my %parmhash       = %$rparmhash;
                   1591:     my @page_resources = @$resources;
1.575.2.1! foxr     1592:     my $mode           = $helper->{'VARS'}->{'LATEX_TYPE'};
        !          1593:     my $symb           = $helper->{'VARS'}->{'symb'};
1.559     foxr     1594: 
                   1595:     my $format_from_helper = $helper->{'VARS'}->{'FORMAT'};
                   1596: 
1.575.2.1! foxr     1597:     my @temporary_array = split /\|/, $format_from_helper;
        !          1598:     my ( $laystyle, $numberofcolumns, $papersize, $pdfFormFields ) =
        !          1599:       @temporary_array;
1.559     foxr     1600:     $laystyle = &map_laystyle($laystyle);
1.575.2.1! foxr     1601:     my ( $textwidth, $textheight, $oddoffset, $evenoffset ) =
        !          1602:       &page_format( $papersize, $laystyle, $numberofcolumns );
        !          1603:     my $LaTeXwidth = &recalcto_mm($textwidth);
        !          1604: 
        !          1605:     if ( $mode ne '' ) { $mode = '\\' . $mode }
        !          1606:     my $result = &print_latex_header($mode);
        !          1607:     if ( $currentURL =~ m|^(/adm/wrapper/)?ext/| ) {
        !          1608:         $currentURL =~ s|^(/adm/wrapper/)?ext/|http://|;
        !          1609:         my $title = &Apache::lonnet::gettitle($symb);
        !          1610:         $title = &Apache::lonxml::latex_special_symbols($title);
        !          1611:     }
        !          1612:     else {
        !          1613:         $result .= $currentURL;
1.559     foxr     1614:     }
                   1615:     $result .= '\\\\';
                   1616: 
1.575.2.1! foxr     1617:     if ( $helper->{'VARS'}->{'style_file'} =~ /\w/ ) {
        !          1618:         &Apache::lonnet::appenv(
        !          1619:             { 'construct.style' => $helper->{'VARS'}->{'style_file'} } );
        !          1620:     }
        !          1621:     elsif ( $env{'construct.style'} ) {
        !          1622:         &Apache::lonnet::delenv('construct.style');
1.559     foxr     1623:     }
                   1624: 
1.575.2.1! foxr     1625:     # First is the overall page description.  This is then followed by the
1.559     foxr     1626:     # components of the page. Each of which must be printed independently.
1.575.2.1! foxr     1627:     my $the_page = shift(@page_resources);
1.559     foxr     1628: 
                   1629:     foreach my $resource (@page_resources) {
1.575.2.1! foxr     1630:         my $resource_src =
        !          1631:           $resource->src();    # Essentially the URL of the resource.
        !          1632:         $result .= $resource->title() . '\\\\';
        !          1633: 
        !          1634:         # Recurse if a .page:
        !          1635: 
        !          1636:         if ( $resource_src =~ /.page$/i ) {
        !          1637:             my $navmap         = Apache::lonnavmaps::navmap->new();
        !          1638:             my @page_resources = $navmap->retrieveResources($resource_src);
        !          1639:             $result .=
        !          1640:               &print_page_in_course( $helper, $rparmhash, $resource_src,
        !          1641:                 \@page_resources );
        !          1642:         }
1.559     foxr     1643: 
1.575.2.1! foxr     1644:         # these resources go through the XML transformer:
1.559     foxr     1645: 
1.575.2.1! foxr     1646:         elsif ( $resource_src =~
        !          1647: /\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm\xhtml|xhtm)$/
        !          1648:           )
        !          1649:         {
        !          1650:             my $urlp = &Apache::lonnet::clutter($resource_src);
        !          1651:             my %form;
        !          1652:             my %moreenv;
        !          1653: 
        !          1654:             &Apache::lonxml::remember_problem_counter();
        !          1655:             $moreenv{'request.filename'} = $urlp;
        !          1656:             if ( $helper->{'VARS'}->{'probstatus'} eq 'exam' ) {
        !          1657:                 $form{'problemtype'} = 'exam';
        !          1658:             }
        !          1659: 
        !          1660:             $form{'grade_target'} = 'tex';
        !          1661:             $form{'textwidth'}    = &get_textwidth( $helper, $LaTeXwidth );
        !          1662:             $form{'pdfFormFiels'} = $pdfFormFields;                           #
        !          1663:             $form{'showallfoils'} = $helper->{'VARS'}->{'showallfoils'};
        !          1664: 
        !          1665:             $form{'problem_split'}  = $parmhash{'problem_stream_switch'};
        !          1666:             $form{'suppress_tries'} = $parmhash{'suppress_tries'};
        !          1667:             $form{'latex_type'}     = $helper->{'VARS'}->{'LATEX_TYPE'};
        !          1668:             $form{'print_discussions'} =
        !          1669:               $helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
        !          1670:             $form{'print_annotations'} =
        !          1671:               $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
        !          1672:             if (   ( $helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes' )
        !          1673:                 || ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) )
        !          1674:             {
        !          1675:                 $form{'problem_split'} = 'yes';
        !          1676:             }
        !          1677:             my $rndseed = time;
        !          1678:             if ( $helper->{'VARS'}->{'curseed'} ) {
        !          1679:                 $rndseed = $helper->{'VARS'}->{'curseed'};
        !          1680:             }
        !          1681:             $form{'rndseed'} = $rndseed;
        !          1682:             &Apache::lonnet::appenv( \%moreenv );
        !          1683: 
        !          1684:             &Apache::lonxml::clear_problem_counter();
        !          1685: 
        !          1686:             my $texversion =
        !          1687:               &ssi_with_retries( $urlp, $ssi_retry_count, %form );
        !          1688: 
        !          1689:             # current document with answers.. no need to encap in minipage
        !          1690:             #  since there's only one answer.
        !          1691: 
        !          1692:             if (   ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' )
        !          1693:                 || ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only' ) )
        !          1694:             {
        !          1695:                 my %answerform = %form;
        !          1696: 
        !          1697:                 $answerform{'problem_split'} =
        !          1698:                   $parmhash{'problem_stream_switch'};
        !          1699:                 $answerform{'grade_target'}       = 'answer';
        !          1700:                 $answerform{'answer_output_mode'} = 'tex';
        !          1701:                 $answerform{'rndseed'}            = $rndseed;
        !          1702:                 if ( $helper->{'VARS'}->{'probstatus'} eq 'exam' ) {
        !          1703:                     $answerform{'problemtype'} = 'exam';
        !          1704:                 }
        !          1705:                 $resources_printed .= $urlp . ':';
        !          1706:                 my $answer =
        !          1707:                   &ssi_with_retries( $urlp, $ssi_retry_count, %answerform );
        !          1708: 
        !          1709:                 if ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' ) {
        !          1710:                     $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
        !          1711:                 }
        !          1712:                 else {
        !          1713:                     $texversion =
        !          1714:                       &print_latex_header( $helper->{'VARS'}->{'LATEX_TYPE'} );
        !          1715:                     if ( $helper->{'VARS'}->{'construction'} ne '1' ) {
        !          1716:                         my $title =
        !          1717:                           &Apache::lonnet::gettitle(
        !          1718:                             $helper->{'VARS'}->{'symb'} );
        !          1719:                         $title = &Apache::lonxml::latex_special_symbols($title);
        !          1720:                         $texversion .=
        !          1721:                             '\vskip 0 mm \noindent\textbf{' 
        !          1722:                           . $title
        !          1723:                           . '}\vskip 0 mm ';
        !          1724:                         $texversion .= &path_to_problem( $urlp, $LaTeXwidth );
        !          1725:                     }
        !          1726:                     else {
        !          1727:                         $texversion .=
        !          1728: '\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
        !          1729:                         my $URLpath = $urlp;
        !          1730:                         $URLpath =~ s/~([^\/]+)/public_html\/$1\/$1/;
        !          1731:                         $texversion .=
        !          1732:                           &path_to_problem( $URLpath, $LaTeXwidth );
        !          1733:                     }
        !          1734:                     $texversion .= '\vskip 1 mm ' . $answer . '\end{document}';
        !          1735:                 }
        !          1736: 
        !          1737:             }
        !          1738: 
        !          1739:             # Print annotations.
        !          1740: 
        !          1741:             if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          1742:                 my $annotation .= &annotate($currentURL);
        !          1743:                 $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
        !          1744:             }
        !          1745: 
        !          1746:             if ( $helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes' ) {
        !          1747:                 $texversion = &IndexCreation( $texversion, $currentURL );
        !          1748:             }
        !          1749:             if ( $helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes' ) {
        !          1750:                 $texversion =~
        !          1751: s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$currentURL| \\strut\\\\\\strut /;
1.559     foxr     1752: 
1.575.2.1! foxr     1753:             }
        !          1754:             $texversion = &latex_header_footer_remove($texversion);
1.562     foxr     1755: 
1.575.2.1! foxr     1756:             # the first remaining line is a comment from londefdef the second
        !          1757:             # line  seems to be an extraneous \vskip 1mm \\\\ :
1.562     foxr     1758:             # (imperfect removal from header_footer_remove?
                   1759: 
1.575.2.1! foxr     1760:             $texversion =~ s/\\vskip 1mm \\\\\\\\//;
1.562     foxr     1761: 
1.575.2.1! foxr     1762:             $result .= $texversion;
        !          1763:             if ( $currentURL =~ m/\.page\s*$/ ) {
        !          1764:                 ( $result, $numberofcolumns ) = &page_cleanup($result);
        !          1765:             }
        !          1766:         }
1.559     foxr     1767:     }
                   1768: 
1.575.2.1! foxr     1769:     $result .=
        !          1770: '\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill} \end{document}';
1.559     foxr     1771:     return $result;
                   1772: }
                   1773: 
1.363     foxr     1774: #
1.395     www      1775: # List of recently generated print files
                   1776: #
                   1777: sub recently_generated {
1.575.2.1! foxr     1778:     my $r        = shift;
        !          1779:     my $prtspool = $r->dir_config('lonPrtDir');
1.400     albertel 1780:     my $zip_result;
                   1781:     my $pdf_result;
1.575.2.1! foxr     1782:     opendir( DIR, $prtspool );
1.400     albertel 1783: 
1.575.2.1! foxr     1784:     my @files =
        !          1785:       grep(
        !          1786:         /^$env{'user.name'}_$env{'user.domain'}_printout_(\d+)_.*\.(pdf|zip)$/,
        !          1787:         readdir(DIR) );
1.395     www      1788:     closedir(DIR);
1.400     albertel 1789: 
                   1790:     @files = sort {
1.575.2.1! foxr     1791:         my ($actime) = ( stat( $prtspool . '/' . $a ) )[10];
        !          1792:         my ($bctime) = ( stat( $prtspool . '/' . $b ) )[10];
        !          1793:         return $bctime <=> $actime;
1.400     albertel 1794:     } (@files);
                   1795: 
                   1796:     foreach my $filename (@files) {
1.575.2.1! foxr     1797:         my ($ext) = ( $filename =~ m/(pdf|zip)$/ );
        !          1798:         my (
        !          1799:             $cdev,   $cino,     $cmode, $cnlink, $cuid,
        !          1800:             $cgid,   $crdev,    $csize, $catime, $cmtime,
        !          1801:             $cctime, $cblksize, $cblocks
        !          1802:         ) = stat( $prtspool . '/' . $filename );
        !          1803:         my $ext_text = 'pdf' ? &mt('PDF File') : &mt('Zip File');
        !          1804:         my $result =
        !          1805:             &Apache::loncommon::start_data_table_row() . '<td>'
        !          1806:           . '<a href="/prtspool/'
        !          1807:           . $filename . '">'
        !          1808:           . $ext_text . '</a>' . '</td>' . '<td>'
        !          1809:           . &Apache::lonlocal::locallocaltime($cctime) . '</td>'
        !          1810:           . '<td align="right">'
        !          1811:           . $csize . '</td>'
        !          1812:           . &Apache::loncommon::end_data_table_row();
        !          1813:         if ( $ext eq 'pdf' ) { $pdf_result .= $result; }
        !          1814:         if ( $ext eq 'zip' ) { $zip_result .= $result; }
1.400     albertel 1815:     }
1.575.2.1! foxr     1816:     if ( $zip_result || $pdf_result ) {
1.544     bisitz   1817:         $r->print('<hr />');
                   1818:     }
1.400     albertel 1819:     if ($zip_result) {
1.575.2.1! foxr     1820:         $r->print( '<h3>'
        !          1821:               . &mt('Recently generated printout zip files')
        !          1822:               . "</h3>\n"
        !          1823:               . &Apache::loncommon::start_data_table()
        !          1824:               . &Apache::loncommon::start_data_table_header_row() . '<th>'
        !          1825:               . &mt('Download') . '</th>' . '<th>'
        !          1826:               . &mt('Creation Date') . '</th>' . '<th>'
        !          1827:               . &mt('File Size (Bytes)') . '</th>'
        !          1828:               . &Apache::loncommon::end_data_table_header_row()
        !          1829:               . $zip_result
        !          1830:               . &Apache::loncommon::end_data_table() );
1.400     albertel 1831:     }
                   1832:     if ($pdf_result) {
1.575.2.1! foxr     1833:         $r->print( '<h3>'
        !          1834:               . &mt('Recently generated printouts')
        !          1835:               . "</h3>\n"
        !          1836:               . &Apache::loncommon::start_data_table()
        !          1837:               . &Apache::loncommon::start_data_table_header_row() . '<th>'
        !          1838:               . &mt('Download') . '</th>' . '<th>'
        !          1839:               . &mt('Creation Date') . '</th>' . '<th>'
        !          1840:               . &mt('File Size (Bytes)') . '</th>'
        !          1841:               . &Apache::loncommon::end_data_table_header_row()
        !          1842:               . $pdf_result
        !          1843:               . &Apache::loncommon::end_data_table() );
1.396     albertel 1844:     }
1.395     www      1845: }
                   1846: 
                   1847: #
1.363     foxr     1848: #   Retrieve the hash of page breaks.
                   1849: #
                   1850: #  Inputs:
                   1851: #    helper   - reference to helper object.
                   1852: #  Outputs
                   1853: #    A reference to a page break hash.
                   1854: #
                   1855: #
1.562     foxr     1856: # use Data::Dumper;
1.569     foxr     1857: # sub dump_helper_vars {
1.418     foxr     1858: #    my ($helper) = @_;
                   1859: #    my $helpervars = Dumper($helper->{'VARS'});
                   1860: #    &Apache::lonnet::logthis("Dump of helper vars:\n $helpervars");
                   1861: #}
1.363     foxr     1862: 
1.575.2.1! foxr     1863: sub get_page_breaks {
1.481     albertel 1864:     my ($helper) = @_;
                   1865:     my %page_breaks;
                   1866: 
1.575.2.1! foxr     1867:     foreach my $break ( split /\|\|\|/, $helper->{'VARS'}->{'FINISHPAGE'} ) {
        !          1868:         $page_breaks{$break} = 1;
1.481     albertel 1869:     }
                   1870:     return %page_breaks;
                   1871: }
1.575.2.1! foxr     1872: 
        !          1873: #
1.569     foxr     1874: #   Returns text to insert for any extra vskip prior to the resource.
                   1875: #   Parameters:
                   1876: #     helper   - Reference to the helper object driving the printout.
                   1877: #     resource - Identifies the resource about to be printed.
                   1878: #
                   1879: #   This is done as follows:
                   1880: #    POSSIBLE_RESOURCES has the list of possible resources.
                   1881: #    EXTRASPACE         has the list of extra space values.
1.570     foxr     1882: #    EXTRASPACE_UNITS   is the set of resources for which the units are
                   1883: #                       mm. All others are 'in'.
1.575.2.1! foxr     1884: #
1.569     foxr     1885: #    The resource is found in the POSSIBLE_RESOURCES to get the index
                   1886: #    of the EXTRASPACE value.
                   1887: #
                   1888: #   In order to speed this up for lengthy printouts, the first time,
                   1889: #   POSSIBLE_RESOURCES is turned into a look up hash and
                   1890: #   EXTRASPACE is turned into an array.
                   1891: #
                   1892: 
                   1893: my %possible_resources;
1.570     foxr     1894: my %extraspace_mm;
1.569     foxr     1895: my @extraspace;
1.575.2.1! foxr     1896: my $skips_loaded = 0;
1.569     foxr     1897: 
                   1898: #  Function to load the skips hash and array
                   1899: 
                   1900: sub load_skips {
                   1901: 
1.575.2.1! foxr     1902:     my ($helper) = @_;
1.569     foxr     1903: 
                   1904:     #  If this is the first time, unrap the resources and extra spaces:
                   1905: 
1.575.2.1! foxr     1906:     if ( !$skips_loaded ) {
        !          1907:         @extraspace = ( split( /\|\|\|/, $helper->{'VARS'}->{'EXTRASPACE'} ) );
        !          1908:         my @resource_list =
        !          1909:           ( split( /\|\|\|/, $helper->{'VARS'}->{'POSSIBLE_RESOURCES'} ) );
        !          1910:         my $i = 0;
        !          1911:         foreach my $resource (@resource_list) {
        !          1912:             $possible_resources{$resource} = $i;
        !          1913:             $i++;
        !          1914:         }
        !          1915:         foreach my $mm_resource (
        !          1916:             split( /\|\|\|/, $helper->{'VARS'}->{'EXTRASPACE_UNITS'} ) )
        !          1917:         {
        !          1918:             $extraspace_mm{$mm_resource} = 1;
        !          1919:         }
        !          1920:         $skips_loaded = 1;
1.569     foxr     1921:     }
                   1922: }
                   1923: 
                   1924: sub get_extra_vspaces {
1.575.2.1! foxr     1925:     my ( $helper, $resource ) = @_;
1.569     foxr     1926: 
                   1927:     &load_skips($helper);
                   1928: 
                   1929:     #  Lookup the resource in the possible resources hash.. that is the index
                   1930:     # into the extraspace array that gives us either an empty string or
                   1931:     # the number of mm to skip:
                   1932: 
                   1933:     my $index = $possible_resources{$resource};
                   1934:     my $skip  = $extraspace[$index];
                   1935: 
                   1936:     my $result = '';
1.575.2.1! foxr     1937:     if ( $skip ne '' ) {
        !          1938:         my $units = 'in';
        !          1939:         if ( defined( $extraspace_mm{$resource} ) ) {
        !          1940:             $units = 'mm';
        !          1941:         }
        !          1942:         $result = '\vskip ' . $skip . ' ' . $units;
1.569     foxr     1943:     }
1.570     foxr     1944: 
1.569     foxr     1945:     return $result;
                   1946: 
                   1947: }
                   1948: 
                   1949: #
                   1950: #  The resource chooser part of the helper needs more than just
                   1951: #  the value of the extraspaces var to recover the value into a text
                   1952: #  field option.  This sub produces the required format for the saved var:
1.575.2.1! foxr     1953: #  specifically
1.569     foxr     1954: #    ||| separated fields of the form resourcename=value
                   1955: #
                   1956: #  Parameters:
                   1957: #    $helper     - Refers to the helper we are configuring
                   1958: #  Implicit input:
                   1959: #     $helper->{'VARS'}->{'EXTRASPACE'}  - the spaces helper var has the text field
                   1960: #                                          value.
1.570     foxr     1961: #     $helper->{'VARS'}->{'EXTRASPACE_UNITS'} - units for the skips (checkboxes).
1.569     foxr     1962: #     $helper->{'VARS'}->{'POSSIBLE_RESOURCES'}  - has the list of resources. |||
                   1963: #                                          separated of course.
                   1964: #  Implicit outputs:
1.570     foxr     1965: #     $env{'form.extraspace'}
                   1966: #     $env{'form.extraspace_units'}
1.569     foxr     1967: #
                   1968: sub set_form_extraspace {
                   1969:     my ($helper) = @_;
                   1970: 
                   1971:     # the most convenient way to do this is to drive from the skips arrays/hash.
                   1972:     # may not be the fastest, but this is once per print request so it's not so
                   1973:     # speed critical:
                   1974: 
                   1975:     &load_skips($helper);
                   1976: 
                   1977:     my $result = '';
                   1978: 
1.575.2.1! foxr     1979:     foreach my $resource ( keys(%possible_resources) ) {
        !          1980:         my $vskip = $extraspace[ $possible_resources{$resource} ];
        !          1981:         $result .= $resource . '=' . $vskip . '|||';
1.569     foxr     1982:     }
                   1983: 
1.575.2.1! foxr     1984:     $env{'form.extraspace'}       = $result;
1.570     foxr     1985:     $env{'form.extraspace_units'} = $helper->{'VARS'}->{'EXTRASPACE_UNITS'};
1.569     foxr     1986:     return $result;
1.575.2.1! foxr     1987: 
1.569     foxr     1988: }
1.363     foxr     1989: 
1.459     foxr     1990: #  Output a sequence (recursively if neeed)
                   1991: #  from construction space.
                   1992: # Parameters:
                   1993: #    url     = URL of the sequence to print.
                   1994: #    helper  - Reference to the helper hash.
                   1995: #    form    - Copy of the format hash.
                   1996: #    LaTeXWidth
                   1997: # Returns:
                   1998: #   Text to add to the printout.
                   1999: #   NOTE if the first element of the outermost sequence
                   2000: #   is itself a sequence, the outermost caller may need to
                   2001: #   prefix the latex with the page headers stuff.
                   2002: #
                   2003: sub print_construction_sequence {
1.575.2.1! foxr     2004:     my ( $currentURL, $helper, %form, $LaTeXwidth ) = @_;
1.459     foxr     2005:     my $result;
1.575.2.1! foxr     2006:     my $rndseed = time;
        !          2007:     if ( $helper->{'VARS'}->{'curseed'} ) {
        !          2008:         $rndseed = $helper->{'VARS'}->{'curseed'};
1.459     foxr     2009:     }
1.575.2.1! foxr     2010:     my $errtext = &LONCAPA::map::mapread($currentURL);
        !          2011: 
        !          2012:     #
1.459     foxr     2013:     #  These make this all support recursing for subsequences.
                   2014:     #
1.575.2.1! foxr     2015:     my @order     = @LONCAPA::map::order;
        !          2016:     my @resources = @LONCAPA::map::resources;
        !          2017:     for ( my $member = 0 ; $member <= $#order ; $member++ ) {
        !          2018:         $resources[ $order[$member] ] =~ /^([^:]*):([^:]*):/;
        !          2019:         my $urlp = $2;
        !          2020:         if ( $urlp =~
        !          2021: /\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/
        !          2022:           )
        !          2023:         {
        !          2024:             my $texversion = '';
        !          2025:             if ( $helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only' ) {
        !          2026:                 $form{'problem_split'}  = $parmhash{'problem_stream_switch'};
        !          2027:                 $form{'suppress_tries'} = $parmhash{'suppress_tries'};
        !          2028:                 $form{'latex_type'}     = $helper->{'VARS'}->{'LATEX_TYPE'};
        !          2029:                 $form{'rndseed'}        = $rndseed;
        !          2030:                 $resources_printed .= $urlp . ':';
        !          2031:                 $texversion =
        !          2032:                   &ssi_with_retries( $urlp, $ssi_retry_count, %form );
        !          2033:             }
        !          2034:             if (
        !          2035:                 (
        !          2036:                        ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' )
        !          2037:                     || ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only' )
        !          2038:                 )
        !          2039:                 && ( $urlp =~
        !          2040:                     /\.(problem|exam|quiz|assess|survey|form|library|page)$/ )
        !          2041:               )
        !          2042:             {
        !          2043: 
        !          2044:                 #  Don't permanently modify %$form...
        !          2045:                 my %answerform = %form;
        !          2046:                 $answerform{'grade_target'}       = 'answer';
        !          2047:                 $answerform{'answer_output_mode'} = 'tex';
        !          2048:                 $answerform{'rndseed'}            = $rndseed;
        !          2049:                 $answerform{'problem_split'} =
        !          2050:                   $parmhash{'problem_stream_switch'};
        !          2051:                 if ( $urlp =~ /\/res\// ) {
        !          2052:                     $env{'request.state'} = 'published';
        !          2053:                 }
        !          2054:                 $resources_printed .= $urlp . ':';
        !          2055:                 my $answer =
        !          2056:                   &ssi_with_retries( $urlp, $ssi_retry_count, %answerform );
        !          2057: 
        !          2058:                 if ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' ) {
        !          2059:                     $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
        !          2060:                 }
        !          2061:                 else {
        !          2062: 
        !          2063:                     # If necessary, encapsulate answer in minipage:
        !          2064: 
        !          2065:                     $texversion =
        !          2066:                       &print_latex_header( $helper->{'VARS'}->{'LATEX_TYPE'} );
        !          2067:                     my $title =
        !          2068:                       &Apache::lonnet::gettitle( $helper->{'VARS'}->{'symb'} );
        !          2069:                     $title = &Apache::lonxml::latex_special_symbols($title);
        !          2070:                     my $body =
        !          2071:                         '\vskip 0 mm \noindent\textbf{' 
        !          2072:                       . $title
        !          2073:                       . '}\vskip 0 mm ';
        !          2074:                     $body .= &path_to_problem( $urlp, $LaTeXwidth );
        !          2075:                     $body .= '\vskip 1 mm ' . $answer . '\end{document}';
        !          2076:                     $body = &encapsulate_minipage($body);
        !          2077:                     $texversion .= $body;
        !          2078:                 }
        !          2079:             }
        !          2080:             $texversion = &latex_header_footer_remove($texversion);
        !          2081: 
        !          2082:             if ( $helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes' ) {
        !          2083:                 $texversion = &IndexCreation( $texversion, $urlp );
        !          2084:             }
        !          2085:             if ( $helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes' ) {
        !          2086:                 $texversion =~
        !          2087: s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /;
        !          2088:             }
        !          2089:             $result .= $texversion;
        !          2090: 
        !          2091:         }
        !          2092:         elsif ( $urlp =~ /\.(sequence|page)$/ ) {
        !          2093: 
        !          2094:             # header:
        !          2095: 
        !          2096:             $result .=
        !          2097:                 '\strut\newline\noindent Sequence/page ' 
        !          2098:               . $urlp
        !          2099:               . '\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent ';
        !          2100: 
        !          2101:             # IF sequence, recurse:
        !          2102: 
        !          2103:             if ( $urlp =~ /\.sequence$/ ) {
        !          2104:                 my $sequence_url = $urlp;
        !          2105:                 my $domain = $env{'user.domain'};  # Constr. space only on local
        !          2106:                 my $user   = $env{'user.name'};
        !          2107: 
        !          2108:                 $sequence_url =~ s/^\/res\/$domain/\/home/;
        !          2109:                 $sequence_url =~ s/^(\/home\/$user)/$1\/public_html/;
        !          2110: 
        !          2111:               #		$sequence_url    =~ s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;
        !          2112:                 $result .=
        !          2113:                   &print_construction_sequence( $sequence_url, $helper, %form,
        !          2114:                     $LaTeXwidth );
        !          2115:             }
        !          2116:         }
        !          2117:         elsif ( $urlp =~ /\.pdf$/i ) {
        !          2118:             my $texversion;
        !          2119:             if ( $member != 0 ) {
        !          2120:                 $texversion .= '\cleardoublepage';
        !          2121:             }
        !          2122: 
        !          2123:             $texversion .= &include_pdf($urlp);
        !          2124:             $texversion = &latex_header_footer_remove($texversion);
        !          2125:             if ( $member != $#order ) {
        !          2126:                 $texversion .= '\\ \cleardoublepage';
        !          2127:             }
        !          2128: 
        !          2129:             $result .= $texversion;
        !          2130:         }
        !          2131:     }
        !          2132:     if ( $helper->{VARS}->{'construction'} eq '1' ) {
        !          2133:         $result =~ s/(\\begin{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;
1.459     foxr     2134:     }
                   2135:     return $result;
                   2136: }
                   2137: 
1.177     sakharuk 2138: sub output_data {
1.575.2.1! foxr     2139:     my ( $r, $helper, $rparmhash ) = @_;
1.184     sakharuk 2140:     my %parmhash = %$rparmhash;
1.575.2.1! foxr     2141:     $ssi_error         = 0;    # This will be set nonzero by failing ssi's.
1.459     foxr     2142:     $resources_printed = '';
1.556     foxr     2143:     $font_size = $helper->{'VARS'}->{'fontsize'};
1.499     foxr     2144:     my $do_postprocessing = 1;
1.575.2.1! foxr     2145:     my $js                = <<ENDPART;
1.433     albertel 2146: <script type="text/javascript">
1.264     sakharuk 2147:     var editbrowser;
                   2148:     function openbrowser(formname,elementname,only,omit) {
                   2149:         var url = '/res/?';
                   2150:         if (editbrowser == null) {
                   2151:             url += 'launch=1&';
                   2152:         }
                   2153:         url += 'catalogmode=interactive&';
                   2154:         url += 'mode=parmset&';
                   2155:         url += 'form=' + formname + '&';
                   2156:         if (only != null) {
                   2157:             url += 'only=' + only + '&';
                   2158:         } 
                   2159:         if (omit != null) {
                   2160:             url += 'omit=' + omit + '&';
                   2161:         }
                   2162:         url += 'element=' + elementname + '';
                   2163:         var title = 'Browser';
                   2164:         var options = 'scrollbars=1,resizable=1,menubar=0';
                   2165:         options += ',width=700,height=600';
                   2166:         editbrowser = open(url,title,options,'1');
                   2167:         editbrowser.focus();
                   2168:     }
                   2169: </script>
1.140     sakharuk 2170: ENDPART
                   2171: 
1.558     bisitz   2172:     # Breadcrumbs
                   2173:     #FIXME: Choose better/different breadcrumbs?!? Links?
1.575.2.1! foxr     2174:     my $brcrum = [
        !          2175:         {
        !          2176:             'href' => '',
        !          2177:             'text' => 'Helper'
        !          2178:         },    #FIXME: Different origin possible than print out helper?
        !          2179:         {
        !          2180:             'href' => '',
        !          2181:             'text' => 'Preparing Printout'
        !          2182:         }
        !          2183:     ];
1.363     foxr     2184: 
1.575.2.1! foxr     2185:     my $start_page = &Apache::loncommon::start_page( 'Preparing Printout',
        !          2186:         $js, { 'bread_crumbs' => $brcrum, } );
        !          2187:     my $msg = &mt(
        !          2188: 'Please stand by while processing your print request, this may take some time ...'
        !          2189:     );
        !          2190: 
        !          2191:     $r->print( $start_page . "\n<p>\n$msg\n</p>\n" );
1.372     foxr     2192: 
1.363     foxr     2193:     # fetch the pagebreaks and store them in the course environment
                   2194:     # The page breaks will be pulled into the hash %page_breaks which is
                   2195:     # indexed by symb and contains 1's for each break.
                   2196: 
1.575.2.1! foxr     2197:     $env{'form.pagebreaks'} = $helper->{'VARS'}->{'FINISHPAGE'};
1.569     foxr     2198:     &set_form_extraspace($helper);
1.575.2.1! foxr     2199:     $env{'form.lastprinttype'} = $helper->{'VARS'}->{'PRINT_TYPE'};
        !          2200:     &Apache::loncommon::store_course_settings(
        !          2201:         'print',
        !          2202:         {
        !          2203:             'pagebreaks'       => 'scalar',
        !          2204:             'extraspace'       => 'scalar',
        !          2205:             'extraspace_units' => 'scalar',
        !          2206:             'lastprinttype'    => 'scalar'
        !          2207:         }
        !          2208:     );
        !          2209:     my %page_breaks = &get_page_breaks($helper);
1.363     foxr     2210: 
1.140     sakharuk 2211:     my $format_from_helper = $helper->{'VARS'}->{'FORMAT'};
1.575.2.1! foxr     2212:     my ( $result, $selectionmade ) = ( '', '' );
        !          2213:     my $number_of_columns =
        !          2214:       1;    #used only for pages to determine the width of the cell
        !          2215:     my @temporary_array = split /\|/, $format_from_helper;
        !          2216:     my ( $laystyle, $numberofcolumns, $papersize, $pdfFormFields ) =
        !          2217:       @temporary_array;
1.559     foxr     2218: 
                   2219:     $laystyle = &map_laystyle($laystyle);
1.575.2.1! foxr     2220:     my ( $textwidth, $textheight, $oddoffset, $evenoffset ) =
        !          2221:       &page_format( $papersize, $laystyle, $numberofcolumns );
        !          2222:     my $assignment    = $env{'form.assignment'};
        !          2223:     my $LaTeXwidth    = &recalcto_mm($textwidth);
        !          2224:     my @print_array   = ();
        !          2225:     my @student_names = ();
1.360     albertel 2226: 
                   2227:     #  Common settings for the %form has:
                   2228:     # In some cases these settings get overriddent by specific cases, but the
                   2229:     # settings are common enough to make it worthwhile factoring them out
                   2230:     # here.
                   2231:     #
                   2232:     my %form;
1.575.2.1! foxr     2233:     $form{'grade_target'}  = 'tex';
        !          2234:     $form{'textwidth'}     = &get_textwidth( $helper, $LaTeXwidth );
1.539     onken    2235:     $form{'pdfFormFields'} = $pdfFormFields;
1.372     foxr     2236: 
                   2237:     # If form.showallfoils is set, then request all foils be shown:
1.575.2.1! foxr     2238:     # privilege will be enforced both by not allowing the
1.372     foxr     2239:     # check box selecting this option to be presnt unless it's ok,
                   2240:     # and by lonresponse's priv. check.
                   2241:     # The if is here because lonresponse.pm only cares that
                   2242:     # showallfoils is defined, not what the value is.
                   2243: 
1.575.2.1! foxr     2244:     if ( $helper->{'VARS'}->{'showallfoils'} eq "1" ) {
        !          2245:         $form{'showallfoils'} = $helper->{'VARS'}->{'showallfoils'};
        !          2246:     }
        !          2247: 
        !          2248:     if ( $helper->{'VARS'}->{'style_file'} =~ /\w/ ) {
        !          2249:         &Apache::lonnet::appenv(
        !          2250:             { 'construct.style' => $helper->{'VARS'}->{'style_file'} } );
1.372     foxr     2251:     }
1.575.2.1! foxr     2252:     elsif ( $env{'construct.style'} ) {
        !          2253:         &Apache::lonnet::delenv('construct.style');
1.504     albertel 2254:     }
                   2255: 
1.575.2.1! foxr     2256:     if ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'current_document' ) {
1.372     foxr     2257: 
1.575.2.1! foxr     2258:         #-- single document - problem, page, html, xml, ...
        !          2259:         my ( $currentURL, $cleanURL );
        !          2260: 
        !          2261:         if ( $helper->{'VARS'}->{'construction'} ne '1' ) {
1.375     foxr     2262: 
1.185     sakharuk 2263:             #prints published resource
1.575.2.1! foxr     2264:             $currentURL = $helper->{'VARS'}->{'postdata'};
        !          2265:             $cleanURL   = &Apache::lonenc::check_decrypt($currentURL);
        !          2266:         }
        !          2267:         else {
1.512     foxr     2268: 
1.185     sakharuk 2269:             #prints resource from the construction space
1.575.2.1! foxr     2270:             $currentURL = '/' . $helper->{'VARS'}->{'filename'};
        !          2271:             if ( $currentURL =~ /([^?]+)/ ) { $currentURL = $1; }
        !          2272:             $cleanURL = $currentURL;
        !          2273:         }
        !          2274:         $selectionmade = 1;
        !          2275:         if (   $cleanURL !~ m|^/adm/|
        !          2276:             && $cleanURL =~
        !          2277: /\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/
        !          2278:           )
        !          2279:         {
        !          2280:             my $rndseed    = time;
        !          2281:             my $texversion = '';
        !          2282:             if ( $helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only' ) {
        !          2283:                 my %moreenv;
        !          2284:                 $moreenv{'request.filename'} = $cleanURL;
        !          2285:                 if ( $helper->{'VARS'}->{'probstatus'} eq 'exam' ) {
        !          2286:                     $form{'problemtype'} = 'exam';
        !          2287:                 }
        !          2288:                 $form{'problem_split'}  = $parmhash{'problem_stream_switch'};
        !          2289:                 $form{'suppress_tries'} = $parmhash{'suppress_tries'};
        !          2290:                 $form{'latex_type'}     = $helper->{'VARS'}->{'LATEX_TYPE'};
        !          2291:                 $form{'print_discussions'} =
        !          2292:                   $helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
        !          2293:                 $form{'print_annotations'} =
        !          2294:                   $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
        !          2295:                 if (   ( $helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes' )
        !          2296:                     || ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) )
        !          2297:                 {
        !          2298:                     $form{'problem_split'} = 'yes';
        !          2299:                 }
        !          2300:                 if ( $helper->{'VARS'}->{'curseed'} ) {
        !          2301:                     $rndseed = $helper->{'VARS'}->{'curseed'};
        !          2302:                 }
        !          2303:                 $form{'rndseed'} = $rndseed;
        !          2304:                 &Apache::lonnet::appenv( \%moreenv );
        !          2305: 
        !          2306:                 &Apache::lonxml::clear_problem_counter();
        !          2307: 
        !          2308:                 $resources_printed .= $currentURL . ':';
        !          2309:                 $texversion .=
        !          2310:                   &ssi_with_retries( $currentURL, $ssi_retry_count, %form );
        !          2311: 
        !          2312:                 #  Add annotations if required:
        !          2313: 
        !          2314:                 &Apache::lonxml::clear_problem_counter();
        !          2315: 
        !          2316:                 &Apache::lonnet::delenv('request.filename');
        !          2317:             }
        !          2318: 
        !          2319:             # current document with answers.. no need to encap in minipage
        !          2320:             #  since there's only one answer.
        !          2321: 
        !          2322:             if (   ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' )
        !          2323:                 || ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only' ) )
        !          2324:             {
        !          2325:                 $form{'problem_split'} = $parmhash{'problem_stream_switch'};
        !          2326:                 $form{'grade_target'}  = 'answer';
        !          2327:                 $form{'answer_output_mode'} = 'tex';
        !          2328:                 $form{'rndseed'}            = $rndseed;
        !          2329:                 if ( $helper->{'VARS'}->{'probstatus'} eq 'exam' ) {
        !          2330:                     $form{'problemtype'} = 'exam';
        !          2331:                 }
        !          2332:                 $resources_printed .= $currentURL . ':';
        !          2333:                 my $answer =
        !          2334:                   &ssi_with_retries( $currentURL, $ssi_retry_count, %form );
        !          2335: 
        !          2336:                 if ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' ) {
        !          2337:                     $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
        !          2338:                 }
        !          2339:                 else {
        !          2340:                     $texversion =
        !          2341:                       &print_latex_header( $helper->{'VARS'}->{'LATEX_TYPE'} );
        !          2342:                     if ( $helper->{'VARS'}->{'construction'} ne '1' ) {
        !          2343:                         my $title =
        !          2344:                           &Apache::lonnet::gettitle(
        !          2345:                             $helper->{'VARS'}->{'symb'} );
        !          2346:                         $title = &Apache::lonxml::latex_special_symbols($title);
        !          2347:                         $texversion .=
        !          2348:                             '\vskip 0 mm \noindent\textbf{' 
        !          2349:                           . $title
        !          2350:                           . '}\vskip 0 mm ';
        !          2351:                         $texversion .=
        !          2352:                           &path_to_problem( $cleanURL, $LaTeXwidth );
        !          2353:                     }
        !          2354:                     else {
        !          2355:                         $texversion .=
        !          2356: '\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
        !          2357:                         my $URLpath = $cleanURL;
        !          2358:                         $URLpath =~ s/~([^\/]+)/public_html\/$1\/$1/;
        !          2359:                         $texversion .=
        !          2360:                           &path_to_problem( $URLpath, $LaTeXwidth );
        !          2361:                     }
        !          2362:                     $texversion .= '\vskip 1 mm ' . $answer . '\end{document}';
        !          2363:                 }
        !          2364: 
        !          2365:             }
        !          2366: 
        !          2367:             # Print annotations.
        !          2368: 
        !          2369:             if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          2370:                 my $annotation .= &annotate($currentURL);
        !          2371:                 $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
        !          2372:             }
        !          2373: 
        !          2374:             if ( $helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes' ) {
        !          2375:                 $texversion = &IndexCreation( $texversion, $currentURL );
        !          2376:             }
        !          2377:             if ( $helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes' ) {
        !          2378:                 $texversion =~
        !          2379: s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$currentURL| \\strut\\\\\\strut /;
        !          2380: 
        !          2381:             }
        !          2382:             $result .= $texversion;
        !          2383:             if ( $currentURL =~ m/\.page\s*$/ ) {
        !          2384:                 ( $result, $number_of_columns ) = &page_cleanup($result);
        !          2385:             }
        !          2386:         }
        !          2387:         elsif ($cleanURL !~ m|^/adm/|
        !          2388:             && $currentURL =~ /\.(sequence|page)$/
        !          2389:             && $helper->{'VARS'}->{'construction'} eq '1' )
        !          2390:         {
        !          2391: 
        !          2392:             #printing content of sequence from the construction space
        !          2393: 
        !          2394:             $currentURL =~ s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;
        !          2395:             $result .=
        !          2396:               &print_construction_sequence( $currentURL, $helper, %form,
        !          2397:                 $LaTeXwidth );
        !          2398:             $result .= '\end{document}';
        !          2399:             if ( !( $result =~ /\\begin\{document\}/ ) ) {
        !          2400:                 $result = &print_latex_header() . $result;
        !          2401:             }
        !          2402: 
        !          2403:             # End construction space sequence.
        !          2404:         }
        !          2405:         elsif ( $cleanURL =~ /\/(smppg|syllabus|aboutme|bulletinboard)$/ ) {
        !          2406:             $form{'latex_type'} = $helper->{'VARS'}->{'LATEX_TYPE'};
        !          2407:             if ( $currentURL =~ /\/syllabus$/ ) { $currentURL =~ s/\/res//; }
        !          2408:             $resources_printed .= $currentURL . ':';
        !          2409:             my $texversion =
        !          2410:               &ssi_with_retries( $currentURL, $ssi_retry_count, %form );
        !          2411:             if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          2412:                 my $annotation = &annotate($currentURL);
        !          2413:                 $texversion =~ s/(\\end{document})/$annotation$1/;
        !          2414:             }
        !          2415:             $result .= $texversion;
        !          2416:         }
        !          2417:         elsif ( $cleanURL =~ /\.tex$/ ) {
1.511     foxr     2418: 
1.575.2.1! foxr     2419:            # For this sort of print of a single LaTeX file,
        !          2420:            # We can just print the LaTeX file as it is uninterpreted in any way:
        !          2421:            #
        !          2422: 
        !          2423:             $result = &fetch_raw_resource($currentURL);
        !          2424:             if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          2425:                 my $annotation = &annotate($currentURL);
        !          2426:                 $result =~ s/(\\end{document})/$annotation$1/;
        !          2427:             }
        !          2428: 
        !          2429:             $do_postprocessing = 0;    # Don't massage the result.
        !          2430: 
        !          2431:         }
        !          2432:         elsif ( $cleanURL =~ /\.pdf$/i ) {
        !          2433:             $result .= &include_pdf($cleanURL);
        !          2434:             $result .= '\end{document}';
        !          2435:         }
        !          2436:         elsif ( $cleanURL =~ /\.page$/i )
        !          2437:         {    #  Print page in non construction space contexts.
        !          2438: 
        !          2439:             # Determine the set of resources in the map of the page:
        !          2440: 
        !          2441:             my $navmap         = Apache::lonnavmaps::navmap->new();
        !          2442:             my @page_resources = $navmap->retrieveResources($cleanURL);
        !          2443:             $result .= &print_page_in_course( $helper, $rparmhash, $cleanURL,
        !          2444:                 \@page_resources );
        !          2445: 
        !          2446:         }
        !          2447:         else {
        !          2448:             $result .= &unsupported(
        !          2449:                 $currentURL,
        !          2450:                 $helper->{'VARS'}->{'LATEX_TYPE'},
        !          2451:                 $helper->{'VARS'}->{'symb'}
        !          2452:             );
        !          2453:         }
        !          2454:     }
        !          2455:     elsif (
        !          2456:            ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems' )
        !          2457:         or ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_in_page' )
        !          2458:         or ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_resources_in_page' )
        !          2459:         or ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_pages' )
        !          2460:         or ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems' )
        !          2461:         or ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_resources' )
        !          2462:         or    # BUGBUG
        !          2463:         ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences' )
        !          2464:       )
        !          2465:     {
1.511     foxr     2466: 
1.141     sakharuk 2467:         #-- produce an output string
1.575.2.1! foxr     2468:         if (   ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems' )
        !          2469:             or ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_in_page' ) )
        !          2470:         {
        !          2471:             $selectionmade = 2;
        !          2472:         }
        !          2473:         elsif (( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_pages' )
        !          2474:             or ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_resources_in_page' )
        !          2475:           )
        !          2476:         {
        !          2477:             $selectionmade = 3;
        !          2478:         }
        !          2479:         elsif ( ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems' ) ) {
        !          2480:             $selectionmade = 4;
        !          2481:         }
        !          2482:         elsif ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_resources' ) { #BUGBUG
        !          2483:             $selectionmade = 4;
        !          2484:         }
        !          2485:         elsif ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences' ) {
        !          2486:             $selectionmade = 7;
        !          2487:         }
        !          2488:         $form{'problem_split'}     = $parmhash{'problem_stream_switch'};
        !          2489:         $form{'suppress_tries'}    = $parmhash{'suppress_tries'};
        !          2490:         $form{'latex_type'}        = $helper->{'VARS'}->{'LATEX_TYPE'};
        !          2491:         $form{'print_discussions'} = $helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
        !          2492:         $form{'print_annotations'} = $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
        !          2493:         if (   ( $helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes' )
        !          2494:             || ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) )
        !          2495:         {
        !          2496:             $form{'problem_split'} = 'yes';
        !          2497:         }
        !          2498:         my $flag_latex_header_remove = 'NO';
        !          2499:         my $flag_page_in_sequence    = 'NO';
        !          2500:         my @master_seq     = split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
        !          2501:         my $prevassignment = '';
        !          2502: 
        !          2503:         &Apache::lonxml::clear_problem_counter();
        !          2504: 
        !          2505:         my $pbreakresources = keys %page_breaks;
        !          2506:         for ( my $i = 0 ; $i <= $#master_seq ; $i++ ) {
        !          2507: 
        !          2508:             &Apache::lonenc::reset_enc();
        !          2509: 
        !          2510:             # Note due to document structure, not allowed to put \newpage
        !          2511:             # prior to the first resource
        !          2512: 
        !          2513:             if ( defined $page_breaks{ $master_seq[$i] } ) {
        !          2514:                 if ( $i != 0 ) {
        !          2515:                     $result .= "\\newpage\n";
        !          2516:                 }
        !          2517:             }
        !          2518:             $result .= &get_extra_vspaces( $helper, $master_seq[$i] );
        !          2519:             my ( $sequence, $middle_thingy, $urlp ) =
        !          2520:               &Apache::lonnet::decode_symb( $master_seq[$i] );
        !          2521:             $urlp = &Apache::lonnet::clutter($urlp);
        !          2522:             $form{'symb'} = $master_seq[$i];
        !          2523: 
        !          2524:             my $assignment =
        !          2525:               &Apache::lonxml::latex_special_symbols(
        !          2526:                 &Apache::lonnet::gettitle($sequence), 'header' )
        !          2527:               ;    #title of the assignment which contains this problem
        !          2528: 
        !          2529:             if ( $selectionmade == 7 ) {
        !          2530:                 $helper->{VARS}->{'assignment'} = $assignment;
        !          2531:             }
        !          2532:             if ( $i == 0 ) { $prevassignment = $assignment; }
        !          2533:             my $texversion = '';
        !          2534:             if (   $urlp !~ m|^/adm/|
        !          2535:                 && $urlp =~
        !          2536: /\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/
        !          2537:               )
        !          2538:             {
        !          2539:                 $resources_printed .= $urlp . ':';
        !          2540:                 &Apache::lonxml::remember_problem_counter();
        !          2541:                 if ( $flag_latex_header_remove eq 'NO' ) {
        !          2542:                     $texversion .=
        !          2543:                       &print_latex_header( $helper->{'VARS'}->{'LATEX_TYPE'} )
        !          2544:                       ;    # RF
        !          2545:                     $flag_latex_header_remove = 'YES';
        !          2546:                 }
        !          2547:                 $texversion .=
        !          2548:                   &ssi_with_retries( $urlp, $ssi_retry_count, %form );
        !          2549:                 if ( $urlp =~ /\.page$/ ) {
        !          2550:                     ( $texversion, my $number_of_columns_page ) =
        !          2551:                       &page_cleanup($texversion);
        !          2552:                     if ( $number_of_columns_page > $number_of_columns ) {
        !          2553:                         $number_of_columns = $number_of_columns_page;
        !          2554:                     }
        !          2555:                     $texversion =~ s/\\end{document}\d*/\\end{document}/;
        !          2556:                     $flag_page_in_sequence = 'YES';
        !          2557:                 }
        !          2558: 
        !          2559:                 if (   ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' )
        !          2560:                     || ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only' ) )
        !          2561:                 {
        !          2562: 
        !          2563:                     #  Don't permanently pervert the %form hash
        !          2564:                     my %answerform = %form;
        !          2565:                     $answerform{'grade_target'}       = 'answer';
        !          2566:                     $answerform{'answer_output_mode'} = 'tex';
        !          2567:                     $resources_printed .= $urlp . ':';
        !          2568: 
        !          2569:                     &Apache::lonxml::restore_problem_counter();
        !          2570:                     my $answer =
        !          2571:                       &ssi_with_retries( $urlp, $ssi_retry_count, %answerform );
        !          2572: 
        !          2573:                     if ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' ) {
        !          2574:                         $texversion =~
        !          2575:                           s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
        !          2576:                     }
        !          2577:                     else {
        !          2578:                         if ( $urlp =~
        !          2579:                             /\.(problem|exam|quiz|assess|survey|form|library)$/
        !          2580:                           )
        !          2581:                         {
        !          2582:                             $texversion =
        !          2583:                               &print_latex_header(
        !          2584:                                 $helper->{'VARS'}->{'LATEX_TYPE'} );
        !          2585:                             $texversion =~ s/\\begin{document}//;
        !          2586:                             my $title =
        !          2587:                               &Apache::lonnet::gettitle( $master_seq[$i] );
        !          2588:                             $title =
        !          2589:                               &Apache::lonxml::latex_special_symbols($title);
        !          2590:                             my $body =
        !          2591:                                 '\vskip 0 mm \noindent\textbf{' 
        !          2592:                               . $title
        !          2593:                               . '}\vskip 0 mm ';
        !          2594:                             $body .= &path_to_problem( $urlp, $LaTeXwidth );
        !          2595:                             $body .= '\vskip 1 mm ' . $answer;
        !          2596:                             $body = &encapsulate_minipage($body);
        !          2597:                             $texversion .= $body;
        !          2598:                         }
        !          2599:                         else {
        !          2600:                             $texversion = '';
        !          2601:                         }
        !          2602:                     }
        !          2603: 
        !          2604:                 }
        !          2605:                 if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          2606:                     my $annotation .= &annotate($urlp);
        !          2607:                     $texversion =~
        !          2608:                       s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
        !          2609:                 }
        !          2610: 
        !          2611:                 if ( $flag_latex_header_remove ne 'NO' ) {
        !          2612:                     $texversion = &latex_header_footer_remove($texversion);
        !          2613:                 }
        !          2614:                 else {
        !          2615:                     $texversion =~ s/\\end{document}//;
        !          2616:                 }
        !          2617:                 if ( $helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes' ) {
        !          2618:                     $texversion = &IndexCreation( $texversion, $urlp );
        !          2619:                 }
        !          2620:                 if (    ( $selectionmade == 4 )
        !          2621:                     and ( $assignment ne $prevassignment ) )
        !          2622:                 {
        !          2623:                     my $name         = &get_name();
        !          2624:                     my $courseidinfo = &get_course();
        !          2625:                     $prevassignment = $assignment;
        !          2626:                     my $header_text = $parmhash{'print_header_format'};
        !          2627:                     $header_text = &format_page_header(
        !          2628:                         $textwidth,    $header_text, $assignment,
        !          2629:                         $courseidinfo, $name
        !          2630:                     );
        !          2631: 
        !          2632:                     if ( $numberofcolumns eq '1' ) {
        !          2633:                         $result .=
        !          2634: '\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{'
        !          2635:                           . $header_text
        !          2636:                           . '}} \vskip 5 mm ';
        !          2637:                     }
        !          2638:                     else {
        !          2639:                         $result .=
        !          2640: '\newpage \noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{'
        !          2641:                           . $header_text
        !          2642:                           . '}} \vskip 5 mm ';
        !          2643:                     }
        !          2644:                 }
        !          2645:                 $result .= $texversion;
        !          2646:                 $flag_latex_header_remove = 'YES';
        !          2647:             }
        !          2648:             elsif ( $urlp =~ /\/(smppg|syllabus|aboutme|bulletinboard)$/ ) {
        !          2649:                 $form{'latex_type'} = $helper->{'VARS'}->{'LATEX_TYPE'};
        !          2650:                 if ( $urlp =~ /\/syllabus$/ ) { $urlp =~ s/\/res//; }
        !          2651:                 $resources_printed .= $urlp . ':';
        !          2652:                 my $texversion =
        !          2653:                   &ssi_with_retries( $urlp, $ssi_retry_count, %form );
        !          2654:                 if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          2655:                     my $annotation = &annotate($urlp);
        !          2656:                     $texversion =~ s/(\\end{document)/$annotation$1/;
        !          2657:                 }
        !          2658: 
        !          2659:                 if ( $flag_latex_header_remove ne 'NO' ) {
        !          2660:                     $texversion = &latex_header_footer_remove($texversion);
        !          2661:                 }
        !          2662:                 else {
        !          2663:                     $texversion =~
        !          2664: s/\\end{document}/\\vskip 0\.5mm\\noindent\\makebox\[\\textwidth\/\$number_of_columns\]\[b\]\{\\hrulefill\}/;
        !          2665:                 }
        !          2666:                 $result .= $texversion;
        !          2667:                 $flag_latex_header_remove = 'YES';
        !          2668:             }
        !          2669:             elsif ( $urlp =~ /\.pdf$/i ) {
        !          2670:                 if ( $i > 0 ) {
        !          2671:                     $result .= '\cleardoublepage';
        !          2672:                 }
        !          2673:                 $result .= &include_pdf($urlp);
        !          2674:                 if ( $i != $#master_seq ) {
        !          2675:                     if ( $numberofcolumns eq '1' ) {
        !          2676:                         $result .= '\newpage';
        !          2677:                     }
        !          2678:                     else {
        !          2679: 
        !          2680:              # the \\'s seem to be needed to let LaTeX know there's something
        !          2681:              # on the page since LaTeX seems to not like to clear an empty page.
        !          2682:              #
        !          2683:                         $result .= '\\ \cleardoublepage';
        !          2684:                     }
        !          2685:                 }
        !          2686:                 $flag_latex_header_remove = 'YES';
        !          2687: 
        !          2688:             }
        !          2689:             else {
        !          2690:                 $texversion =
        !          2691:                   &unsupported( $urlp, $helper->{'VARS'}->{'LATEX_TYPE'},
        !          2692:                     $master_seq[$i] );
        !          2693:                 if ( $flag_latex_header_remove ne 'NO' ) {
        !          2694:                     $texversion = &latex_header_footer_remove($texversion);
        !          2695:                 }
        !          2696:                 else {
        !          2697:                     $texversion =~ s/\\end{document}//;
        !          2698:                 }
        !          2699:                 $result .= $texversion;
        !          2700:                 $flag_latex_header_remove = 'YES';
        !          2701:             }
        !          2702:             if ( &Apache::loncommon::connection_aborted($r) ) {
        !          2703:                 last;
        !          2704:             }
        !          2705:         }
        !          2706:         &Apache::lonxml::clear_problem_counter();
        !          2707:         if ( $flag_page_in_sequence eq 'YES' ) {
        !          2708:             $result =~
        !          2709:               s/\\usepackage{calc}/\\usepackage{calc}\\usepackage{longtable}/;
        !          2710:         }
        !          2711:         $result .= '\end{document}';
        !          2712:     }
        !          2713:     elsif (
        !          2714:         ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students' )
        !          2715:         || ( $helper->{'VARS'}->{'PRINT_TYPE'} eq
        !          2716:             'problems_for_students_from_page' )
        !          2717:         || ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems_students' )
        !          2718:         || ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_students' )
        !          2719:       )
        !          2720:     {
        !          2721: 
        !          2722:         #-- prints assignments for whole class or for selected students
        !          2723:         my $type;
        !          2724:         if (
        !          2725:             ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students' )
        !          2726:             || ( $helper->{'VARS'}->{'PRINT_TYPE'} eq
        !          2727:                 'problems_for_students_from_page' )
        !          2728:             || ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems_students' )
        !          2729:           )
        !          2730:         {
        !          2731:             $selectionmade = 5;
        !          2732:             $type          = 'problems';
        !          2733:         }
        !          2734:         elsif ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_students' )
        !          2735:         {
        !          2736:             $selectionmade = 8;
        !          2737:             $type          = 'resources';
        !          2738:         }
        !          2739:         my @students = split /\|\|\|/, $helper->{'VARS'}->{'STUDENTS'};
        !          2740: 
        !          2741:      #   The normal sort order is by section then by students within the
        !          2742:      #   section. If the helper var student_sort is 1, then the user has elected
        !          2743:      #   to override this and output the students by name.
        !          2744:      #    Each element of the students array is of the form:
        !          2745:      #       username:domain:section:last, first:status
        !          2746:      #
        !          2747:      #  Note that student sort is not compatible with printing
        !          2748:      #  1 section per pdf...so that setting overrides.
        !          2749:      #
        !          2750:         if (   ( $helper->{'VARS'}->{'student_sort'} eq 1 )
        !          2751:             && ( $helper->{'VARS'}->{'SPLIT_PDFS'} ne "sections" ) )
        !          2752:         {
        !          2753:             @students = sort compare_names @students;
        !          2754:         }
        !          2755:         &adjust_number_to_print($helper);
        !          2756: 
        !          2757:         if (   $helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq '0'
        !          2758:             || $helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'all' )
        !          2759:         {
        !          2760:             $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = $#students + 1;
        !          2761:         }
        !          2762: 
        !          2763:         # If we are splitting on section boundaries, we need
        !          2764:         # to remember that in split_on_sections and
        !          2765:         # print all of the students in the list.
        !          2766:         #
        !          2767:         my $split_on_sections = 0;
        !          2768:         if ( $helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'section' ) {
        !          2769:             $split_on_sections = 1;
        !          2770:             $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = $#students + 1;
        !          2771:         }
        !          2772:         my @master_seq = split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
        !          2773: 
        !          2774:         #loop over students
        !          2775: 
        !          2776:         my $flag_latex_header_remove = 'NO';
        !          2777:         my %moreenv;
        !          2778:         $moreenv{'instructor_comments'} = 'hide';
        !          2779:         $moreenv{'textwidth'} = &get_textwidth( $helper, $LaTeXwidth );
        !          2780:         $moreenv{'print_discussions'} =
        !          2781:           $helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
        !          2782:         $moreenv{'print_annotations'} =
        !          2783:           $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
        !          2784:         $moreenv{'problem_split'}  = $parmhash{'problem_stream_switch'};
        !          2785:         $moreenv{'suppress_tries'} = $parmhash{'suppress_tries'};
        !          2786: 
        !          2787:         if (   ( $helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes' )
        !          2788:             || ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) )
        !          2789:         {
        !          2790:             $moreenv{'problem_split'} = 'yes';
        !          2791:         }
        !          2792:         my %prog_state = &Apache::lonhtmlcommon::Create_PrgWin(
        !          2793:             $r, 'Print Status',
        !          2794:             'Class Print Status',
        !          2795:             $#students + 1,
        !          2796:             'inline', '75'
        !          2797:         );
        !          2798:         my $student_counter = -1;
        !          2799:         my $i               = 0;
        !          2800:         my $last_section    = ( split( /:/, $students[0] ) )[2];
        !          2801:         foreach my $person (@students) {
        !          2802: 
        !          2803:             my $duefile =
        !          2804: "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due";
        !          2805:             if ( -e $duefile ) {
        !          2806:                 my $temp_file = Apache::File->new( '>>' . $duefile );
        !          2807:                 print $temp_file "1969\n";
        !          2808:             }
        !          2809:             $student_counter++;
        !          2810:             if ($split_on_sections) {
        !          2811:                 my $this_section = ( split( /:/, $person ) )[2];
        !          2812:                 if ( $this_section ne $last_section ) {
        !          2813:                     $i++;
        !          2814:                     $last_section = $this_section;
        !          2815:                 }
        !          2816:             }
        !          2817:             else {
        !          2818:                 $i = int(
        !          2819:                     $student_counter / $helper->{'VARS'}{'NUMBER_TO_PRINT'} );
        !          2820:             }
        !          2821:             my ( $output, $fullname, $printed ) =
        !          2822:               &print_resources( $r, $helper, $person, $type, \%moreenv,
        !          2823:                 \@master_seq, $flag_latex_header_remove, $LaTeXwidth );
        !          2824:             $resources_printed .= ":";
        !          2825:             $print_array[$i]   .= $output;
        !          2826:             $student_names[$i] .= $person . ':' . $fullname . '_END_';
        !          2827:             &Apache::lonhtmlcommon::Increment_PrgWin( $r, \%prog_state,
        !          2828:                 &mt('last student') . ' ' . $fullname );
        !          2829:             $flag_latex_header_remove = 'YES';
        !          2830:             if ( &Apache::loncommon::connection_aborted($r) ) { last; }
        !          2831:         }
        !          2832:         &Apache::lonhtmlcommon::Close_PrgWin( $r, \%prog_state );
        !          2833:         $result .= $print_array[0] . '  \end{document}';
        !          2834:     }
        !          2835:     elsif (( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon' )
        !          2836:         || ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon_page' )
        !          2837:         || ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon' ) )
        !          2838:     {
        !          2839:         my $cdom = $env{ 'course.' . $env{'request.course.id'} . '.domain' };
        !          2840:         my $cnum = $env{ 'course.' . $env{'request.course.id'} . '.num' };
        !          2841:         my $num_todo      = $helper->{'VARS'}->{'NUMBER_TO_PRINT_TOTAL'};
        !          2842:         my $code_name     = $helper->{'VARS'}->{'ANON_CODE_STORAGE_NAME'};
        !          2843:         my $old_name      = $helper->{'VARS'}->{'REUSE_OLD_CODES'};
        !          2844:         my $single_code   = $helper->{'VARS'}->{'SINGLE_CODE'};
        !          2845:         my $selected_code = $helper->{'VARS'}->{'CODE_SELECTED_FROM_LIST'};
        !          2846: 
        !          2847:         my $code_option = $helper->{'VARS'}->{'CODE_OPTION'};
        !          2848:         my @lines       = &Apache::grades::get_scantronformat_file();
        !          2849:         my ( $code_type, $code_length ) = ( 'letter', 6 );
        !          2850:         foreach my $line (@lines) {
        !          2851:             my ( $name, $type, $length ) = ( split( /:/, $line ) )[ 0, 2, 4 ];
        !          2852:             if ( $name eq $code_option ) {
        !          2853:                 $code_length = $length;
        !          2854:                 if ( $type eq 'number' ) { $code_type = 'number'; }
        !          2855:             }
        !          2856:         }
        !          2857:         my %moreenv = ( 'textwidth' => &get_textwidth( $helper, $LaTeXwidth ) );
        !          2858:         $moreenv{'problem_split'}       = $parmhash{'problem_stream_switch'};
        !          2859:         $moreenv{'instructor_comments'} = 'hide';
        !          2860:         my $seed = time + ( $$ << 16 ) + ($$);
        !          2861:         my @allcodes;
        !          2862:         if ($old_name) {
        !          2863:             my %result =
        !          2864:               &Apache::lonnet::get( 'CODEs', [ $old_name, "type\0$old_name" ],
        !          2865:                 $cdom, $cnum );
        !          2866:             $code_type = $result{"type\0$old_name"};
        !          2867:             @allcodes  = split( ',', $result{$old_name} );
        !          2868:             $num_todo  = scalar(@allcodes);
        !          2869:         }
        !          2870:         elsif ($selected_code) {    # Selection value is always numeric.
        !          2871:             $num_todo = 1;
        !          2872:             @allcodes = ($selected_code);
        !          2873:         }
        !          2874:         elsif ($single_code) {
        !          2875: 
        !          2876:             $num_todo = 1;          # Unconditionally one code to do.
        !          2877:                  # If an alpha code have to convert to numbers so it can be
        !          2878:                  # converted back to letters again :-)
        !          2879:                  #
        !          2880:             if ( $code_type ne 'number' ) {
        !          2881:                 $single_code = &letters_to_num($single_code);
        !          2882:             }
        !          2883:             @allcodes = ($single_code);
        !          2884:         }
        !          2885:         else {
        !          2886:             my %allcodes;
        !          2887:             srand($seed);
        !          2888:             for ( my $i = 0 ; $i < $num_todo ; $i++ ) {
        !          2889:                 $moreenv{'CODE'} =
        !          2890:                   &get_CODE( \%allcodes, $i, $seed, $code_length, $code_type );
        !          2891:             }
        !          2892:             if ($code_name) {
        !          2893:                 &Apache::lonnet::put(
        !          2894:                     'CODEs',
        !          2895:                     {
        !          2896:                         $code_name         => join( ',', keys(%allcodes) ),
        !          2897:                         "type\0$code_name" => $code_type
        !          2898:                     },
        !          2899:                     $cdom, $cnum
        !          2900:                 );
        !          2901:             }
        !          2902:             @allcodes = keys(%allcodes);
        !          2903:         }
        !          2904:         my @master_seq = split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
        !          2905:         my ($type) = split( /_/, $helper->{'VARS'}->{'PRINT_TYPE'} );
        !          2906:         &adjust_number_to_print($helper);
        !          2907:         my $number_per_page = $helper->{'VARS'}->{'NUMBER_TO_PRINT'};
        !          2908:         if ( $number_per_page eq '0' || $number_per_page eq 'all' ) {
        !          2909:             $number_per_page = $num_todo;
        !          2910:         }
        !          2911:         my $flag_latex_header_remove = 'NO';
        !          2912:         my %prog_state =
        !          2913:           &Apache::lonhtmlcommon::Create_PrgWin( $r, 'Print Status',
        !          2914:             'Class Print Status',
        !          2915:             $num_todo, 'inline', '75' );
        !          2916:         my $count = 0;
        !          2917:         foreach my $code ( sort(@allcodes) ) {
        !          2918:             my $file_num = int( $count / $number_per_page );
        !          2919:             if ( $code_type eq 'number' ) {
        !          2920:                 $moreenv{'CODE'} = $code;
        !          2921:             }
        !          2922:             else {
        !          2923:                 $moreenv{'CODE'} = &num_to_letters($code);
        !          2924:             }
        !          2925:             my ( $output, $fullname, $printed ) =
        !          2926:               &print_resources( $r, $helper, 'anonymous', $type, \%moreenv,
        !          2927:                 \@master_seq, $flag_latex_header_remove, $LaTeXwidth );
        !          2928:             $resources_printed .= ":";
        !          2929:             $print_array[$file_num] .= $output;
        !          2930:             &Apache::lonhtmlcommon::Increment_PrgWin( $r, \%prog_state,
        !          2931:                 &mt('last assignment') . ' ' . $fullname );
        !          2932:             $flag_latex_header_remove = 'YES';
        !          2933:             $count++;
        !          2934:             if ( &Apache::loncommon::connection_aborted($r) ) { last; }
        !          2935:         }
        !          2936:         &Apache::lonhtmlcommon::Close_PrgWin( $r, \%prog_state );
        !          2937:         $result .= $print_array[0] . '  \end{document}';
        !          2938:     }
        !          2939:     elsif ( $helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_from_directory' ) {
        !          2940: 
        !          2941:         #prints selected problems from the subdirectory
        !          2942:         $selectionmade = 6;
        !          2943:         my @list_of_files = split /\|\|\|/, $helper->{'VARS'}->{'FILES'};
        !          2944:         @list_of_files = sort @list_of_files;
        !          2945:         my $flag_latex_header_remove = 'NO';
        !          2946:         my $rndseed                  = time;
        !          2947:         if ( $helper->{'VARS'}->{'curseed'} ) {
        !          2948:             $rndseed = $helper->{'VARS'}->{'curseed'};
        !          2949:         }
        !          2950:         for ( my $i = 0 ; $i <= $#list_of_files ; $i++ ) {
1.521     foxr     2951: 
1.575.2.1! foxr     2952:             &Apache::lonenc::reset_enc();
        !          2953: 
        !          2954:             my $urlp = $list_of_files[$i];
        !          2955:             $urlp =~ s|//|/|;
        !          2956:             if ( $urlp =~ /\// ) {
        !          2957:                 $form{'problem_split'} = $parmhash{'problem_stream_switch'};
        !          2958:                 $form{'rndseed'}       = $rndseed;
        !          2959:                 if ( $urlp =~ m|/home/([^/]+)/public_html| ) {
        !          2960:                     $urlp =~ s|/home/([^/]*)/public_html|/~$1|;
        !          2961:                 }
        !          2962:                 else {
        !          2963:                     $urlp =~ s|^$Apache::lonnet::perlvar{'lonDocRoot'}||;
        !          2964:                 }
        !          2965:                 $resources_printed .= $urlp . ':';
        !          2966:                 my $texversion =
        !          2967:                   &ssi_with_retries( $urlp, $ssi_retry_count, %form );
        !          2968:                 if (   ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' )
        !          2969:                     || ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only' ) )
        !          2970:                 {
        !          2971: 
        !          2972:                     #  Don't permanently pervert %form:
        !          2973:                     my %answerform = %form;
        !          2974:                     $answerform{'grade_target'}       = 'answer';
        !          2975:                     $answerform{'answer_output_mode'} = 'tex';
        !          2976:                     $answerform{'latex_type'} =
        !          2977:                       $helper->{'VARS'}->{'LATEX_TYPE'};
        !          2978:                     $answerform{'rndseed'} = $rndseed;
        !          2979:                     $resources_printed .= $urlp . ':';
        !          2980:                     my $answer =
        !          2981:                       &ssi_with_retries( $urlp, $ssi_retry_count, %answerform );
        !          2982: 
        !          2983:                     if ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' ) {
        !          2984:                         $texversion =~
        !          2985:                           s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
        !          2986:                     }
        !          2987:                     else {
        !          2988:                         $texversion =
        !          2989:                           &print_latex_header(
        !          2990:                             $helper->{'VARS'}->{'LATEX_TYPE'} );
        !          2991:                         if ( $helper->{'VARS'}->{'construction'} ne '1' ) {
        !          2992:                             $texversion .= '\vskip 0 mm \noindent ';
        !          2993:                             $texversion .=
        !          2994:                               &path_to_problem( $urlp, $LaTeXwidth );
        !          2995:                         }
        !          2996:                         else {
        !          2997:                             $texversion .=
        !          2998: '\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
        !          2999:                             my $URLpath = $urlp;
        !          3000:                             $URLpath =~ s/~([^\/]+)/public_html\/$1\/$1/;
        !          3001:                             $texversion .=
        !          3002:                               &path_to_problem( $URLpath, $LaTeXwidth );
        !          3003:                         }
        !          3004:                         $texversion .=
        !          3005:                           '\vskip 1 mm ' . $answer . '\end{document}';
        !          3006:                     }
        !          3007:                 }
1.521     foxr     3008: 
1.515     foxr     3009:                 #this chunk is responsible for printing the path to problem
                   3010: 
1.575.2.1! foxr     3011:                 my $newurlp = $urlp;
        !          3012:                 if ( $newurlp =~ /~/ ) {
        !          3013:                     $newurlp =~ s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;
        !          3014:                 }
        !          3015:                 $newurlp = &path_to_problem( $newurlp, $LaTeXwidth );
        !          3016:                 $texversion =~ s/(\\begin{minipage}{\\textwidth})/$1 $newurlp/;
        !          3017:                 if ( $flag_latex_header_remove ne 'NO' ) {
        !          3018:                     $texversion = &latex_header_footer_remove($texversion);
        !          3019:                 }
        !          3020:                 else {
        !          3021:                     $texversion =~ s/\\end{document}//;
        !          3022:                 }
        !          3023:                 if ( $helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes' ) {
        !          3024:                     $texversion = &IndexCreation( $texversion, $urlp );
        !          3025:                 }
        !          3026:                 if ( $helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes' ) {
        !          3027:                     $texversion =~
        !          3028: s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /;
        !          3029: 
        !          3030:                 }
        !          3031:                 $result .= $texversion;
        !          3032:             }
        !          3033:             $flag_latex_header_remove = 'YES';
        !          3034:         }
        !          3035:         if ( $helper->{VARS}->{'construction'} eq '1' ) {
        !          3036:             $result =~ s/(\\typeout)/ RANDOM SEED IS $rndseed $1/;
        !          3037:         }
        !          3038:         $result .= '\end{document}';
1.140     sakharuk 3039:     }
1.575.2.1! foxr     3040: 
1.140     sakharuk 3041: #-------------------------------------------------------- corrections for the different page formats
1.499     foxr     3042: 
1.575.2.1! foxr     3043: # Only post process if that has not been turned off e.g. by a raw latex resource.
1.499     foxr     3044: 
                   3045:     if ($do_postprocessing) {
1.575.2.1! foxr     3046:         $result = &page_format_transformation(
        !          3047:             $papersize,
        !          3048:             $laystyle,
        !          3049:             $numberofcolumns,
        !          3050:             $helper->{'VARS'}->{'PRINT_TYPE'},
        !          3051:             $result,
        !          3052:             $helper->{VARS}->{'assignment'},
        !          3053:             $helper->{'VARS'}->{'TABLE_CONTENTS'},
        !          3054:             $helper->{'VARS'}->{'TABLE_INDEX'},
        !          3055:             $selectionmade
        !          3056:         );
        !          3057:         $result =
        !          3058:           &latex_corrections( $number_of_columns, $result, $selectionmade,
        !          3059:             $helper->{'VARS'}->{'ANSWER_TYPE'} );
        !          3060: 
        !          3061:         #if ($numberofcolumns == 1) {
        !          3062:         $result =~
        !          3063: s/\\textwidth\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textwidth= $helper->{'VARS'}->{'pagesize.width'} $helper->{'VARS'}->{'pagesize.widthunit'} /;
        !          3064:         $result =~
        !          3065: s/\\textheight\s*=?\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textheight $helper->{'VARS'}->{'pagesize.height'} $helper->{'VARS'}->{'pagesize.heightunit'} /;
        !          3066:         $result =~
        !          3067: s/\\evensidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\evensidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /;
        !          3068:         $result =~
        !          3069: s/\\oddsidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\oddsidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /;
        !          3070: 
        !          3071:         #}
1.499     foxr     3072:     }
1.367     foxr     3073: 
1.515     foxr     3074:     # Set URLback if this is a construction space print so we can provide
                   3075:     # a link to the resource being edited.
                   3076:     #
1.274     sakharuk 3077: 
1.575.2.1! foxr     3078:     my $URLback = '';    #link to original document
        !          3079:     if ( $helper->{'VARS'}->{'construction'} eq '1' ) {
        !          3080: 
        !          3081:         #prints resource from the construction space
        !          3082:         $URLback = '/' . $helper->{'VARS'}->{'filename'};
        !          3083:         if ( $URLback =~ /([^?]+)/ ) {
        !          3084:             $URLback = $1;
        !          3085:             $URLback =~ s|^/~|/priv/|;
        !          3086:         }
1.276     sakharuk 3087:     }
1.575.2.1! foxr     3088: 
1.556     foxr     3089:     #
                   3090:     # Final adjustment of the font size:
                   3091:     #
                   3092: 
                   3093:     $result = set_font_size($result);
1.375     foxr     3094: 
1.575.2.1! foxr     3095:     #-- writing .tex file in prtspool
1.525     www      3096:     my $temp_file;
                   3097:     my $identifier = &Apache::loncommon::get_cgi_id();
1.575.2.1! foxr     3098:     my $filename =
        !          3099: "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout_$identifier.tex";
        !          3100:     if ( !( $#print_array > 0 ) ) {
        !          3101:         unless ( $temp_file = Apache::File->new( '>' . $filename ) ) {
        !          3102:             $r->log_error("Couldn't open $filename for output $!");
        !          3103:             return SERVER_ERROR;
        !          3104:         }
        !          3105:         print $temp_file $result;
        !          3106:         my $begin = index( $result, '\begin{document}', 0 );
        !          3107:         my $inc = substr( $result, 0, $begin + 16 );
        !          3108:     }
        !          3109:     else {
        !          3110:         my $begin = index( $result, '\begin{document}', 0 );
        !          3111:         my $inc = substr( $result, 0, $begin + 16 );
        !          3112:         for ( my $i = 0 ; $i <= $#print_array ; $i++ ) {
        !          3113:             if ( $i == 0 ) {
        !          3114:                 $print_array[$i] = $result;
        !          3115:             }
        !          3116:             else {
        !          3117:                 $print_array[$i] .= '\end{document}';
        !          3118:                 $print_array[$i] =
        !          3119:                   &latex_corrections( $number_of_columns, $print_array[$i],
        !          3120:                     $selectionmade, $helper->{'VARS'}->{'ANSWER_TYPE'} );
        !          3121: 
        !          3122:                 my $anobegin =
        !          3123:                   index( $print_array[$i], '\setcounter{page}', 0 );
        !          3124:                 substr( $print_array[$i], 0, $anobegin ) = '';
        !          3125:                 $print_array[$i] = $inc . $print_array[$i];
        !          3126:             }
        !          3127:             my $temp_file;
        !          3128:             my $newfilename = $filename;
        !          3129:             my $num         = $i + 1;
        !          3130:             $newfilename =~ s/\.tex$//;
        !          3131:             $newfilename = sprintf( "%s_%03d.tex", $newfilename, $num );
        !          3132:             unless ( $temp_file = Apache::File->new( '>' . $newfilename ) ) {
        !          3133:                 $r->log_error("Couldn't open $newfilename for output $!");
        !          3134:                 return SERVER_ERROR;
        !          3135:             }
        !          3136:             print $temp_file $print_array[$i];
        !          3137:         }
        !          3138:     }
        !          3139:     my $student_names = '';
        !          3140:     if ( $#print_array > 0 ) {
        !          3141:         for ( my $i = 0 ; $i <= $#print_array ; $i++ ) {
        !          3142:             $student_names .= $student_names[$i] . '_ENDPERSON_';
        !          3143:         }
        !          3144:     }
        !          3145:     else {
        !          3146:         if ( $#student_names > -1 ) {
        !          3147:             $student_names = $student_names[0] . '_ENDPERSON_';
        !          3148:         }
        !          3149:         else {
        !          3150:             my $fullname = &get_name( $env{'user.name'}, $env{'user.domain'} );
        !          3151:             $student_names = join( ':',
        !          3152:                 $env{'user.name'}, $env{'user.domain'},
        !          3153:                 $env{'request.course.sec'}, $fullname )
        !          3154:               . '_ENDPERSON_' . '_END_';
        !          3155:         }
        !          3156:     }
        !          3157: 
        !          3158:     # logic for now is too complex to trace if this has been defined
        !          3159:     #  yet.
        !          3160:     my $cnum = $env{ 'course.' . $env{'request.course.id'} . '.num' };
        !          3161:     my $cdom = $env{ 'course.' . $env{'request.course.id'} . '.domain' };
        !          3162:     &Apache::lonnet::appenv(
        !          3163:         {
        !          3164:             'cgi.' . $identifier . '.file'      => $filename,
        !          3165:             'cgi.' . $identifier . '.layout'    => $laystyle,
        !          3166:             'cgi.' . $identifier . '.numcol'    => $numberofcolumns,
        !          3167:             'cgi.' . $identifier . '.paper'     => $papersize,
        !          3168:             'cgi.' . $identifier . '.selection' => $selectionmade,
        !          3169:             'cgi.'
        !          3170:               . $identifier
        !          3171:               . '.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'},
        !          3172:             'cgi.'
        !          3173:               . $identifier
        !          3174:               . '.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'},
        !          3175:             'cgi.' . $identifier . '.role'          => $perm{'pav'},
        !          3176:             'cgi.' . $identifier . '.numberoffiles' => $#print_array,
        !          3177:             'cgi.' . $identifier . '.studentnames'  => $student_names,
        !          3178:             'cgi.' . $identifier . '.backref'       => $URLback,
        !          3179:         }
        !          3180:     );
        !          3181:     &Apache::lonnet::appenv(
        !          3182:         {
        !          3183:             "cgi.$identifier.user"      => $env{'user.name'},
        !          3184:             "cgi.$identifier.domain"    => $env{'user.domain'},
        !          3185:             "cgi.$identifier.courseid"  => $cnum,
        !          3186:             "cgi.$identifier.coursedom" => $cdom,
        !          3187:             "cgi.$identifier.resources" => $resources_printed
        !          3188:         }
        !          3189:     );
        !          3190: 
        !          3191:     my $end_page      = &Apache::loncommon::end_page();
1.529     raeburn  3192:     my $continue_text = &mt('Continue');
1.575.2.1! foxr     3193: 
1.525     www      3194:     # If there's been an unrecoverable SSI error, report it to the user
                   3195:     if ($ssi_error) {
                   3196:         my $helpurl = &Apache::loncommon::top_nav_help('Helpdesk');
1.575.2.1! foxr     3197:         $r->print(
        !          3198:                 '<br /><p class="LC_error">'
        !          3199:               . &mt('An unrecoverable network error occurred:')
        !          3200:               . '</p><p>'
        !          3201:               . &mt(
        !          3202: 'At least one of the resources you chose to print could not be rendered due to an unrecoverable error when communicating with a server:'
        !          3203:               )
        !          3204:               . '<br />'
        !          3205:               . $ssi_last_error_resource
        !          3206:               . '<br />'
        !          3207:               . $ssi_last_error
        !          3208:               . '</p><p>'
        !          3209:               . &mt(
        !          3210: 'You can continue using the link provided below, but make sure to carefully inspect your output file! The errors will be marked in the file.'
        !          3211:               )
        !          3212:               . '<br />'
        !          3213:               . &mt(
        !          3214: 'You may be able to reprint the individual resources for which this error occurred, as the issue may be temporary.'
        !          3215:               )
        !          3216:               . '<br />'
        !          3217:               . &mt(
        !          3218: 'If the error persists, please contact the [_1] for assistance.',
        !          3219:                 $helpurl
        !          3220:               )
        !          3221:               . '</p><p>'
        !          3222:               . &mt('We apologize for the inconvenience.') . '</p>'
        !          3223:               . '<a href="/cgi-bin/printout.pl?'
        !          3224:               . $identifier . '">'
        !          3225:               . $continue_text . '</a>'
        !          3226:               . $end_page
        !          3227:         );
        !          3228:     }
        !          3229:     else {
        !          3230:         $r->print(<<FINALEND);
1.317     albertel 3231: <br />
1.288     albertel 3232: <meta http-equiv="Refresh" content="0; url=/cgi-bin/printout.pl?$identifier" />
1.528     raeburn  3233: <a href="/cgi-bin/printout.pl?$identifier">$continue_text</a>
1.431     albertel 3234: $end_page
1.140     sakharuk 3235: FINALEND
1.575.2.1! foxr     3236:     }    # endif ssi errors.
1.140     sakharuk 3237: }
                   3238: 
1.288     albertel 3239: sub get_CODE {
1.575.2.1! foxr     3240:     my ( $all_codes, $num, $seed, $size, $type ) = @_;
        !          3241:     my $max = '1' . '0' x $size;
1.288     albertel 3242:     my $newcode;
1.575.2.1! foxr     3243:     while (1) {
        !          3244:         $newcode = sprintf( "%0" . $size . "d", int( rand($max) ) );
        !          3245:         if ( !exists( $$all_codes{$newcode} ) ) {
        !          3246:             $$all_codes{$newcode} = 1;
        !          3247:             if ( $type eq 'number' ) {
        !          3248:                 return $newcode;
        !          3249:             }
        !          3250:             else {
        !          3251:                 return &num_to_letters($newcode);
        !          3252:             }
        !          3253:         }
1.288     albertel 3254:     }
                   3255: }
1.140     sakharuk 3256: 
1.284     albertel 3257: sub print_resources {
1.575.2.1! foxr     3258:     my ( $r, $helper, $person, $type, $moreenv, $master_seq,
        !          3259:         $remove_latex_header, $LaTeXwidth )
        !          3260:       = @_;
        !          3261:     my $current_output = '';
        !          3262:     my $printed        = '';
        !          3263:     my ( $username, $userdomain, $usersection ) = split /:/, $person;
        !          3264:     my $fullname = &get_name( $username, $userdomain );
        !          3265:     my $namepostfix =
        !          3266:       "\\\\";    # Both anon and not anon should get the same vspace.
        !          3267:     if ( $person =~ 'anon' ) {
        !          3268:         $namepostfix .= "Name: ";
        !          3269:         $fullname = "CODE - " . $moreenv->{'CODE'};
1.288     albertel 3270:     }
1.575.2.1! foxr     3271: 
1.444     foxr     3272:     #  Fullname may have special latex characters that need \ prefixing:
                   3273:     #
                   3274: 
1.575.2.1! foxr     3275:     my $i = 0;
        !          3276: 
        !          3277:     #goes through all resources, checks if they are available for
        !          3278:     #current student, and produces output
1.428     albertel 3279: 
                   3280:     &Apache::lonxml::clear_problem_counter();
1.575.2.1! foxr     3281:     my %page_breaks = &get_page_breaks($helper);
        !          3282:     my $columns_in_format = ( split( /\|/, $helper->{'VARS'}->{'FORMAT'} ) )[1];
        !          3283: 
1.440     foxr     3284:     #
1.575.2.1! foxr     3285:     #   end each student with a
1.440     foxr     3286:     #   Special that allows the post processor to even out the page
                   3287:     #   counts later.  Nasty problem this... it would be really
                   3288:     #   nice to put the special in as a postscript comment
1.441     foxr     3289:     #   e.g. \special{ps:\ENDOFSTUDENTSTAMP}  unfortunately,
1.440     foxr     3290:     #   The special gets passed the \ and dvips puts it in the output file
1.441     foxr     3291:     #   so we will just rely on prntout.pl to strip  ENDOFSTUDENTSTAMP from the
                   3292:     #   postscript.  Each ENDOFSTUDENTSTAMP will go on a line by itself.
1.440     foxr     3293:     #
1.568     foxr     3294:     my $syllabus_first = 0;
1.575.2.1! foxr     3295:     foreach my $curresline ( @{$master_seq} ) {
        !          3296:         if ( defined $page_breaks{$curresline} ) {
        !          3297:             if ( $i != 0 ) {
        !          3298:                 $current_output .= "\\newpage\n";
        !          3299:             }
        !          3300:         }
        !          3301:         $current_output .= &get_extra_vspaces( $helper, $curresline );
        !          3302:         $i++;
1.511     foxr     3303: 
1.575.2.1! foxr     3304:         if (
        !          3305:             !(
        !          3306:                 $type eq 'problems'
        !          3307:                 && ( $curresline !~
        !          3308:                     m/\.(problem|exam|quiz|assess|survey|form|library)$/ )
        !          3309:             )
        !          3310:           )
        !          3311:         {
        !          3312:             my ( $map, $id, $res_url ) =
        !          3313:               &Apache::lonnet::decode_symb($curresline);
        !          3314:             if ( &Apache::lonnet::allowed( 'bre', $res_url ) ) {
        !          3315:                 if (   $res_url !~ m|^ext/|
        !          3316:                     && $res_url =~
        !          3317: /\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/
        !          3318:                   )
        !          3319:                 {
        !          3320:                     $printed .= $curresline . ':';
        !          3321:                     &Apache::lonxml::remember_problem_counter();
        !          3322: 
        !          3323:                     my $rendered =
        !          3324:                       &get_student_view_with_retries( $curresline,
        !          3325:                         $ssi_retry_count, $username, $userdomain,
        !          3326:                         $env{'request.course.id'},
        !          3327:                         'tex', $moreenv );
        !          3328:                     if (   ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' )
        !          3329:                         || ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only' ) )
        !          3330:                     {
        !          3331: 
        !          3332:         #   Use a copy of the hash so we don't pervert it on future loop passes.
        !          3333:                         my %answerenv = %{$moreenv};
        !          3334:                         $answerenv{'answer_output_mode'} = 'tex';
        !          3335:                         $answerenv{'latex_type'} =
        !          3336:                           $helper->{'VARS'}->{'LATEX_TYPE'};
        !          3337: 
        !          3338:                         &Apache::lonxml::restore_problem_counter();
        !          3339: 
        !          3340:                         my $ansrendered =
        !          3341:                           &Apache::loncommon::get_student_answers( $curresline,
        !          3342:                             $username, $userdomain, $env{'request.course.id'},
        !          3343:                             %answerenv );
        !          3344: 
        !          3345:                         if ( $helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no' ) {
        !          3346:                             $rendered =~
        !          3347:                               s/(\\keephidden{ENDOFPROBLEM})/$ansrendered$1/;
        !          3348:                         }
        !          3349:                         else {
        !          3350: 
        !          3351:                             my $header =
        !          3352:                               &print_latex_header(
        !          3353:                                 $helper->{'VARS'}->{'LATEX_TYPE'} );
        !          3354:                             $header =~ s/\\begin{document}//;    #<<<<<
        !          3355:                             my $title = &Apache::lonnet::gettitle($curresline);
        !          3356:                             $title =
        !          3357:                               &Apache::lonxml::latex_special_symbols($title);
        !          3358:                             my $body =
        !          3359:                                 '\vskip 0 mm \noindent\textbf{' 
        !          3360:                               . $title
        !          3361:                               . '}\vskip 0 mm ';
        !          3362:                             $body .= &path_to_problem( $res_url, $LaTeXwidth );
        !          3363:                             $body .= '\vskip 1 mm ' . $ansrendered;
        !          3364:                             $body     = &encapsulate_minipage($body);
        !          3365:                             $rendered = $header . $body;
        !          3366:                         }
        !          3367:                     }
        !          3368:                     if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          3369:                         my $url        = &Apache::lonnet::clutter($res_url);
        !          3370:                         my $annotation = &annotate($url);
        !          3371:                         $rendered =~
        !          3372:                           s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
        !          3373:                     }
        !          3374:                     my $junk;
        !          3375:                     if ( $remove_latex_header eq 'YES' ) {
        !          3376:                         $rendered = &latex_header_footer_remove($rendered);
        !          3377:                     }
        !          3378:                     else {
        !          3379:                         $rendered =~ s/\\end{document}//;
        !          3380:                     }
        !          3381:                     $current_output .= $rendered;
        !          3382:                 }
        !          3383:                 elsif (
        !          3384:                     $res_url =~ /\/(smppg|syllabus|aboutme|bulletinboard)$/ )
        !          3385:                 {
        !          3386:                     if ( $i == 1 ) {
        !          3387:                         $syllabus_first = 1;
        !          3388:                     }
        !          3389:                     $printed .= $curresline . ':';
        !          3390:                     my $rendered =
        !          3391:                       &get_student_view_with_retries( $curresline,
        !          3392:                         $ssi_retry_count, $username, $userdomain,
        !          3393:                         $env{'request.course.id'},
        !          3394:                         'tex', $moreenv );
        !          3395:                     if ( $helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes' ) {
        !          3396:                         my $url        = &Apache::lonnet::clutter($res_url);
        !          3397:                         my $annotation = &annotate($url);
        !          3398:                         $annotation =~ s/(\\end{document})/$annotation$1/;
        !          3399:                     }
        !          3400:                     if ( $remove_latex_header eq 'YES' ) {
        !          3401:                         $rendered = &latex_header_footer_remove($rendered);
        !          3402:                     }
        !          3403:                     else {
        !          3404:                         $rendered =~ s/\\end{document}//;
        !          3405:                     }
        !          3406:                     $current_output .= $rendered
        !          3407:                       . '\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\strut \vskip 0 mm \strut ';
        !          3408:                 }
        !          3409:                 elsif ( $res_url = ~/\.pdf$/ ) {
        !          3410:                     my $url      = &Apache::lonnet::clutter($res_url);
        !          3411:                     my $rendered = &include_pdf($url);
        !          3412:                     if ( $remove_latex_header ne 'NO' ) {
        !          3413:                         $rendered = &latex_header_footer_remove($rendered);
        !          3414:                     }
        !          3415:                     $current_output .= $rendered;
        !          3416:                 }
        !          3417:                 else {
        !          3418:                     my $rendered =
        !          3419:                       &unsupported( $res_url, $helper->{'VARS'}->{'LATEX_TYPE'},
        !          3420:                         $curresline );
        !          3421:                     if ( $remove_latex_header ne 'NO' ) {
        !          3422:                         $rendered = &latex_header_footer_remove($rendered);
        !          3423:                     }
        !          3424:                     else {
        !          3425:                         $rendered =~ s/\\end{document}//;
        !          3426:                     }
        !          3427:                     $current_output .= $rendered;
        !          3428:                 }
        !          3429:             }
        !          3430:             $remove_latex_header = 'YES';
        !          3431:         }
        !          3432:         if ( &Apache::loncommon::connection_aborted($r) ) { last; }
1.284     albertel 3433:     }
1.552     foxr     3434: 
1.284     albertel 3435:     my $courseidinfo = &get_course();
1.575.2.1! foxr     3436:     my $currentassignment =
        !          3437:       &Apache::lonxml::latex_special_symbols( $helper->{VARS}->{'assignment'},
        !          3438:         'header' );
1.476     albertel 3439:     my $header_line =
1.575.2.1! foxr     3440:       &format_page_header( $LaTeXwidth, $parmhash{'print_header_format'},
        !          3441:         $currentassignment, $courseidinfo, $fullname, $usersection );
        !          3442:     my $header_start =
        !          3443:       ( $columns_in_format == 1 )
        !          3444:       ? '\lhead'
        !          3445:       : '\fancyhead[LO]';
        !          3446:     $header_line = $header_start . '{' . $header_line . '}';
        !          3447:     if ( $current_output =~ /\\documentclass/ && ( !$syllabus_first ) ) {
        !          3448:         $current_output =~
        !          3449: s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$header_line$namepostfix}\\vskip 5 mm /;
        !          3450:     }
        !          3451:     elsif ($syllabus_first) {
        !          3452: 
        !          3453:         $current_output =~ s/\\\\ Last updated:/Last updated:/;
        !          3454:     }
        !          3455:     else {
        !          3456:         my $blankpages =
        !          3457:           '\clearpage\strut\clearpage' x $helper->{'VARS'}->{'EMPTY_PAGES'};
        !          3458: 
        !          3459:         $current_output =
        !          3460:             '\strut\vspace*{-6 mm}\\newline'
        !          3461:           . &copyright_line()
        !          3462:           . ' \newpage '
        !          3463:           . $blankpages
        !          3464:           . $end_of_student
        !          3465:           . '\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent'
        !          3466:           . $header_line
        !          3467:           . $namepostfix
        !          3468:           . '} \vskip 5 mm '
        !          3469:           . $current_output;
1.284     albertel 3470:     }
1.575.2.1! foxr     3471: 
1.440     foxr     3472:     #
                   3473:     #  Close the student bracketing.
                   3474:     #
1.575.2.1! foxr     3475:     return ( $current_output, $fullname, $printed );
1.284     albertel 3476: 
                   3477: }
1.140     sakharuk 3478: 
1.3       sakharuk 3479: sub handler {
                   3480: 
                   3481:     my $r = shift;
1.416     foxr     3482: 
1.575.2.1! foxr     3483:     &init_perm();
1.67      www      3484: 
1.397     albertel 3485:     my $helper = printHelper($r);
1.575.2.1! foxr     3486:     if ( !ref($helper) ) {
        !          3487:         return $helper;
1.60      sakharuk 3488:     }
1.350     foxr     3489: 
1.575.2.1! foxr     3490:     %parmhash = &Apache::lonnet::coursedescription( $env{'request.course.id'} );
1.350     foxr     3491: 
1.367     foxr     3492:     #  If a figure conversion queue file exists for this user.domain
                   3493:     # we delete it since it can only be bad (if it were good, printout.pl
                   3494:     # would have deleted it the last time around.
                   3495: 
1.575.2.1! foxr     3496:     my $conversion_queuefile =
        !          3497:       "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat";
        !          3498:     if ( -e $conversion_queuefile ) {
        !          3499:         unlink $conversion_queuefile;
1.367     foxr     3500:     }
1.515     foxr     3501: 
1.575.2.1! foxr     3502:     &output_data( $r, $helper, \%parmhash );
1.2       sakharuk 3503:     return OK;
1.575.2.1! foxr     3504: }
1.2       sakharuk 3505: 
1.131     bowersj2 3506: use Apache::lonhelper;
1.130     sakharuk 3507: 
1.223     bowersj2 3508: sub addMessage {
1.575.2.1! foxr     3509:     my $text      = shift;
1.223     bowersj2 3510:     my $paramHash = Apache::lonhelper::getParamHash();
                   3511:     $paramHash->{MESSAGE_TEXT} = $text;
                   3512:     Apache::lonhelper::message->new();
                   3513: }
                   3514: 
1.397     albertel 3515: sub init_perm {
                   3516:     undef(%perm);
1.575.2.1! foxr     3517:     $perm{'pav'} = &Apache::lonnet::allowed( 'pav', $env{'request.course.id'} );
        !          3518:     if ( !$perm{'pav'} ) {
        !          3519:         $perm{'pav'} =
        !          3520:           &Apache::lonnet::allowed( 'pav',
        !          3521:             $env{'request.course.id'} . '/' . $env{'request.course.sec'} );
        !          3522:     }
        !          3523:     $perm{'pfo'} = &Apache::lonnet::allowed( 'pfo', $env{'request.course.id'} );
        !          3524:     if ( !$perm{'pfo'} ) {
        !          3525:         $perm{'pfo'} =
        !          3526:           &Apache::lonnet::allowed( 'pfo',
        !          3527:             $env{'request.course.id'} . '/' . $env{'request.course.sec'} );
1.397     albertel 3528:     }
                   3529: }
                   3530: 
1.507     albertel 3531: sub get_randomly_ordered_warning {
1.575.2.1! foxr     3532:     my ( $helper, $map ) = @_;
1.507     albertel 3533: 
                   3534:     my $message;
                   3535: 
                   3536:     my $postdata = $env{'form.postdata'} || $helper->{VARS}{'postdata'};
                   3537:     my $navmap = Apache::lonnavmaps::navmap->new();
1.575.2.1! foxr     3538:     if ( defined($navmap) ) {
1.547     raeburn  3539:         my $res = $navmap->getResourceByUrl($map);
                   3540:         if ($res) {
1.575.2.1! foxr     3541:             my $func =
        !          3542:               sub { return ( $_[0]->is_map() && $_[0]->randomorder ); };
        !          3543:             my @matches = $navmap->retrieveResources( $res, $func, 1, 1, 1 );
        !          3544:             if (@matches) {
        !          3545:                 $message =
        !          3546: "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.";
        !          3547:             }
1.547     raeburn  3548:         }
                   3549:         if ($message) {
1.575.2.1! foxr     3550:             return '<message type="warning">' . $message . '</message>';
1.547     raeburn  3551:         }
1.575.2.1! foxr     3552:     }
        !          3553:     else {
        !          3554:         $message =
        !          3555:           "Retrieval of information about ordering of resources failed.";
        !          3556:         return '<message type="warning">' . $message . '</message>';
1.507     albertel 3557:     }
                   3558:     return;
                   3559: }
                   3560: 
1.131     bowersj2 3561: sub printHelper {
1.115     bowersj2 3562:     my $r = shift;
                   3563: 
1.575.2.1! foxr     3564:     if ( $r->header_only ) {
        !          3565:         if ( $env{'browser.mathml'} ) {
        !          3566:             &Apache::loncommon::content_type( $r, 'text/xml' );
        !          3567:         }
        !          3568:         else {
        !          3569:             &Apache::loncommon::content_type( $r, 'text/html' );
1.131     bowersj2 3570:         }
                   3571:         $r->send_http_header;
                   3572:         return OK;
1.115     bowersj2 3573:     }
                   3574: 
1.131     bowersj2 3575:     # Send header, nocache
1.575.2.1! foxr     3576:     if ( $env{'browser.mathml'} ) {
        !          3577:         &Apache::loncommon::content_type( $r, 'text/xml' );
        !          3578:     }
        !          3579:     else {
        !          3580:         &Apache::loncommon::content_type( $r, 'text/html' );
1.115     bowersj2 3581:     }
                   3582:     &Apache::loncommon::no_cache($r);
                   3583:     $r->send_http_header;
                   3584:     $r->rflush();
                   3585: 
1.131     bowersj2 3586:     # Unfortunately, this helper is so complicated we have to
                   3587:     # write it by hand
                   3588: 
1.575.2.1! foxr     3589:     Apache::loncommon::get_unprocessed_cgi( $ENV{QUERY_STRING} );
        !          3590: 
1.176     bowersj2 3591:     my $helper = Apache::lonhelper::helper->new("Printing Helper");
1.146     bowersj2 3592:     $helper->declareVar('symb');
1.575.2.1! foxr     3593:     $helper->declareVar('postdata');
        !          3594:     $helper->declareVar('curseed');
        !          3595:     $helper->declareVar('probstatus');
1.156     bowersj2 3596:     $helper->declareVar('filename');
                   3597:     $helper->declareVar('construction');
1.178     sakharuk 3598:     $helper->declareVar('assignment');
1.262     sakharuk 3599:     $helper->declareVar('style_file');
1.340     foxr     3600:     $helper->declareVar('student_sort');
1.363     foxr     3601:     $helper->declareVar('FINISHPAGE');
1.366     foxr     3602:     $helper->declareVar('PRINT_TYPE');
1.372     foxr     3603:     $helper->declareVar("showallfoils");
1.483     foxr     3604:     $helper->declareVar("STUDENTS");
1.569     foxr     3605:     $helper->declareVar("EXTRASPACE");
1.518     foxr     3606: 
1.575.2.1! foxr     3607:   #  The page breaks and extra spaces
        !          3608:   #  can get loaded initially from the course environment:
        !          3609:   # But we only do this in the initial state so that they are allowed to change.
        !          3610:   #
        !          3611: 
        !          3612:     &Apache::loncommon::restore_course_settings(
        !          3613:         'print',
        !          3614:         {
        !          3615:             'pagebreaks'       => 'scalar',
        !          3616:             'extraspace'       => 'scalar',
        !          3617:             'extraspace_units' => 'scalar',
        !          3618:             'lastprinttype'    => 'scalar'
        !          3619:         }
        !          3620:     );
1.366     foxr     3621: 
1.483     foxr     3622:     # This will persistently load in the data we want from the
                   3623:     # very first screen.
1.575.2.1! foxr     3624: 
        !          3625:     if ( $helper->{VARS}->{PRINT_TYPE} eq $env{'form.lastprinttype'} ) {
        !          3626:         if ( !defined( $env{"form.CURRENT_STATE"} ) ) {
        !          3627: 
        !          3628:             $helper->{VARS}->{FINISHPAGE}       = $env{'form.pagebreaks'};
        !          3629:             $helper->{VARS}->{EXTRASPACE}       = $env{'form.extraspace'};
        !          3630:             $helper->{VARS}->{EXTRASPACE_UNITS} = $env{'form.extraspace_units'};
        !          3631:         }
        !          3632:         else {
        !          3633:             my $state = $env{"form.CURRENT_STATE"};
        !          3634:             if ( $state eq "START" ) {
        !          3635:                 $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'};
        !          3636:                 $helper->{VARS}->{EXTRASPACE} = $env{'form.extraspace'};
        !          3637:                 $helper->{VARS}->{EXTRASPACE_UNITS} =
        !          3638:                   $env{'form.extraspace_units'};
        !          3639: 
        !          3640:             }
        !          3641:         }
        !          3642: 
1.366     foxr     3643:     }
1.481     albertel 3644: 
1.156     bowersj2 3645:     # Detect whether we're coming from construction space
1.575.2.1! foxr     3646:     if (
        !          3647:         $env{'form.postdata'} =~ /^(?:http:\/\/[^\/]+\/|\/|)\~([^\/]+)\/(.*)$/ )
        !          3648:     {
        !          3649:         $helper->{VARS}->{'filename'}     = "~$1/$2";
1.156     bowersj2 3650:         $helper->{VARS}->{'construction'} = 1;
1.575.2.1! foxr     3651:     }
        !          3652:     else {
        !          3653:         if ( $env{'form.postdata'} ) {
        !          3654:             $helper->{VARS}->{'symb'} =
        !          3655:               &Apache::lonnet::symbread( $env{'form.postdata'} );
        !          3656:             if ( $helper->{VARS}->{'symb'} eq '' ) {
        !          3657:                 $helper->{VARS}->{'postdata'} = $env{'form.postdata'};
        !          3658:             }
1.156     bowersj2 3659:         }
1.575.2.1! foxr     3660:         if ( $env{'form.symb'} ) {
1.373     albertel 3661:             $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.156     bowersj2 3662:         }
1.575.2.1! foxr     3663:         if ( $env{'form.url'} ) {
        !          3664:             $helper->{VARS}->{'symb'} =
        !          3665:               &Apache::lonnet::symbread( $helper->{VARS}->{'postdata'} );
1.156     bowersj2 3666:         }
1.416     foxr     3667: 
1.157     bowersj2 3668:     }
1.481     albertel 3669: 
1.575.2.1! foxr     3670:     if ( $env{'form.symb'} ) {
1.373     albertel 3671:         $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.146     bowersj2 3672:     }
1.575.2.1! foxr     3673:     if ( $env{'form.url'} ) {
        !          3674:         $helper->{VARS}->{'symb'} =
        !          3675:           &Apache::lonnet::symbread( $helper->{VARS}->{'postdata'} );
1.153     sakharuk 3676: 
1.140     sakharuk 3677:     }
1.575.2.1! foxr     3678:     $helper->{VARS}->{'symb'} =
        !          3679:       &Apache::lonenc::check_encrypt( $helper->{VARS}->{'symb'} );
        !          3680:     my ( $resourceTitle, $sequenceTitle, $mapTitle ) =
        !          3681:       &details_for_menu($helper);
        !          3682:     if ( $sequenceTitle ne '' ) {
        !          3683:         $helper->{VARS}->{'assignment'} = $sequenceTitle;
        !          3684:     }
1.481     albertel 3685: 
1.146     bowersj2 3686:     # Extract map
                   3687:     my $symb = $helper->{VARS}->{'symb'};
1.575.2.1! foxr     3688:     my ( $map, $id, $url );
1.156     bowersj2 3689:     my $subdir;
1.575.2.1! foxr     3690:     my $is_published = 0;    # True when printing from resource space.
1.156     bowersj2 3691: 
                   3692:     # Get the resource name from construction space
1.575.2.1! foxr     3693:     if ( $helper->{VARS}->{'construction'} ) {
        !          3694:         $resourceTitle = substr( $helper->{VARS}->{'filename'},
        !          3695:             rindex( $helper->{VARS}->{'filename'}, '/' ) + 1 );
        !          3696:         $subdir = substr( $helper->{VARS}->{'filename'},
        !          3697:             0, rindex( $helper->{VARS}->{'filename'}, '/' ) + 1 );
        !          3698:     }
        !          3699:     else {
        !          3700: 
        !          3701:         # From course space:
        !          3702: 
        !          3703:         if ( $symb ne '' ) {
        !          3704:             ( $map, $id, $url ) = &Apache::lonnet::decode_symb($symb);
        !          3705:             $helper->{VARS}->{'postdata'} =
        !          3706:               &Apache::lonenc::check_encrypt( &Apache::lonnet::clutter($url) );
        !          3707:         }
        !          3708:         else {
        !          3709:             $url          = $helper->{VARS}->{'postdata'};
        !          3710:             $is_published = 1;                            # From resource space.
        !          3711:         }
        !          3712:         $url = &Apache::lonnet::clutter($url);
        !          3713:         if ( !$resourceTitle )
        !          3714:         {    # if the resource doesn't have a title, use the filename
1.238     bowersj2 3715:             my $postdata = $helper->{VARS}->{'postdata'};
1.575.2.1! foxr     3716:             $resourceTitle = substr( $postdata, rindex( $postdata, '/' ) + 1 );
1.156     bowersj2 3717:         }
1.575.2.1! foxr     3718:         $subdir = &Apache::lonnet::filelocation( "", $url );
1.128     bowersj2 3719:     }
1.575.2.1! foxr     3720:     if ( !$helper->{VARS}->{'curseed'} && $env{'form.curseed'} ) {
        !          3721:         $helper->{VARS}->{'curseed'} = $env{'form.curseed'};
1.230     albertel 3722:     }
1.575.2.1! foxr     3723:     if ( !$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'} ) {
        !          3724:         $helper->{VARS}->{'probstatus'} = $env{'form.problemstatus'};
1.290     sakharuk 3725:     }
1.115     bowersj2 3726: 
1.192     bowersj2 3727:     my $userCanSeeHidden = Apache::lonnavmaps::advancedUser();
                   3728: 
1.481     albertel 3729:     Apache::lonhelper::registerHelperTags();
1.119     bowersj2 3730: 
1.131     bowersj2 3731:     # "Delete everything after the last slash."
1.119     bowersj2 3732:     $subdir =~ s|/[^/]+$||;
                   3733: 
1.131     bowersj2 3734:     # What can be printed is a very dynamic decision based on
                   3735:     # lots of factors. So we need to dynamically build this list.
                   3736:     # To prevent security leaks, states are only added to the wizard
                   3737:     # if they can be reached, which ensures manipulating the form input
                   3738:     # won't allow anyone to reach states they shouldn't have permission
                   3739:     # to reach.
                   3740: 
                   3741:     # printChoices is tracking the kind of printing the user can
                   3742:     # do, and will be used in a choices construction later.
                   3743:     # In the meantime we will be adding states and elements to
                   3744:     # the helper by hand.
                   3745:     my $printChoices = [];
                   3746:     my $paramHash;
1.130     sakharuk 3747: 
1.240     albertel 3748:     if ($resourceTitle) {
1.575.2.1! foxr     3749:         push @{$printChoices},
        !          3750:           [
        !          3751:             "<b><i>$resourceTitle</i></b> ("
        !          3752:               . &mt('the resource you just saw on the screen') . ")",
        !          3753:             'current_document', 'PAGESIZE'
        !          3754:           ];
1.156     bowersj2 3755:     }
                   3756: 
1.238     bowersj2 3757:     # Useful filter strings
1.575.2.1! foxr     3758:     my $isProblem =
        !          3759:       '($res->is_problem()||$res->contains_problem||$res->is_practice()) ';
1.238     bowersj2 3760:     $isProblem .= ' && !$res->randomout()' if !$userCanSeeHidden;
1.575.2.1! foxr     3761:     my $isProblemOrMap =
        !          3762: '$res->is_problem() || $res->contains_problem() || $res->is_sequence() || $res->is_practice()';
1.287     albertel 3763:     my $isNotMap = '!$res->is_sequence()';
1.238     bowersj2 3764:     $isNotMap .= ' && !$res->randomout()' if !$userCanSeeHidden;
1.575.2.1! foxr     3765:     my $isMap      = '$res->is_map()';
1.342     albertel 3766:     my $symbFilter = '$res->shown_symb()';
1.575.2.1! foxr     3767:     my $urlValue   = '$res->link()';
1.238     bowersj2 3768: 
                   3769:     $helper->declareVar('SEQUENCE');
                   3770: 
1.465     albertel 3771:     # If we're in a sequence...
1.416     foxr     3772: 
1.465     albertel 3773:     my $start_new_option;
1.575.2.1! foxr     3774:     if ( $perm{'pav'} ) {
        !          3775:         $start_new_option =
        !          3776:             "<option text='"
        !          3777:           . &mt('Start new page<br />before selected')
        !          3778:           . "' variable='FINISHPAGE' />"
        !          3779:           . "<option text='"
        !          3780:           . &mt('Extra space<br />before selected')
        !          3781:           . "' variable='EXTRASPACE' type='text' />"
        !          3782:           . "<option "
        !          3783:           . "' variable='POSSIBLE_RESOURCES' type='hidden' />"
        !          3784:           . "<option text='"
        !          3785:           . &mt('Space units<br />check for mm')
        !          3786:           . "' variable='EXTRASPACE_UNITS' type='checkbox' />";
1.569     foxr     3787: 
1.465     albertel 3788:     }
1.238     bowersj2 3789: 
1.562     foxr     3790:     # If not construction space user can print the components of a page:
                   3791: 
                   3792:     my $page_ispage;
                   3793:     my $page_title;
1.575.2.1! foxr     3794:     if ( !$helper->{VARS}->{'construction'} ) {
        !          3795:         my $varspostdata   = $helper->{VARS}->{'postdata'};
        !          3796:         my $varsassignment = $helper->{VARS}->{'assignment'};
        !          3797:         my $page_navmap    = Apache::lonnavmaps::navmap->new();
        !          3798:         if ( defined($page_navmap) ) {
        !          3799:             my @page_resources = $page_navmap->retrieveResources($url);
        !          3800:             if ( defined( $page_resources[0] ) ) {
        !          3801:                 $page_ispage = $page_resources[0]->is_page();
        !          3802:                 $page_title  = $page_resources[0]->title();
        !          3803:                 my $resourcesymb = $page_resources[0]->symb();
        !          3804:                 my ( $pagemap, $pageid, $pageurl ) =
        !          3805:                   &Apache::lonnet::decode_symb($symb);
        !          3806:                 if ($page_ispage) {
        !          3807:                     push @{$printChoices},
        !          3808:                       [
        !          3809:                         &mt(
        !          3810:                             'Selected [_1]Problems[_2] from page [_3]',
        !          3811:                             '<b>', '</b>', '<b><i>' . $page_title . '</i></b>'
        !          3812:                         ),
        !          3813:                         'map_problems_in_page',
        !          3814:                         'CHOOSE_PROBLEMS_PAGE'
        !          3815:                       ];
        !          3816:                     push @{$printChoices},
        !          3817:                       [
        !          3818:                         &mt(
        !          3819:                             'Selected [_1]Resources[_2] from page [_3]',
        !          3820:                             '<b>', '</b>', '<b><i>' . $page_title . '</i></b>'
        !          3821:                         ),
        !          3822:                         'map_resources_in_page',
        !          3823:                         'CHOOSE_RESOURCES_PAGE'
        !          3824:                       ];
        !          3825:                 }
        !          3826:                 my $helperFragment = &generate_resource_chooser(
        !          3827:                     'CHOOSE_PROBLEMS_PAGE',
        !          3828:                     'Select Problem(s) to print',
        !          3829: "multichoice='1' toponly='1' addstatus='1' closeallpages='1'",
        !          3830:                     'RESOURCES',
        !          3831:                     'PAGESIZE',
        !          3832:                     $url,
        !          3833:                     $isProblem,
        !          3834:                     '',
        !          3835:                     $symbFilter,
        !          3836:                     $start_new_option
        !          3837:                 );
        !          3838: 
        !          3839:                 $helperFragment .= &generate_resource_chooser(
        !          3840:                     'CHOOSE_RESOURCES_PAGE',
        !          3841:                     'Select Resource(s) to print',
        !          3842: 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
        !          3843:                     'RESOURCES',
        !          3844:                     'PAGESIZE',
        !          3845:                     $url,
        !          3846:                     $isNotMap,
        !          3847:                     '',
        !          3848:                     $symbFilter,
        !          3849:                     $start_new_option
        !          3850:                 );
1.562     foxr     3851: 
1.575.2.1! foxr     3852:                 &Apache::lonxml::xmlparse( $r, 'helper', $helperFragment );
1.562     foxr     3853: 
1.575.2.1! foxr     3854:             }
        !          3855:         }
1.562     foxr     3856:     }
                   3857: 
1.575.2.1! foxr     3858:     if (   ( $helper->{'VAR'}->{'construction'} ne '1' )
        !          3859:         && $helper->{VARS}->{'postdata'}
        !          3860:         && $helper->{VARS}->{'assignment'} )
        !          3861:     {
        !          3862: 
1.131     bowersj2 3863:         # Allow problems from sequence
1.575.2.1! foxr     3864:         push @{$printChoices},
        !          3865:           [
        !          3866:             &mt(
        !          3867:                 'Selected [_1]Problems[_2] from folder [_3]',
        !          3868:                 '<b>', '</b>', '<b><i>' . $sequenceTitle . '</i></b>'
        !          3869:             ),
        !          3870:             'map_problems',
        !          3871:             'CHOOSE_PROBLEMS'
        !          3872:           ];
        !          3873: 
1.131     bowersj2 3874:         # Allow all resources from sequence
1.575.2.1! foxr     3875:         push @{$printChoices},
        !          3876:           [
        !          3877:             &mt(
        !          3878:                 'Selected [_1]Resources[_2] from folder [_3]',
        !          3879:                 '<b>', '</b>', '<b><i>' . $sequenceTitle . '</i></b>'
        !          3880:             ),
        !          3881:             'map_problems_pages',
        !          3882:             'CHOOSE_PROBLEMS_HTML'
        !          3883:           ];
        !          3884:         my $helperFragment = &generate_resource_chooser(
        !          3885:             'CHOOSE_PROBLEMS',
        !          3886:             'Select Problem(s) to print',
        !          3887:             'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
        !          3888:             'RESOURCES',
        !          3889:             'PAGESIZE',
        !          3890:             $map,
        !          3891:             $isProblem,
        !          3892:             '',
        !          3893:             $symbFilter,
        !          3894:             $start_new_option
        !          3895:         );
        !          3896:         $helperFragment .= &generate_resource_chooser(
        !          3897:             'CHOOSE_PROBLEMS_HTML',
        !          3898:             'Select Resource(s) to print',
        !          3899:             'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
        !          3900:             'RESOURCES',
        !          3901:             'PAGESIZE',
        !          3902:             $map,
        !          3903:             $isNotMap,
        !          3904:             '',
        !          3905:             $symbFilter,
        !          3906:             $start_new_option
        !          3907:         );
1.121     bowersj2 3908: 
1.575.2.1! foxr     3909:         &Apache::lonxml::xmlparse( $r, 'helper', $helperFragment );
1.121     bowersj2 3910:     }
                   3911: 
1.575.2.1! foxr     3912: # If the user has pfo (print for others) allow them to print all
        !          3913: # problems and resources  in the entire course, optionally for selected students
1.562     foxr     3914:     my $post_data = $helper->{VARS}->{'postdata'};
1.575.2.1! foxr     3915:     if (
        !          3916:            $perm{'pfo'}
        !          3917:         && !$is_published
        !          3918:         && (   $post_data =~ /\/res\//
        !          3919:             || $post_data =~ /\/(syllabus|smppg|aboutme|bulletinboard)$/ )
        !          3920:       )
        !          3921:     {
        !          3922: 
        !          3923:         push @{$printChoices},
        !          3924:           [
        !          3925:             &mtn('Selected <b>Problems</b> from <b>entire course</b>'),
        !          3926:             'all_problems', 'ALL_PROBLEMS'
        !          3927:           ];
        !          3928:         push @{$printChoices},
        !          3929:           [
        !          3930:             &mtn('Selected <b>Resources</b> from <b>entire course</b>'),
        !          3931:             'all_resources', 'ALL_RESOURCES'
        !          3932:           ];
        !          3933:         push @{$printChoices},
        !          3934:           [
        !          3935:             &mtn(
        !          3936: 'Selected <b>Problems</b> from <b>entire course</b> for <b>selected people</b>'
        !          3937:             ),
        !          3938:             'all_problems_students',
        !          3939:             'ALL_PROBLEMS_STUDENTS'
        !          3940:           ];
        !          3941:         my $suffixXml = <<ALL_PROBLEMS;
1.536     foxr     3942:   <state name="STUDENTS1" title="Select People">
                   3943:       <message><b>Select sorting order of printout</b> </message>
                   3944:     <choices variable='student_sort'>
                   3945:       <choice computer='0'>Sort by section then student</choice>
                   3946:       <choice computer='1'>Sort by students across sections.</choice>
                   3947:     </choices>
                   3948:       <message><br /><hr /><br /> </message>
                   3949:       <student multichoice='1' variable="STUDENTS" nextstate="PRINT_FORMATTING" coursepersonnel="1"/>
                   3950:   </state>
1.284     albertel 3951: ALL_PROBLEMS
1.575.2.1! foxr     3952:         &Apache::lonxml::xmlparse(
        !          3953:             $r, 'helper',
        !          3954:             &generate_resource_chooser(
        !          3955:                 'ALL_PROBLEMS',
        !          3956:                 'SelectProblem(s) to print',
        !          3957: 'multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1"',
        !          3958:                 'RESOURCES',
        !          3959:                 'PAGESIZE',
        !          3960:                 '',
        !          3961:                 $isProblemOrMap,
        !          3962:                 $isNotMap,
        !          3963:                 $symbFilter,
        !          3964:                 $start_new_option
        !          3965:               )
        !          3966:               . &generate_resource_chooser(
        !          3967:                 'ALL_RESOURCES',
        !          3968:                 'Select Resource(s) to print',
        !          3969: " toponly='0' multichoice='1' suppressEmptySequences='0' addstatus='1' closeallpages='1'",
        !          3970:                 'RESOURCES',
        !          3971:                 'PAGESIZE',
        !          3972:                 '',
        !          3973:                 $isNotMap,
        !          3974:                 '',
        !          3975:                 $symbFilter,
        !          3976:                 $start_new_option
        !          3977:               )
        !          3978:               . &generate_resource_chooser(
        !          3979:                 'ALL_PROBLEMS_STUDENTS',
        !          3980:                 'Select Problem(s) to print',
        !          3981: 'toponly="0" multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1"',
        !          3982:                 'RESOURCES',
        !          3983:                 'STUDENTS1',
        !          3984:                 '',
        !          3985:                 $isProblemOrMap,
        !          3986:                 '',
        !          3987:                 $symbFilter,
        !          3988:                 $start_new_option
        !          3989:               )
        !          3990:               . $suffixXml
        !          3991:         );
        !          3992: 
        !          3993:         if ( $helper->{VARS}->{'assignment'} ) {
        !          3994: 
        !          3995:      # If we were looking at a page, allow a selection of problems from the page
        !          3996:      # either for selected students or for coded assignments.
1.424     foxr     3997: 
1.575.2.1! foxr     3998:             if ($page_ispage) {
        !          3999:                 push @{$printChoices},
        !          4000:                   [
        !          4001:                     &mt(
        !          4002: 'Selected [_1]Problems[_2] from page [_3] for [_4]selected people[_5]',
        !          4003:                         '<b>',
        !          4004:                         '</b>',
        !          4005:                         '<b><i>' . $page_title . '</i></b>',
        !          4006:                         '<b>',
        !          4007:                         '</b>'
        !          4008:                     ),
        !          4009:                     'problems_for_students_from_page',
        !          4010:                     'CHOOSE_TGT_STUDENTS_PAGE'
        !          4011:                   ];
        !          4012:                 push @{$printChoices},
        !          4013:                   [
        !          4014:                     &mt(
        !          4015: 'Selected [_1]Problems[_2] from page [_3] for [_4]CODEd assignments[_5]',
        !          4016:                         '<b>',
        !          4017:                         '</b>',
        !          4018:                         '<b><i>' . $page_title . '</i></b>',
        !          4019:                         '<b>',
        !          4020:                         '</b>'
        !          4021:                     ),
        !          4022:                     'problems_for_anon_page',
        !          4023:                     'CHOOSE_ANON1_PAGE'
        !          4024:                   ];
        !          4025:             }
        !          4026:             push @{$printChoices},
        !          4027:               [
        !          4028:                 &mt(
        !          4029: 'Selected [_1]Problems[_2] from folder [_3] for [_4]selected people[_5]',
        !          4030:                     '<b>',
        !          4031:                     '</b>',
        !          4032:                     '<b><i>' . $sequenceTitle . '</i></b>',
        !          4033:                     '<b>',
        !          4034:                     '</b>'
        !          4035:                 ),
        !          4036:                 'problems_for_students',
        !          4037:                 'CHOOSE_STUDENTS'
        !          4038:               ];
        !          4039:             push @{$printChoices},
        !          4040:               [
        !          4041:                 &mt(
        !          4042: 'Selected [_1]Problems[_2] from folder [_3] for [_4]CODEd assignments[_5]',
        !          4043:                     '<b>',
        !          4044:                     '</b>',
        !          4045:                     '<b><i>' . $sequenceTitle . '</i></b>',
        !          4046:                     '<b>',
        !          4047:                     '</b>'
        !          4048:                 ),
        !          4049:                 'problems_for_anon',
        !          4050:                 'CHOOSE_ANON1'
        !          4051:               ];
        !          4052:         }
        !          4053: 
        !          4054:         my $randomly_ordered_warning =
        !          4055:           &get_randomly_ordered_warning( $helper, $map );
1.507     albertel 4056: 
1.575.2.1! foxr     4057:    # resource_selector will hold a few states that:
        !          4058:    #   - Allow resources to be selected for printing.
        !          4059:    #   - Determine pagination between assignments.
        !          4060:    #   - Determine how many assignments should be bundled into a single PDF.
        !          4061:    # TODO:
        !          4062:    #    Probably good to do things like separate this up into several vars, each
        !          4063:    #    with one state, and use REGEXPs at inclusion time to set state names
        !          4064:    #    and next states for better mix and match capability
        !          4065:    #
        !          4066:         my $resource_selector = &generate_resource_chooser(
        !          4067:             'SELECT_PROBLEMS',
        !          4068:             'Select resources to print',
        !          4069:             'multichoice="1" addstatus="1" closeallpages="1"',
        !          4070:             'RESOURCES',
        !          4071:             'PRINT_FORMATTING',
        !          4072:             $map,
        !          4073:             $isProblem,
        !          4074:             '',
        !          4075:             $symbFilter,
        !          4076:             $start_new_option
        !          4077:         );
        !          4078:         $resource_selector .= <<RESOURCE_SELECTOR;
1.424     foxr     4079:     <state name="PRINT_FORMATTING" title="How should results be printed?">
1.155     sakharuk 4080:     <message><br /><big><i><b>How should the results be printed?</b></i></big><br /></message>
1.149     bowersj2 4081:     <choices variable="EMPTY_PAGES">
1.204     sakharuk 4082:       <choice computer='0'>Start each student\'s assignment on a new page/column (add a pagefeed after each assignment)</choice>
                   4083:       <choice computer='1'>Add one empty page/column after each student\'s assignment</choice>
                   4084:       <choice computer='2'>Add two empty pages/column after each student\'s assignment</choice>
                   4085:       <choice computer='3'>Add three empty pages/column after each student\'s assignment</choice>
1.284     albertel 4086:     </choices>
1.424     foxr     4087:     <nextstate>PAGESIZE</nextstate>
1.429     foxr     4088:     <message><hr width='33%' /><b>How do you want assignments split into PDF files? </b></message>
                   4089:     <choices variable="SPLIT_PDFS">
                   4090:        <choice computer="all">All assignments in a single PDF file</choice>
                   4091:        <choice computer="sections">Each PDF contains exactly one section</choice>
                   4092:        <choice computer="oneper">Each PDF contains exactly one assignment</choice>
1.449     albertel 4093:        <choice computer="usenumber" relatedvalue="NUMBER_TO_PRINT">
                   4094:             Specify the number of assignments per PDF:</choice>
1.429     foxr     4095:     </choices>
1.424     foxr     4096:     </state>
1.284     albertel 4097: RESOURCE_SELECTOR
1.575.2.1! foxr     4098:         $resource_selector .= &generate_resource_chooser(
        !          4099:             'CHOOSE_STUDENTS_PAGE',
        !          4100:             'Select Problem(s) to print',
        !          4101:             "multichoice='1' addstatus='1' closeallpages ='1'",
        !          4102:             'RESOURCES',
        !          4103:             'PRINT_FORMATTING',
        !          4104:             $url,
        !          4105:             $isProblem,
        !          4106:             '',
        !          4107:             $symbFilter,
        !          4108:             $start_new_option
        !          4109:         );
1.562     foxr     4110: 
1.575.2.1! foxr     4111:         # Generate student choosers.
1.284     albertel 4112: 
1.575.2.1! foxr     4113:         &Apache::lonxml::xmlparse(
        !          4114:             $r, 'helper',
        !          4115:             &generate_student_chooser(
        !          4116:                 'CHOOSE_TGT_STUDENTS_PAGE', 'student_sort',
        !          4117:                 'STUDENTS',                 'CHOOSE_STUDENTS_PAGE'
        !          4118:             )
        !          4119:         );
        !          4120:         &Apache::lonxml::xmlparse(
        !          4121:             $r, 'helper',
        !          4122:             &generate_student_chooser(
        !          4123:                 'CHOOSE_STUDENTS', 'student_sort',
        !          4124:                 'STUDENTS',        'SELECT_PROBLEMS'
        !          4125:             )
        !          4126:         );
        !          4127:         &Apache::lonxml::xmlparse( $r, 'helper', $resource_selector );
1.389     foxr     4128: 
1.575.2.1! foxr     4129:         my $cdom  = $env{ 'course.' . $env{'request.course.id'} . '.domain' };
        !          4130:         my $cnum  = $env{ 'course.' . $env{'request.course.id'} . '.num' };
        !          4131:         my @names = &Apache::lonnet::getkeys( 'CODEs', $cdom, $cnum );
        !          4132:         my $namechoice = '<choice></choice>';
        !          4133:         foreach my $name ( sort { uc($a) cmp uc($b) } @names ) {
        !          4134:             if ( $name =~ /^error: 2 / ) { next; }
        !          4135:             if ( $name =~ /^type\0/ )    { next; }
        !          4136:             $namechoice .=
        !          4137:               '<choice computer="' . $name . '">' . $name . '</choice>';
        !          4138:         }
1.389     foxr     4139: 
1.575.2.1! foxr     4140:         my %code_values;
        !          4141:         my %codes_to_print;
        !          4142:         foreach my $key (@names) {
        !          4143:             %code_values = &Apache::grades::get_codes( $key, $cdom, $cnum );
        !          4144:             foreach my $key ( keys(%code_values) ) {
        !          4145:                 $codes_to_print{$key} = 1;
        !          4146:             }
        !          4147:         }
1.389     foxr     4148: 
1.575.2.1! foxr     4149:         my $code_selection;
        !          4150:         foreach
        !          4151:           my $code ( sort { uc($a) cmp uc($b) } ( keys(%codes_to_print) ) )
        !          4152:         {
        !          4153:             my $choice = $code;
        !          4154:             if ( $code =~ /^[A-Z]+$/ ) {    # Alpha code
        !          4155:                 $choice = &letters_to_num($code);
        !          4156:             }
        !          4157:             push( @{ $helper->{DATA}{ALL_CODE_CHOICES} }, [ $code, $choice ] );
        !          4158:         }
        !          4159:         if (%codes_to_print) {
        !          4160:             $code_selection .= '   
1.472     albertel 4161: 	    <message><b>Choose single CODE from list:</b></message>
1.448     albertel 4162: 		<message></td><td></message>
1.452     albertel 4163: 		<dropdown variable="CODE_SELECTED_FROM_LIST" multichoice="0" allowempty="0">
                   4164:                   <choice></choice>
1.448     albertel 4165:                   <exec>
                   4166:                      push(@{$state->{CHOICES}},@{$helper->{DATA}{ALL_CODE_CHOICES}});
                   4167:                   </exec>
1.452     albertel 4168: 		</dropdown>
1.468     foxr     4169: 	    <message></td></tr><tr><td></message>
1.575.2.1! foxr     4170:             ' . $/;
1.448     albertel 4171: 
1.575.2.1! foxr     4172:         }
1.432     albertel 4173: 
1.575.2.1! foxr     4174:         my @lines      = &Apache::grades::get_scantronformat_file();
        !          4175:         my $codechoice = '';
        !          4176:         foreach my $line (@lines) {
        !          4177:             my ( $name, $description, $code_type, $code_length ) =
        !          4178:               ( split( /:/, $line ) )[ 0, 1, 2, 4 ];
        !          4179:             if (   $code_length > 0
        !          4180:                 && $code_type =~ /^(letter|number|-1)/ )
        !          4181:             {
        !          4182:                 $codechoice .=
        !          4183:                     '<choice computer="' 
        !          4184:                   . $name . '">'
        !          4185:                   . $description
        !          4186:                   . '</choice>';
        !          4187:             }
        !          4188:         }
        !          4189:         if ( $codechoice eq '' ) {
        !          4190:             $codechoice = '<choice computer="default">Default</choice>';
        !          4191:         }
        !          4192:         my $anon1 =
        !          4193:           &generate_code_selector( $helper, 'CHOOSE_ANON1', 'SELECT_PROBLEMS',
        !          4194:             $codechoice, $code_selection, $namechoice )
        !          4195:           . $resource_selector;
        !          4196: 
        !          4197:         &Apache::lonxml::xmlparse( $r, 'helper', $anon1 );
        !          4198: 
        !          4199:         my $anon_page =
        !          4200:           &generate_code_selector( $helper, 'CHOOSE_ANON1_PAGE',
        !          4201:             'SELECT_PROBLEMS_PAGE', $codechoice, $code_selection, $namechoice )
        !          4202:           . &generate_resource_chooser(
        !          4203:             'SELECT_PROBLEMS_PAGE',
        !          4204:             'Select Problem(s) to print',
        !          4205:             "multichoice='1' addstatus='1' closeallpages ='1'",
        !          4206:             'RESOURCES',
        !          4207:             'PRINT_FORMATTING',
        !          4208:             $url,
        !          4209:             $isProblem,
        !          4210:             '',
        !          4211:             $symbFilter,
        !          4212:             $start_new_option
        !          4213:           );
        !          4214:         &Apache::lonxml::xmlparse( $r, 'helper', $anon_page );
        !          4215: 
        !          4216:         if ( $helper->{VARS}->{'assignment'} ) {
        !          4217:             push @{$printChoices},
        !          4218:               [
        !          4219:                 &mt(
        !          4220: 'Selected [_1]Resources[_2] from folder [_3] for [_4]selected people[_5]',
        !          4221:                     '<b>',
        !          4222:                     '</b>',
        !          4223:                     '<b><i>' . $sequenceTitle . '</i></b>',
        !          4224:                     '<b>',
        !          4225:                     '</b>'
        !          4226:                 ),
        !          4227:                 'resources_for_students',
        !          4228:                 'CHOOSE_STUDENTS1'
        !          4229:               ];
        !          4230:             push @{$printChoices},
        !          4231:               [
        !          4232:                 &mt(
        !          4233: 'Selected [_1]Resources[_2] from folder [_3] for [_4]CODEd assignments[_5]',
        !          4234:                     '<b>',
        !          4235:                     '</b>',
        !          4236:                     '<b><i>' . $sequenceTitle . '</i></b>',
        !          4237:                     '<b>',
        !          4238:                     '</b>'
        !          4239:                 ),
        !          4240:                 'resources_for_anon',
        !          4241:                 'CHOOSE_ANON2'
        !          4242:               ];
        !          4243:         }
1.284     albertel 4244: 
1.575.2.1! foxr     4245:         $resource_selector = <<RESOURCE_SELECTOR;
1.424     foxr     4246:     <state name="SELECT_RESOURCES" title="Select Resources">
1.507     albertel 4247:     $randomly_ordered_warning
1.424     foxr     4248:     <nextstate>PRINT_FORMATTING</nextstate>
1.254     sakharuk 4249:     <message><br /><big><i><b>Select resources for the assignment</b></i></big><br /></message>
1.287     albertel 4250:     <resource variable="RESOURCES" multichoice="1" addstatus="1" 
                   4251:               closeallpages="1">
1.254     sakharuk 4252:       <filterfunc>return $isNotMap;</filterfunc>
                   4253:       <mapurl>$map</mapurl>
                   4254:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 4255:       $start_new_option
1.254     sakharuk 4256:       </resource>
1.424     foxr     4257:     </state>
1.562     foxr     4258: 
1.424     foxr     4259:     <state name="PRINT_FORMATTING" title="Format of the print job">
                   4260:     <nextstate>NUMBER_PER_PDF</nextstate>
1.254     sakharuk 4261:     <message><br /><big><i><b>How should the results be printed?</b></i></big><br /></message>
                   4262:     <choices variable="EMPTY_PAGES">
                   4263:       <choice computer='0'>Start each student\'s assignment on a new page/column (add a pagefeed after each assignment)</choice>
                   4264:       <choice computer='1'>Add one empty page/column after each student\'s assignment</choice>
                   4265:       <choice computer='2'>Add two empty pages/column after each student\'s assignment</choice>
                   4266:       <choice computer='3'>Add three empty pages/column after each student\'s assignment</choice>
1.284     albertel 4267:     </choices>
1.424     foxr     4268:     <nextstate>PAGESIZE</nextstate>
1.429     foxr     4269:     <message><hr width='33%' /><b>How do you want assignments split into PDF files? </b></message>
                   4270:     <choices variable="SPLIT_PDFS">
                   4271:        <choice computer="all">All assignments in a single PDF file</choice>
                   4272:        <choice computer="sections">Each PDF contains exactly one section</choice>
                   4273:        <choice computer="oneper">Each PDF contains exactly one assignment</choice>
1.449     albertel 4274:        <choice computer="usenumber" relatedvalue="NUMBER_TO_PRINT">
                   4275:            Specify the number of assignments per PDF:</choice>
1.429     foxr     4276:     </choices>
1.424     foxr     4277:     </state>
1.284     albertel 4278: RESOURCE_SELECTOR
                   4279: 
1.575.2.1! foxr     4280:         &Apache::lonxml::xmlparse( $r, 'helper', <<CHOOSE_STUDENTS1);
1.284     albertel 4281:   <state name="CHOOSE_STUDENTS1" title="Select Students and Resources">
1.340     foxr     4282:     <choices variable='student_sort'>
                   4283:       <choice computer='0'>Sort by section then student</choice>
                   4284:       <choice computer='1'>Sort by students across sections.</choice>
                   4285:     </choices>
1.437     foxr     4286:     <message><br /><hr /><br /></message>
1.426     foxr     4287:     <student multichoice='1' variable="STUDENTS" nextstate="SELECT_RESOURCES" coursepersonnel="1" />
1.340     foxr     4288: 
1.424     foxr     4289:     </state>
1.284     albertel 4290:     $resource_selector
1.254     sakharuk 4291: CHOOSE_STUDENTS1
                   4292: 
1.575.2.1! foxr     4293:         &Apache::lonxml::xmlparse( $r, 'helper', <<CHOOSE_ANON2);
1.472     albertel 4294:   <state name="CHOOSE_ANON2" title="Select CODEd Assignments">
1.424     foxr     4295:     <nextstate>SELECT_RESOURCES</nextstate>
1.472     albertel 4296:     <message><h4>Fill out one of the forms below</h4></message>
                   4297:     <message><br /><hr /> <br /></message>
                   4298:     <message><h3>Generate new CODEd Assignments</h3></message>
                   4299:     <message><table><tr><td><b>Number of CODEd assignments to print:</b></td><td></message>
1.362     albertel 4300:     <string variable="NUMBER_TO_PRINT_TOTAL" maxlength="5" size="5">
                   4301:        <validator>
                   4302: 	if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) &&
1.386     foxr     4303: 	    !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                &&
1.388     foxr     4304: 	    !\$helper->{'VARS'}{'SINGLE_CODE'}                   &&
                   4305: 	    !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.362     albertel 4306: 	    return "You need to specify the number of assignments to print";
                   4307: 	}
                   4308: 	return undef;
                   4309:        </validator>
                   4310:     </string>
                   4311:     <message></td></tr><tr><td></message>
1.501     albertel 4312:     <message><b>Names to save the CODEs under for later:</b></message>
1.412     albertel 4313:     <message></td><td></message>
                   4314:     <string variable="ANON_CODE_STORAGE_NAME" maxlength="50" size="20" />
                   4315:     <message></td></tr><tr><td></message>
                   4316:     <message><b>Bubble sheet type:</b></message>
                   4317:     <message></td><td></message>
                   4318:     <dropdown variable="CODE_OPTION" multichoice="0" allowempty="0">
                   4319:     $codechoice
                   4320:     </dropdown>
1.472     albertel 4321:     <message></td></tr><tr><td></table></message>
                   4322:     <message><br /><hr /><h3>Print a Specific CODE </h3><br /><table></message>
                   4323:     <message><tr><td><b>Enter a CODE to print:</b></td><td></message>
1.412     albertel 4324:     <string variable="SINGLE_CODE" size="10">
1.386     foxr     4325:         <validator>
                   4326: 	   if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}           &&
1.388     foxr     4327: 	      !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                 &&
                   4328: 	      !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.386     foxr     4329: 	      return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'},
                   4330: 						      \$helper->{'VARS'}{'CODE_OPTION'});
                   4331: 	   } else {
                   4332: 	       return undef;	# Other forces control us.
                   4333: 	   }
                   4334:         </validator>
                   4335:     </string>
1.472     albertel 4336:     <message></td></tr><tr><td></message>
1.432     albertel 4337:         $code_selection
1.472     albertel 4338:     <message></td></tr></table></message>
                   4339:     <message><hr /><h3>Reprint a Set of Saved CODEs</h3><table><tr><td></message>
                   4340:     <message><b>Select saved CODEs:</b></message>
1.381     albertel 4341:     <message></td><td></message>
1.294     albertel 4342:     <dropdown variable="REUSE_OLD_CODES">
                   4343:         $namechoice
                   4344:     </dropdown>
1.412     albertel 4345:     <message></td></tr></table></message>
1.424     foxr     4346:   </state>
1.284     albertel 4347:     $resource_selector
                   4348: CHOOSE_ANON2
1.481     albertel 4349:     }
                   4350: 
1.121     bowersj2 4351:     # FIXME: That RE should come from a library somewhere.
1.575.2.1! foxr     4352:     if (
        !          4353:         (
        !          4354:                $perm{'pav'} 
        !          4355:             && $subdir ne $Apache::lonnet::perlvar{'lonDocRoot'}
        !          4356:             . '/res/'
        !          4357:             && (
        !          4358:                 defined( $helper->{'VARS'}->{'construction'} )
        !          4359:                 || (   &Apache::lonnet::allowed( 'bre', $subdir ) eq 'F'
        !          4360:                     && $helper->{VARS}->{'postdata'} =~
        !          4361: /\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)/
        !          4362:                 )
        !          4363:             )
        !          4364:         )
        !          4365:         && $helper->{VARS}->{'assignment'} eq ""
        !          4366:       )
        !          4367:     {
        !          4368:         my $pretty_dir = &Apache::lonnet::hreflocation($subdir);
        !          4369:         push @{$printChoices},
        !          4370:           [
        !          4371:             &mt(
        !          4372:                 'Selected [_1]Problems[_2] from current subdirectory [_3]',
        !          4373:                 '<b>',
        !          4374:                 '</b>',
        !          4375:                 '<b><i>' . $pretty_dir . '</i></b>',
        !          4376:                 '<b>',
        !          4377:                 '</b>'
        !          4378:             ),
        !          4379:             'problems_from_directory',
        !          4380:             'CHOOSE_FROM_SUBDIR'
        !          4381:           ];
1.139     bowersj2 4382:         my $xmlfrag = <<CHOOSE_FROM_SUBDIR;
1.482     albertel 4383:   <state name="CHOOSE_FROM_SUBDIR" title="Select File(s) from <b><small>$pretty_dir</small></b> to print">
1.458     www      4384: 
1.138     bowersj2 4385:     <files variable="FILES" multichoice='1'>
1.144     bowersj2 4386:       <nextstate>PAGESIZE</nextstate>
1.138     bowersj2 4387:       <filechoice>return '$subdir';</filechoice>
1.139     bowersj2 4388: CHOOSE_FROM_SUBDIR
1.575.2.1! foxr     4389: 
1.238     bowersj2 4390:         # this is broken up because I really want interpolation above,
                   4391:         # and I really DON'T want it below
1.139     bowersj2 4392:         $xmlfrag .= <<'CHOOSE_FROM_SUBDIR';
1.225     bowersj2 4393:       <filefilter>return Apache::lonhelper::files::not_old_version($filename) &&
                   4394: 	  $filename =~ m/\.(problem|exam|quiz|assess|survey|form|library)$/;
1.131     bowersj2 4395:       </filefilter>
1.138     bowersj2 4396:       </files>
1.131     bowersj2 4397:     </state>
                   4398: CHOOSE_FROM_SUBDIR
1.575.2.1! foxr     4399:         &Apache::lonxml::xmlparse( $r, 'helper', $xmlfrag );
1.131     bowersj2 4400:     }
1.238     bowersj2 4401: 
                   4402:     # Allow the user to select any sequence in the course, feed it to
                   4403:     # another resource selector for that sequence
1.575.2.1! foxr     4404:     if ( !$helper->{VARS}->{'construction'} && !$is_published ) {
        !          4405:         push @$printChoices,
        !          4406:           [
        !          4407:             &mtn(
        !          4408: "Selected <b>Resources</b> from <b>selected folder</b> in course"
        !          4409:             ),
        !          4410:             'select_sequences',
        !          4411:             'CHOOSE_SEQUENCE'
        !          4412:           ];
        !          4413:         my $escapedSequenceName = $helper->{VARS}->{'SEQUENCE'};
        !          4414: 
        !          4415:         #Escape apostrophes and backslashes for Perl
        !          4416:         $escapedSequenceName =~ s/\\/\\\\/g;
        !          4417:         $escapedSequenceName =~ s/'/\\'/g;
        !          4418:         &Apache::lonxml::xmlparse( $r, 'helper', <<CHOOSE_FROM_ANY_SEQUENCE);
1.238     bowersj2 4419:   <state name="CHOOSE_SEQUENCE" title="Select Sequence To Print From">
                   4420:     <message>Select the sequence to print resources from:</message>
                   4421:     <resource variable="SEQUENCE">
                   4422:       <nextstate>CHOOSE_FROM_ANY_SEQUENCE</nextstate>
                   4423:       <filterfunc>return \$res->is_sequence;</filterfunc>
                   4424:       <valuefunc>return $urlValue;</valuefunc>
1.447     foxr     4425:       <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
1.391     foxr     4426: 	</choicefunc>
1.238     bowersj2 4427:       </resource>
                   4428:     </state>
                   4429:   <state name="CHOOSE_FROM_ANY_SEQUENCE" title="Select Resources To Print">
                   4430:     <message>(mark desired resources then click "next" button) <br /></message>
1.435     foxr     4431:     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287     albertel 4432:               closeallpages="1">
1.238     bowersj2 4433:       <nextstate>PAGESIZE</nextstate>
1.466     albertel 4434:       <filterfunc>return $isNotMap</filterfunc>
1.244     bowersj2 4435:       <mapurl evaluate='1'>return '$escapedSequenceName';</mapurl>
1.238     bowersj2 4436:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 4437:       $start_new_option
1.238     bowersj2 4438:       </resource>
                   4439:     </state>
                   4440: CHOOSE_FROM_ANY_SEQUENCE
1.575.2.1! foxr     4441:     }
1.481     albertel 4442: 
1.131     bowersj2 4443:     # Generate the first state, to select which resources get printed.
1.575.2.1! foxr     4444:     Apache::lonhelper::state->new( "START", "Select Printing Options:" );
1.131     bowersj2 4445:     $paramHash = Apache::lonhelper::getParamHash();
1.155     sakharuk 4446:     $paramHash->{MESSAGE_TEXT} = "";
1.131     bowersj2 4447:     Apache::lonhelper::message->new();
1.575.2.1! foxr     4448:     $paramHash               = Apache::lonhelper::getParamHash();
1.131     bowersj2 4449:     $paramHash->{'variable'} = 'PRINT_TYPE';
1.575.2.1! foxr     4450:     $paramHash->{CHOICES}    = $printChoices;
1.131     bowersj2 4451:     Apache::lonhelper::choices->new();
1.161     bowersj2 4452: 
1.575.2.1! foxr     4453:     my $startedTable = 0;    # have we started an HTML table yet? (need
        !          4454:                              # to close it later)
1.223     bowersj2 4455: 
1.575.2.1! foxr     4456:     if (
        !          4457:         (
        !          4458:                 $perm{'pav'}
        !          4459:             and &Apache::lonnet::allowed( 'vgr', $env{'request.course.id'} )
        !          4460:         )
        !          4461:         or ( $helper->{VARS}->{'construction'} eq '1' )
        !          4462:       )
        !          4463:     {
        !          4464:         &addMessage(
        !          4465:                 '<br />' . '<h3>'
        !          4466:               . &mt('Print Options') . '</h3>'
        !          4467:               . &Apache::lonhtmlcommon::start_pick_box()
        !          4468:               . &Apache::lonhtmlcommon::row_title(
        !          4469:                     '<label for="ANSWER_TYPE_forminput">'
        !          4470:                   . &mt('Print Answers')
        !          4471:                   . '</label>'
        !          4472:               )
1.544     bisitz   4473:         );
1.161     bowersj2 4474:         $paramHash = Apache::lonhelper::getParamHash();
1.575.2.1! foxr     4475:         $paramHash->{'variable'} = 'ANSWER_TYPE';
        !          4476:         $helper->declareVar('ANSWER_TYPE');
1.161     bowersj2 4477:         $paramHash->{CHOICES} = [
1.575.2.1! foxr     4478:             [ 'Without Answers', 'yes' ],
        !          4479:             [ 'With Answers',    'no' ],
        !          4480:             [ 'Only Answers',    'only' ]
        !          4481:         ];
1.210     sakharuk 4482:         Apache::lonhelper::dropdown->new();
1.575.2.1! foxr     4483:         &addMessage( &Apache::lonhtmlcommon::row_closure() );
        !          4484:         $startedTable = 1;
1.556     foxr     4485: 
1.575.2.1! foxr     4486:         #
        !          4487:         #  Select font size.
        !          4488:         #
        !          4489: 
        !          4490:         $helper->declareVar('fontsize');
        !          4491:         &addMessage( &Apache::lonhtmlcommon::row_title( &mt('Font Size') ) );
        !          4492:         my $xmlfrag = << "FONT_SELECTION";
1.556     foxr     4493: 
                   4494:           
                   4495:             <dropdown variable='fontsize' multichoice='0', allowempty='0'>
                   4496:             <defaultvalue>
                   4497: 		  return 'normalsize';
                   4498:             </defaultvalue>
                   4499:             <choice computer='tiny'>Tiny</choice>
                   4500:             <choice computer='sub/superscriptsize'>Script Size</choice>
                   4501:             <choice computer='footnotesize'>Footnote Size</choice>
                   4502:             <choice computer='small'>Small</choice>
                   4503:             <choice computer='normalsize'>Normal (default)</choice>
                   4504:             <choice computer='large'>larger than normal</choice>
                   4505:             <choice computer='Large'>Even larger than normal</choice>
                   4506:             <choice computer='LARGE'>Still larger than normal</choice>
                   4507:             <choice computer='huge'>huge font size</choice>
                   4508:             <choice computer='Huge'>Largest possible size</choice>
                   4509:             </dropdown>
                   4510: FONT_SELECTION
1.575.2.1! foxr     4511:         &Apache::lonxml::xmlparse( $r, 'helper', $xmlfrag );
        !          4512:         &addMessage( &Apache::lonhtmlcommon::row_closure(1) );
1.161     bowersj2 4513:     }
1.209     sakharuk 4514: 
1.575.2.1! foxr     4515:     if ( $perm{'pav'} ) {
        !          4516:         if ( !$startedTable ) {
        !          4517:             addMessage( "<hr width='33%' /><table><tr><td align='right'>"
        !          4518:                   . '<label for="LATEX_TYPE_forminput">'
        !          4519:                   . &mt('LaTeX mode')
        !          4520:                   . "</label>: </td><td>" );
        !          4521:             $startedTable = 1;
        !          4522:         }
        !          4523:         else {
        !          4524:             &addMessage(
        !          4525:                 &Apache::lonhtmlcommon::row_title(
        !          4526:                         '<label for="LATEX_TYPE_forminput">'
        !          4527:                       . &mt('LaTeX mode')
        !          4528:                       . '</label>'
        !          4529:                 )
1.544     bisitz   4530:             );
1.575.2.1! foxr     4531:         }
1.203     sakharuk 4532:         $paramHash = Apache::lonhelper::getParamHash();
1.575.2.1! foxr     4533:         $paramHash->{'variable'} = 'LATEX_TYPE';
        !          4534:         $helper->declareVar('LATEX_TYPE');
        !          4535:         if ( $helper->{VARS}->{'construction'} eq '1' ) {
        !          4536:             $paramHash->{CHOICES} = [
        !          4537:                 [ 'standard LaTeX mode', 'standard' ],
        !          4538:                 [ 'LaTeX batchmode',     'batchmode' ],
        !          4539:             ];
        !          4540:         }
        !          4541:         else {
        !          4542:             $paramHash->{CHOICES} = [
        !          4543:                 [ 'LaTeX batchmode',     'batchmode' ],
        !          4544:                 [ 'standard LaTeX mode', 'standard' ]
        !          4545:             ];
        !          4546:         }
1.210     sakharuk 4547:         Apache::lonhelper::dropdown->new();
1.575.2.1! foxr     4548: 
        !          4549:         &addMessage(
        !          4550:             &Apache::lonhtmlcommon::row_closure()
        !          4551:               . &Apache::lonhtmlcommon::row_title(
        !          4552:                     '<label for="TABLE_CONTENTS_forminput">'
        !          4553:                   . &mt('Print Table of Contents')
        !          4554:                   . '</label>'
        !          4555:               )
1.544     bisitz   4556:         );
1.209     sakharuk 4557:         $paramHash = Apache::lonhelper::getParamHash();
1.575.2.1! foxr     4558:         $paramHash->{'variable'} = 'TABLE_CONTENTS';
        !          4559:         $helper->declareVar('TABLE_CONTENTS');
        !          4560:         $paramHash->{CHOICES} = [ [ 'No', 'no' ], [ 'Yes', 'yes' ] ];
1.210     sakharuk 4561:         Apache::lonhelper::dropdown->new();
1.575.2.1! foxr     4562:         &addMessage( &Apache::lonhtmlcommon::row_closure() );
        !          4563: 
        !          4564:         if ( not $helper->{VARS}->{'construction'} ) {
        !          4565:             &addMessage(
        !          4566:                 &Apache::lonhtmlcommon::row_title(
        !          4567:                         '<label for="TABLE_INDEX_forminput">'
        !          4568:                       . &mt('Print Index')
        !          4569:                       . '</label>'
        !          4570:                 )
1.545     bisitz   4571:             );
1.575.2.1! foxr     4572:             $paramHash = Apache::lonhelper::getParamHash();
        !          4573:             $paramHash->{'variable'} = 'TABLE_INDEX';
        !          4574:             $helper->declareVar('TABLE_INDEX');
        !          4575:             $paramHash->{CHOICES} = [ [ 'No', 'no' ], [ 'Yes', 'yes' ] ];
        !          4576:             Apache::lonhelper::dropdown->new();
        !          4577:             &addMessage( &Apache::lonhtmlcommon::row_closure() );
        !          4578:             &addMessage(
        !          4579:                 &Apache::lonhtmlcommon::row_title(
        !          4580:                         '<label for="PRINT_DISCUSSIONS_forminput">'
        !          4581:                       . &mt('Print Discussions')
        !          4582:                       . '</label>'
        !          4583:                 )
1.545     bisitz   4584:             );
1.575.2.1! foxr     4585:             $paramHash = Apache::lonhelper::getParamHash();
        !          4586:             $paramHash->{'variable'} = 'PRINT_DISCUSSIONS';
        !          4587:             $helper->declareVar('PRINT_DISCUSSIONS');
        !          4588:             $paramHash->{CHOICES} = [ [ 'No', 'no' ], [ 'Yes', 'yes' ] ];
        !          4589:             Apache::lonhelper::dropdown->new();
        !          4590:             &addMessage( &Apache::lonhtmlcommon::row_closure() );
        !          4591: 
        !          4592:             # Prompt for printing annotations too.
        !          4593: 
        !          4594:             &addMessage(
        !          4595:                 &Apache::lonhtmlcommon::row_title(
        !          4596:                         '<label for="PRINT_ANNOTATIONS_forminput">'
        !          4597:                       . &mt('Print Annotations')
        !          4598:                       . '</label>'
        !          4599:                 )
1.545     bisitz   4600:             );
1.575.2.1! foxr     4601:             $paramHash = Apache::lonhelper::getParamHash();
        !          4602:             $paramHash->{'variable'} = "PRINT_ANNOTATIONS";
        !          4603:             $helper->declareVar("PRINT_ANNOTATIONS");
        !          4604:             $paramHash->{CHOICES} = [ [ 'No', 'no' ], [ 'Yes', 'yes' ] ];
        !          4605:             Apache::lonhelper::dropdown->new();
        !          4606:             &addMessage( &Apache::lonhtmlcommon::row_closure() );
        !          4607: 
        !          4608:             &addMessage( &Apache::lonhtmlcommon::row_title( &mt('Foils') ) );
        !          4609:             $paramHash                  = Apache::lonhelper::getParamHash();
        !          4610:             $paramHash->{'multichoice'} = "true";
        !          4611:             $paramHash->{'allowempty'}  = "true";
        !          4612:             $paramHash->{'variable'}    = "showallfoils";
        !          4613:             $paramHash->{'CHOICES'} = [ [ &mt('Show All Foils'), "1" ] ];
        !          4614:             Apache::lonhelper::choices->new();
        !          4615:             &addMessage( &Apache::lonhtmlcommon::row_closure(1) );
        !          4616:         }
1.219     sakharuk 4617: 
1.575.2.1! foxr     4618:         if ( $helper->{'VARS'}->{'construction'} ) {
        !          4619:             my $stylevalue     = '$Apache::lonnet::env{"construct.style"}';
        !          4620:             my $randseedtext   = &mt("Use random seed");
        !          4621:             my $stylefiletext  = &mt("Use style file");
        !          4622:             my $selectfiletext = &mt("Select style file");
        !          4623: 
        !          4624:             my $xmlfrag .=
        !          4625:               '<message>'
        !          4626:               . &Apache::lonhtmlcommon::row_title(
        !          4627:                 '<label for="curseed_forminput">' . $randseedtext . '</label>' )
        !          4628:               . '</message>
1.544     bisitz   4629:             <string variable="curseed" size="15" maxlength="15">
                   4630:                 <defaultvalue>
1.575.2.1! foxr     4631:                    return ' . $helper->{VARS}->{'curseed'} . ';
1.544     bisitz   4632:                 </defaultvalue>'
1.575.2.1! foxr     4633:               . '</string>'
        !          4634:               . '<message>'
        !          4635:               . &Apache::lonhtmlcommon::row_closure()
        !          4636:               . &Apache::lonhtmlcommon::row_title(
        !          4637:                 '<label for="style_file">' . $stylefiletext . '</label>' )
        !          4638:               . '</message>
1.504     albertel 4639:              <string variable="style_file" size="40">
1.544     bisitz   4640:                 <defaultvalue>
1.575.2.1! foxr     4641:                     return ' . $stylevalue . ';
1.544     bisitz   4642:                 </defaultvalue>
                   4643:              </string><message>&nbsp;'
1.575.2.1! foxr     4644:               . qq|<a href="javascript:openbrowser('helpform','style_file_forminput','sty')">|
        !          4645:               . $selectfiletext . '</a>'
        !          4646:               . &Apache::lonhtmlcommon::row_closure()
        !          4647:               . &Apache::lonhtmlcommon::row_title( &mt('Show All Foils') )
        !          4648:               . '</message>
1.371     foxr     4649: 	     <choices allowempty="1" multichoice="true" variable="showallfoils">
1.544     bisitz   4650:                 <choice computer="1">&nbsp;</choice>
                   4651:              </choices>'
1.575.2.1! foxr     4652:               . '<message>'
        !          4653:               . &Apache::lonhtmlcommon::row_closure()
        !          4654:               . '</message>';
        !          4655:             &Apache::lonxml::xmlparse( $r, 'helper', $xmlfrag );
        !          4656: 
        !          4657:             &addMessage(
        !          4658:                 &Apache::lonhtmlcommon::row_title( &mt('Problem Type') ) );
        !          4659: 
        !          4660:             #
        !          4661:             # Initial value from construction space:
        !          4662:             #
        !          4663:             if ( !$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'} )
        !          4664:             {
        !          4665:                 $helper->{VARS}->{'probstatus'} =
        !          4666:                   $env{'form.problemtype'};    # initial value
        !          4667:             }
        !          4668:             $xmlfrag = << "PROBTYPE";
1.518     foxr     4669: 		<dropdown variable="probstatus" multichoice="0" allowempty="0">
                   4670: 		   <defaultvalue>
                   4671: 		      return "$helper->{VARS}->{'probstatus'}";
                   4672:                    </defaultvalue>
                   4673: 		   <choice computer="problem">Homework Problem</choice>
                   4674: 		   <choice computer="exam">Exam Problem</choice>
                   4675: 		   <choice computer="survey">Survey question</choice>
1.572     raeburn  4676:                    ,choice computer="anonsurvey"Anonymous survey question</choice>
1.518     foxr     4677: 		</dropdown>
                   4678: PROBTYPE
1.575.2.1! foxr     4679:             &Apache::lonxml::xmlparse( $r, 'helper', $xmlfrag );
        !          4680:             &addMessage( &Apache::lonhtmlcommon::row_closure(1) );
1.556     foxr     4681: 
1.544     bisitz   4682:         }
1.223     bowersj2 4683:     }
1.264     sakharuk 4684: 
1.223     bowersj2 4685:     if ($startedTable) {
1.575.2.1! foxr     4686:         &addMessage( &Apache::lonhtmlcommon::end_pick_box() );
1.215     sakharuk 4687:     }
1.161     bowersj2 4688: 
1.131     bowersj2 4689:     Apache::lonprintout::page_format_state->new("FORMAT");
                   4690: 
1.144     bowersj2 4691:     # Generate the PAGESIZE state which will offer the user the margin
                   4692:     # choices if they select one column
1.575.2.1! foxr     4693:     Apache::lonhelper::state->new( "PAGESIZE", "Set Margins" );
        !          4694:     Apache::lonprintout::page_size_state->new( 'pagesize', 'FORMAT', 'FINAL' );
1.144     bowersj2 4695: 
1.131     bowersj2 4696:     $helper->process();
                   4697: 
                   4698:     # MANUAL BAILOUT CONDITION:
                   4699:     # If we're in the "final" state, bailout and return to handler
1.575.2.1! foxr     4700:     if ( $helper->{STATE} eq 'FINAL' ) {
1.131     bowersj2 4701:         return $helper;
1.575.2.1! foxr     4702:     }
1.130     sakharuk 4703: 
1.575.2.1! foxr     4704:     $r->print( $helper->display() );
        !          4705:     if ( $helper->{STATE} eq 'START' ) {
        !          4706:         &recently_generated($r);
1.395     www      4707:     }
1.333     albertel 4708:     &Apache::lonhelper::unregisterHelperTags();
1.115     bowersj2 4709: 
                   4710:     return OK;
                   4711: }
                   4712: 
1.1       www      4713: 1;
1.119     bowersj2 4714: 
                   4715: package Apache::lonprintout::page_format_state;
                   4716: 
                   4717: =pod
                   4718: 
1.131     bowersj2 4719: =head1 Helper element: page_format_state
                   4720: 
                   4721: See lonhelper.pm documentation for discussion of the helper framework.
1.119     bowersj2 4722: 
1.131     bowersj2 4723: Apache::lonprintout::page_format_state is an element that gives the 
                   4724: user an opportunity to select the page layout they wish to print 
                   4725: with: Number of columns, portrait/landscape, and paper size. If you 
                   4726: want to change the paper size choices, change the @paperSize array 
                   4727: contents in this package.
1.119     bowersj2 4728: 
1.131     bowersj2 4729: page_format_state is always directly invoked in lonprintout.pm, so there
                   4730: is no tag interface. You actually pass parameters to the constructor.
1.119     bowersj2 4731: 
                   4732: =over 4
                   4733: 
1.131     bowersj2 4734: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
1.119     bowersj2 4735: 
                   4736: =back
                   4737: 
                   4738: =cut
                   4739: 
1.131     bowersj2 4740: use Apache::lonhelper;
1.119     bowersj2 4741: 
                   4742: no strict;
1.131     bowersj2 4743: @ISA = ("Apache::lonhelper::element");
1.119     bowersj2 4744: use strict;
1.266     sakharuk 4745: use Apache::lonlocal;
1.373     albertel 4746: use Apache::lonnet;
1.119     bowersj2 4747: 
                   4748: my $maxColumns = 2;
1.575.2.1! foxr     4749: 
1.376     albertel 4750: # it'd be nice if these all worked
1.575.2.1! foxr     4751: #my @paperSize = ("letter [8 1/2x11 in]", "legal [8 1/2x14 in]",
1.376     albertel 4752: #                 "tabloid (ledger) [11x17 in]", "executive [7 1/2x10 in]",
1.575.2.1! foxr     4753: #                 "a2 [420x594 mm]", "a3 [297x420 mm]", "a4 [210x297 mm]",
1.376     albertel 4754: #                 "a5 [148x210 mm]", "a6 [105x148 mm]" );
1.575.2.1! foxr     4755: my @paperSize =
        !          4756:   ( "letter [8 1/2x11 in]", "legal [8 1/2x14 in]", "a4 [210x297 mm]" );
1.119     bowersj2 4757: 
                   4758: # Tentative format: Orientation (L = Landscape, P = portrait) | Colnum |
                   4759: #                   Paper type
                   4760: 
1.575.2.1! foxr     4761: sub new {
1.131     bowersj2 4762:     my $self = Apache::lonhelper::element->new();
1.119     bowersj2 4763: 
1.135     bowersj2 4764:     shift;
                   4765: 
1.131     bowersj2 4766:     $self->{'variable'} = shift;
1.134     bowersj2 4767:     my $helper = Apache::lonhelper::getHelper();
1.575.2.1! foxr     4768:     $helper->declareVar( $self->{'variable'} );
1.131     bowersj2 4769:     bless($self);
1.119     bowersj2 4770:     return $self;
                   4771: }
                   4772: 
                   4773: sub render {
1.575.2.1! foxr     4774:     my $self            = shift;
        !          4775:     my $helper          = Apache::lonhelper::getHelper();
        !          4776:     my $result          = '';
        !          4777:     my $var             = $self->{'variable'};
        !          4778:     my $PageLayout      = &mt('Page layout');
        !          4779:     my $NumberOfColumns = &mt('Number of columns');
        !          4780:     my $PaperType       = &mt('Paper type');
        !          4781:     my $landscape       = &mt('Landscape');
        !          4782:     my $portrait        = &mt('Portrait');
        !          4783:     my $pdfFormLabel    = &mt('PDF-Formfields');
        !          4784:     my $with            = &mt('with Formfields');
        !          4785:     my $without         = &mt('without Formfields');
        !          4786: 
        !          4787:     $result .= '<h3>'
        !          4788:       . &mt('Layout Options') . '</h3>'
        !          4789:       . &Apache::loncommon::start_data_table()
        !          4790:       . &Apache::loncommon::start_data_table_header_row() . '<th>'
        !          4791:       . $PageLayout . '</th>' . '<th>'
        !          4792:       . $NumberOfColumns . '</th>' . '<th>'
        !          4793:       . $PaperType . '</th>' . '<th>'
        !          4794:       . $pdfFormLabel . '</th>'
        !          4795:       . &Apache::loncommon::end_data_table_header_row()
        !          4796:       . &Apache::loncommon::start_data_table_row() . '<td>'
        !          4797:       . '<label><input type="radio" name="'
        !          4798:       . ${var}
        !          4799:       . '.layout" value="L" />'
        !          4800:       . $landscape
        !          4801:       . '</label><br />'
        !          4802:       . '<label><input type="radio" name="'
        !          4803:       . ${var}
        !          4804:       . '.layout" value="P" checked="checked" />'
        !          4805:       . $portrait
        !          4806:       . '</label>' . '</td>';
1.119     bowersj2 4807: 
1.575.2.1! foxr     4808:     $result .= '<td align="center">' . '<select name="' . ${var} . '.cols">';
1.119     bowersj2 4809: 
                   4810:     my $i;
1.575.2.1! foxr     4811:     for ( $i = 1 ; $i <= $maxColumns ; $i++ ) {
        !          4812:         if ( $i == 2 ) {
        !          4813:             $result .=
        !          4814:                 '<option value="' 
        !          4815:               . $i
        !          4816:               . '" selected="selected">'
        !          4817:               . $i
        !          4818:               . '</option>' . "\n";
        !          4819:         }
        !          4820:         else {
        !          4821:             $result .= '<option value="' . $i . '">' . $i . '</option>' . "\n";
1.119     bowersj2 4822:         }
                   4823:     }
                   4824: 
                   4825:     $result .= "</select></td><td>\n";
                   4826:     $result .= "<select name='${var}.paper'>\n";
                   4827: 
1.575.2.1! foxr     4828:     my %parmhash =
        !          4829:       &Apache::lonnet::coursedescription( $env{'request.course.id'} );
        !          4830:     my $DefaultPaperSize = lc( $parmhash{'default_paper_size'} );
        !          4831:     $DefaultPaperSize =~ s/\s//g;
        !          4832:     if ( $DefaultPaperSize eq '' ) { $DefaultPaperSize = 'letter'; }
1.119     bowersj2 4833:     $i = 0;
                   4834:     foreach (@paperSize) {
1.575.2.1! foxr     4835:         $_ =~ /(\w+)/;
        !          4836:         my $papersize = $1;
        !          4837:         if ( $paperSize[$i] =~ /$DefaultPaperSize/ ) {
        !          4838:             $result .=
        !          4839:                 '<option selected="selected" value="'
        !          4840:               . $papersize . '">'
        !          4841:               . $paperSize[$i]
        !          4842:               . '</option>' . "\n";
        !          4843:         }
        !          4844:         else {
        !          4845:             $result .=
        !          4846:                 '<option value="'
        !          4847:               . $papersize . '">'
        !          4848:               . $paperSize[$i]
        !          4849:               . '</option>' . "\n";
1.119     bowersj2 4850:         }
                   4851:         $i++;
                   4852:     }
1.539     onken    4853:     $result .= <<HTML;
                   4854:         </select>
                   4855:     </td>
                   4856:     <td align='center'>
                   4857:         <select name='${var}.pdfFormFields'>
1.553     bisitz   4858:             <option selected="selected" value="no">$without</option>
                   4859:             <option value="yes">$with</option>
1.539     onken    4860:         </select>
                   4861:     </td>
                   4862: HTML
1.575.2.1! foxr     4863:     $result .= &Apache::loncommon::end_data_table_row()
        !          4864:       . &Apache::loncommon::end_data_table();
1.539     onken    4865: 
1.119     bowersj2 4866:     return $result;
1.135     bowersj2 4867: }
                   4868: 
                   4869: sub postprocess {
                   4870:     my $self = shift;
                   4871: 
1.575.2.1! foxr     4872:     my $var    = $self->{'variable'};
1.136     bowersj2 4873:     my $helper = Apache::lonhelper->getHelper();
1.575.2.1! foxr     4874:     $helper->{VARS}->{$var} =
        !          4875:         $env{"form.$var.layout"} . '|'
        !          4876:       . $env{"form.$var.cols"} . '|'
        !          4877:       . $env{"form.$var.paper"} . '|'
        !          4878:       . $env{"form.$var.pdfFormFields"};
1.135     bowersj2 4879:     return 1;
1.119     bowersj2 4880: }
                   4881: 
                   4882: 1;
1.144     bowersj2 4883: 
                   4884: package Apache::lonprintout::page_size_state;
                   4885: 
                   4886: =pod
                   4887: 
                   4888: =head1 Helper element: page_size_state
                   4889: 
                   4890: See lonhelper.pm documentation for discussion of the helper framework.
                   4891: 
                   4892: Apache::lonprintout::page_size_state is an element that gives the 
                   4893: user the opportunity to further refine the page settings if they
                   4894: select a single-column page.
                   4895: 
                   4896: page_size_state is always directly invoked in lonprintout.pm, so there
                   4897: is no tag interface. You actually pass parameters to the constructor.
                   4898: 
                   4899: =over 4
                   4900: 
                   4901: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
                   4902: 
                   4903: =back
                   4904: 
                   4905: =cut
                   4906: 
                   4907: use Apache::lonhelper;
1.373     albertel 4908: use Apache::lonnet;
1.144     bowersj2 4909: no strict;
                   4910: @ISA = ("Apache::lonhelper::element");
                   4911: use strict;
                   4912: 
1.575.2.1! foxr     4913: sub new {
1.144     bowersj2 4914:     my $self = Apache::lonhelper::element->new();
                   4915: 
1.575.2.1! foxr     4916:     shift;    # disturbs me (probably prevents subclassing) but works (drops
        !          4917:               # package descriptor)... - Jeremy
1.144     bowersj2 4918: 
                   4919:     $self->{'variable'} = shift;
                   4920:     my $helper = Apache::lonhelper::getHelper();
1.575.2.1! foxr     4921:     $helper->declareVar( $self->{'variable'} );
1.144     bowersj2 4922: 
1.575.2.1! foxr     4923:     # The variable name of the format element, so we can look into
1.144     bowersj2 4924:     # $helper->{VARS} to figure out whether the columns are one or two
                   4925:     $self->{'formatvar'} = shift;
                   4926: 
                   4927:     $self->{NEXTSTATE} = shift;
                   4928:     bless($self);
1.467     foxr     4929: 
1.144     bowersj2 4930:     return $self;
                   4931: }
                   4932: 
                   4933: sub render {
1.575.2.1! foxr     4934:     my $self   = shift;
1.144     bowersj2 4935:     my $helper = Apache::lonhelper::getHelper();
                   4936:     my $result = '';
1.575.2.1! foxr     4937:     my $var    = $self->{'variable'};
1.467     foxr     4938: 
1.575.2.1! foxr     4939:     if ( defined $self->{ERROR_MSG} ) {
        !          4940:         $result .=
        !          4941:             '<br /><span class="LC_error">'
        !          4942:           . $self->{ERROR_MSG}
        !          4943:           . '</span><br />';
1.144     bowersj2 4944:     }
                   4945: 
1.575.2.1! foxr     4946:     my $format = $helper->{VARS}->{ $self->{'formatvar'} };
1.463     foxr     4947: 
                   4948:     # Use format to get sensible defaults for the margins:
                   4949: 
1.575.2.1! foxr     4950:     my ( $laystyle, $cols, $papersize ) = split( /\|/, $format );
        !          4951:     ($papersize) = split( / /, $papersize );
1.463     foxr     4952: 
1.559     foxr     4953:     $laystyle = &Apache::lonprintout::map_laystyle($laystyle);
1.463     foxr     4954: 
1.464     albertel 4955:     my %size;
1.575.2.1! foxr     4956:     (
        !          4957:         $size{'width_and_units'},
        !          4958:         $size{'height_and_units'},
        !          4959:         $size{'margin_and_units'}
        !          4960:     ) = &Apache::lonprintout::page_format( $papersize, $laystyle, $cols );
        !          4961: 
        !          4962:     foreach my $dimension ( 'width', 'height', 'margin' ) {
        !          4963:         ( $size{$dimension}, $size{ $dimension . '_unit' } ) =
        !          4964:           split( / +/, $size{ $dimension . '_and_units' }, 2 );
        !          4965: 
        !          4966:         foreach my $unit ( 'cm', 'in' ) {
        !          4967:             $size{ $dimension . '_options' } .= '<option ';
        !          4968:             if ( $size{ $dimension . '_unit' } eq $unit ) {
        !          4969:                 $size{ $dimension . '_options' } .= 'selected="selected" ';
        !          4970:             }
        !          4971:             $size{ $dimension . '_options' } .= '>' . $unit . '</option>';
        !          4972:         }
1.438     foxr     4973:     }
                   4974: 
1.470     foxr     4975:     # Adjust margin for LaTeX margin: .. requires units == cm or in.
                   4976: 
1.575.2.1! foxr     4977:     if ( $size{'margin_unit'} eq 'in' ) {
        !          4978:         $size{'margin'} += 1;
        !          4979:     }
        !          4980:     else {
        !          4981:         $size{'margin'} += 2.54;
1.470     foxr     4982:     }
1.548     bisitz   4983:     my %lt = &Apache::lonlocal::texthash(
                   4984:         'format' => 'How should each column be formatted?',
                   4985:         'width'  => 'Width',
                   4986:         'height' => 'Height',
                   4987:         'margin' => 'Left Margin'
                   4988:     );
                   4989: 
1.575.2.1! foxr     4990:     $result .= '<p>'
        !          4991:       . $lt{'format'} . '</p>'
        !          4992:       . &Apache::lonhtmlcommon::start_pick_box()
        !          4993:       . &Apache::lonhtmlcommon::row_title( $lt{'width'} )
        !          4994:       . '<input type="text" name="'
        !          4995:       . $var
        !          4996:       . '.width" value="'
        !          4997:       . $size{'width'}
        !          4998:       . '" size="4" />'
        !          4999:       . '<select name="'
        !          5000:       . $var
        !          5001:       . '.widthunit">'
        !          5002:       . $size{'width_options'}
        !          5003:       . '</select>'
        !          5004:       . &Apache::lonhtmlcommon::row_closure()
        !          5005:       . &Apache::lonhtmlcommon::row_title( $lt{'height'} )
        !          5006:       . '<input type="text" name="'
        !          5007:       . $var
        !          5008:       . '.height" value="'
        !          5009:       . $size{'height'}
        !          5010:       . '" size="4" />'
        !          5011:       . '<select name="'
        !          5012:       . $var
        !          5013:       . '.heightunit">'
        !          5014:       . $size{'height_options'}
        !          5015:       . '</select>'
        !          5016:       . &Apache::lonhtmlcommon::row_closure()
        !          5017:       . &Apache::lonhtmlcommon::row_title( $lt{'margin'} )
        !          5018:       . '<input type="text" name="'
        !          5019:       . $var
        !          5020:       . '.lmargin" value="'
        !          5021:       . $size{'margin'}
        !          5022:       . '" size="4" />'
        !          5023:       . '<select name="'
        !          5024:       . $var
        !          5025:       . '.lmarginunit">'
        !          5026:       . $size{'margin_options'}
        !          5027:       . '</select>'
        !          5028:       . &Apache::lonhtmlcommon::row_closure(1)
        !          5029:       . &Apache::lonhtmlcommon::end_pick_box();
        !          5030: 
1.548     bisitz   5031:     # <p>Hint: Some instructors like to leave scratch space for the student by
                   5032:     # making the width much smaller than the width of the page.</p>
1.144     bowersj2 5033: 
                   5034:     return $result;
                   5035: }
                   5036: 
                   5037: sub preprocess {
1.575.2.1! foxr     5038:     my $self   = shift;
1.144     bowersj2 5039:     my $helper = Apache::lonhelper::getHelper();
                   5040: 
1.575.2.1! foxr     5041:     my $format = $helper->{VARS}->{ $self->{'formatvar'} };
1.467     foxr     5042: 
                   5043:     #  If the user does not have 'pav' privilege, set default widths and
                   5044:     #  on to the next state right away.
                   5045:     #
1.575.2.1! foxr     5046:     if ( !$perm{'pav'} ) {
        !          5047:         my $var    = $self->{'variable'};
        !          5048:         my $format = $helper->{VARS}->{ $self->{'formatvar'} };
        !          5049: 
        !          5050:         my ( $laystyle, $cols, $papersize ) = split( /\|/, $format );
        !          5051:         ($papersize) = split( / /, $papersize );
        !          5052: 
        !          5053:         $laystyle = &Apache::lonprintout::map_laystyle($laystyle);
        !          5054: 
        !          5055:         #  Figure out some good defaults for the print out and set them:
        !          5056: 
        !          5057:         my %size;
        !          5058:         ( $size{'width'}, $size{'height'}, $size{'lmargin'} ) =
        !          5059:           &Apache::lonprintout::page_format( $papersize, $laystyle, $cols );
        !          5060: 
        !          5061:         foreach my $dim ( 'width', 'height', 'lmargin' ) {
        !          5062:             my ( $value, $units ) = split( / /, $size{$dim} );
1.467     foxr     5063: 
1.575.2.1! foxr     5064:             $helper->{VARS}->{ "$var." . $dim } = $value;
        !          5065:             $helper->{VARS}->{ "$var." . $dim . 'unit' } = $units;
1.467     foxr     5066: 
1.575.2.1! foxr     5067:         }
        !          5068: 
        !          5069:         # Transition to the next state
        !          5070: 
        !          5071:         $helper->changeState( $self->{NEXTSTATE} );
1.467     foxr     5072:     }
1.575.2.1! foxr     5073: 
1.144     bowersj2 5074:     return 1;
                   5075: }
                   5076: 
                   5077: sub postprocess {
                   5078:     my $self = shift;
                   5079: 
1.575.2.1! foxr     5080:     my $var    = $self->{'variable'};
1.144     bowersj2 5081:     my $helper = Apache::lonhelper->getHelper();
1.575.2.1! foxr     5082:     my $width  = $helper->{VARS}->{ $var . '.width' } =
        !          5083:       $env{"form.${var}.width"};
        !          5084:     my $height = $helper->{VARS}->{ $var . '.height' } =
        !          5085:       $env{"form.${var}.height"};
        !          5086:     my $lmargin = $helper->{VARS}->{ $var . '.lmargin' } =
        !          5087:       $env{"form.${var}.lmargin"};
        !          5088:     $helper->{VARS}->{ $var . '.widthunit' }  = $env{"form.${var}.widthunit"};
        !          5089:     $helper->{VARS}->{ $var . '.heightunit' } = $env{"form.${var}.heightunit"};
        !          5090:     $helper->{VARS}->{ $var . '.lmarginunit' } =
        !          5091:       $env{"form.${var}.lmarginunit"};
1.144     bowersj2 5092: 
                   5093:     my $error = '';
                   5094: 
1.575.2.1! foxr     5095:     # /^-?[0-9]+(\.[0-9]*)?$/ -> optional minus, at least on digit, followed
1.144     bowersj2 5096:     # by an optional period, followed by digits, ending the string
                   5097: 
1.575.2.1! foxr     5098:     if ( $width !~ /^-?[0-9]*(\.[0-9]*)?$/ ) {
1.144     bowersj2 5099:         $error .= "Invalid width; please type only a number.<br />\n";
                   5100:     }
1.575.2.1! foxr     5101:     if ( $height !~ /^-?[0-9]*(\.[0-9]*)?$/ ) {
1.144     bowersj2 5102:         $error .= "Invalid height; please type only a number.<br />\n";
                   5103:     }
1.575.2.1! foxr     5104:     if ( $lmargin !~ /^-?[0-9]*(\.[0-9]*)?$/ ) {
1.144     bowersj2 5105:         $error .= "Invalid left margin; please type only a number.<br />\n";
1.575.2.1! foxr     5106:     }
        !          5107:     else {
1.470     foxr     5108: 
1.575.2.1! foxr     5109:         # Adjust for LaTeX 1.0 inch margin:
        !          5110: 
        !          5111:         if ( $env{"form.${var}.lmarginunit"} eq "in" ) {
        !          5112:             $helper->{VARS}->{ $var . '.lmargin' } = $lmargin - 1;
        !          5113:         }
        !          5114:         else {
        !          5115:             $helper->{VARS}->{ $var . '.lmargin' } = $lmargin - 2.54;
        !          5116:         }
1.144     bowersj2 5117:     }
                   5118: 
1.575.2.1! foxr     5119:     if ( !$error ) {
        !          5120:         Apache::lonhelper::getHelper()->changeState( $self->{NEXTSTATE} );
1.144     bowersj2 5121:         return 1;
1.575.2.1! foxr     5122:     }
        !          5123:     else {
1.144     bowersj2 5124:         $self->{ERROR_MSG} = $error;
                   5125:         return 0;
                   5126:     }
                   5127: }
                   5128: 
1.1       www      5129: __END__
1.6       sakharuk 5130: 

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