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