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