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

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

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