Annotation of loncom/interface/lonprintout.pm, revision 1.583.2.6
1.562 foxr 1: #
1.389 foxr 2: # The LearningOnline Network
1.1 www 3: # Printout
4: #
1.583.2.6! raeburn 5: # $Id: lonprintout.pm,v 1.583.2.5 2011/09/15 16:33:57 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://|;
1.583.2.6! raeburn 1532: $currentURL=~s|http://https://|https://|;
1.414 albertel 1533: my $title=&Apache::lonnet::gettitle($symb);
1534: $title = &Apache::lonxml::latex_special_symbols($title);
1535: $result.=' \strut \\\\ '.$title.' \strut \\\\ '.$currentURL.' ';
1.296 sakharuk 1536: } else {
1537: $result.=$currentURL;
1538: }
1.419 albertel 1539: $result.= '\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill} \end{document}';
1.296 sakharuk 1540: return $result;
1541: }
1542:
1.559 foxr 1543: #
1544: # Map from helper layout style to the book/album:
1545: #
1546: sub map_laystyle {
1547: my ($laystyle) = @_;
1548: if ($laystyle eq 'L') {
1549: $laystyle='album';
1550: } else {
1551: $laystyle='book';
1552: }
1553: return $laystyle;
1554: }
1555:
1556: sub print_page_in_course {
1557: my ($helper, $rparmhash, $currentURL, $resources) = @_;
1558: my %parmhash = %$rparmhash;
1559: my @page_resources = @$resources;
1560: my $mode = $helper->{'VARS'}->{'LATEX_TYPE'};
1561: my $symb = $helper->{'VARS'}->{'symb'};
1562:
1563:
1564: my $format_from_helper = $helper->{'VARS'}->{'FORMAT'};
1565:
1566:
1567: my @temporary_array=split /\|/,$format_from_helper;
1568: my ($laystyle,$numberofcolumns,$papersize,$pdfFormFields)=@temporary_array;
1569: $laystyle = &map_laystyle($laystyle);
1570: my ($textwidth,$textheight,$oddoffset,$evenoffset) = &page_format($papersize,$laystyle,
1571: $numberofcolumns);
1572: my $LaTeXwidth=&recalcto_mm($textwidth);
1573:
1574:
1575: if ($mode ne '') {$mode='\\'.$mode}
1.562 foxr 1576: my $result = &print_latex_header($mode);
1.559 foxr 1577: if ($currentURL=~m|^(/adm/wrapper/)?ext/|) {
1578: $currentURL=~s|^(/adm/wrapper/)?ext/|http://|;
1579: my $title=&Apache::lonnet::gettitle($symb);
1580: $title = &Apache::lonxml::latex_special_symbols($title);
1581: } else {
1.582 raeburn 1582: my $esc_currentURL= $currentURL;
1583: $esc_currentURL =~ s/_/\\_/g;
1584: $result.=$esc_currentURL;
1.559 foxr 1585: }
1586: $result .= '\\\\';
1587:
1588: if ($helper->{'VARS'}->{'style_file'}=~/\w/) {
1589: &Apache::lonnet::appenv({'construct.style' =>
1590: $helper->{'VARS'}->{'style_file'}});
1591: } elsif ($env{'construct.style'}) {
1592: &Apache::lonnet::delenv('construct.style');
1593: }
1594:
1595: # First is the overall page description. This is then followed by the
1596: # components of the page. Each of which must be printed independently.
1.564 foxr 1597: my $the_page = shift(@page_resources);
1.559 foxr 1598:
1599:
1600: foreach my $resource (@page_resources) {
1601: my $resource_src = $resource->src(); # Essentially the URL of the resource.
1602: $result .= $resource->title() . '\\\\';
1603:
1604: # Recurse if a .page:
1605:
1606: if ($resource_src =~ /.page$/i) {
1607: my $navmap = Apache::lonnavmaps::navmap->new();
1608: my @page_resources = $navmap->retrieveResources($resource_src);
1609: $result .= &print_page_in_course($helper, $rparmhash,
1610: $resource_src, \@page_resources);
1611: }
1612: # these resources go through the XML transformer:
1613:
1.582 raeburn 1614: elsif ($resource_src =~ /\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) {
1.559 foxr 1615: my $urlp = &Apache::lonnet::clutter($resource_src);
1616: my %form;
1617: my %moreenv;
1618:
1619: &Apache::lonxml::remember_problem_counter();
1620: $moreenv{'request.filename'}=$urlp;
1621: if ($helper->{'VARS'}->{'probstatus'} eq 'exam') {$form{'problemtype'}='exam';}
1622:
1623: $form{'grade_target'} = 'tex';
1624: $form{'textwidth'} = &get_textwidth($helper, $LaTeXwidth);
1.583.2.2 raeburn 1625: $form{'pdfFormFields'} = 'no';
1.559 foxr 1626: $form{'showallfoils'} = $helper->{'VARS'}->{'showallfoils'};
1627:
1628: $form{'problem_split'}=$parmhash{'problem_stream_switch'};
1629: $form{'suppress_tries'}=$parmhash{'suppress_tries'};
1630: $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1631: $form{'print_discussions'}=$helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
1632: $form{'print_annotations'}=$helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
1633: if (($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes') ||
1634: ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes')) {
1635: $form{'problem_split'}='yes';
1636: }
1637: my $rndseed = time;
1638: if ($helper->{'VARS'}->{'curseed'}) {
1639: $rndseed=$helper->{'VARS'}->{'curseed'};
1640: }
1641: $form{'rndseed'}=$rndseed;
1642: &Apache::lonnet::appenv(\%moreenv);
1643:
1644: &Apache::lonxml::clear_problem_counter();
1645:
1646: my $texversion = &ssi_with_retries($urlp, $ssi_retry_count, %form);
1647:
1648:
1649: # current document with answers.. no need to encap in minipage
1650: # since there's only one answer.
1651:
1652: if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
1653: ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1654: my %answerform = %form;
1655:
1656:
1657: $answerform{'problem_split'}=$parmhash{'problem_stream_switch'};
1658: $answerform{'grade_target'}='answer';
1659: $answerform{'answer_output_mode'}='tex';
1660: $answerform{'rndseed'}=$rndseed;
1661: if ($helper->{'VARS'}->{'probstatus'} eq 'exam') {
1662: $answerform{'problemtype'}='exam';
1663: }
1664: $resources_printed .= $urlp.':';
1665: my $answer=&ssi_with_retries($urlp,$ssi_retry_count, %answerform);
1666:
1667: if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
1668: $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
1669: } else {
1.562 foxr 1670: $texversion= &print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.559 foxr 1671: if ($helper->{'VARS'}->{'construction'} ne '1') {
1672: my $title = &Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'});
1673: $title = &Apache::lonxml::latex_special_symbols($title);
1674: $texversion.='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
1675: $texversion.=&path_to_problem($urlp,$LaTeXwidth);
1676: } else {
1677: $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
1678: my $URLpath=$urlp;
1679: $URLpath=~s/~([^\/]+)/public_html\/$1\/$1/;
1680: $texversion.=&path_to_problem($URLpath,$LaTeXwidth);
1681: }
1682: $texversion.='\vskip 1 mm '.$answer.'\end{document}';
1683: }
1684:
1685:
1686:
1687:
1688:
1689: }
1690: # Print annotations.
1691:
1692:
1693: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
1694: my $annotation .= &annotate($currentURL);
1695: $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
1696: }
1697:
1698: if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
1699: $texversion=&IndexCreation($texversion,$currentURL);
1700: }
1701: if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') {
1702: $texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$currentURL| \\strut\\\\\\strut /;
1703:
1704: }
1.562 foxr 1705: $texversion = &latex_header_footer_remove($texversion);
1706:
1707: # the first remaining line is a comment from londefdef the second
1708: # line seems to be an extraneous \vskip 1mm \\\\ :
1709: # (imperfect removal from header_footer_remove?
1710:
1711: $texversion =~ s/\\vskip 1mm \\\\\\\\//;
1712:
1.559 foxr 1713: $result .= $texversion;
1714: if ($currentURL=~m/\.page\s*$/) {
1715: ($result,$numberofcolumns) = &page_cleanup($result);
1716: }
1717: }
1718: }
1719:
1720: $result.= '\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill} \end{document}';
1721: return $result;
1722: }
1723:
1.296 sakharuk 1724:
1.363 foxr 1725: #
1.395 www 1726: # List of recently generated print files
1727: #
1728: sub recently_generated {
1.583.2.3 raeburn 1729: my ($prtspool) = @_;
1730: my $output;
1.400 albertel 1731: my $zip_result;
1732: my $pdf_result;
1.395 www 1733: opendir(DIR,$prtspool);
1.400 albertel 1734:
1735: my @files =
1736: grep(/^$env{'user.name'}_$env{'user.domain'}_printout_(\d+)_.*\.(pdf|zip)$/,readdir(DIR));
1.395 www 1737: closedir(DIR);
1.400 albertel 1738:
1739: @files = sort {
1740: my ($actime) = (stat($prtspool.'/'.$a))[10];
1741: my ($bctime) = (stat($prtspool.'/'.$b))[10];
1742: return $bctime <=> $actime;
1743: } (@files);
1744:
1745: foreach my $filename (@files) {
1746: my ($ext) = ($filename =~ m/(pdf|zip)$/);
1747: my ($cdev,$cino,$cmode,$cnlink,
1748: $cuid,$cgid,$crdev,$csize,
1749: $catime,$cmtime,$cctime,
1750: $cblksize,$cblocks)=stat($prtspool.'/'.$filename);
1.544 bisitz 1751: my $ext_text = 'pdf' ? &mt('PDF File'):&mt('Zip File');
1752: my $result=&Apache::loncommon::start_data_table_row()
1753: .'<td>'
1754: .'<a href="/prtspool/'.$filename.'">'.$ext_text.'</a>'
1755: .'</td>'
1756: .'<td>'.&Apache::lonlocal::locallocaltime($cctime).'</td>'
1757: .'<td align="right">'.$csize.'</td>'
1758: .&Apache::loncommon::end_data_table_row();
1.400 albertel 1759: if ($ext eq 'pdf') { $pdf_result .= $result; }
1760: if ($ext eq 'zip') { $zip_result .= $result; }
1761: }
1.544 bisitz 1762: if ($zip_result || $pdf_result) {
1.583.2.3 raeburn 1763: $output ='<hr />';
1.544 bisitz 1764: }
1.400 albertel 1765: if ($zip_result) {
1.583.2.3 raeburn 1766: $output .='<h3>'.&mt('Recently generated printout zip files')."</h3>\n"
1.544 bisitz 1767: .&Apache::loncommon::start_data_table()
1768: .&Apache::loncommon::start_data_table_header_row()
1769: .'<th>'.&mt('Download').'</th>'
1770: .'<th>'.&mt('Creation Date').'</th>'
1771: .'<th>'.&mt('File Size (Bytes)').'</th>'
1772: .&Apache::loncommon::end_data_table_header_row()
1773: .$zip_result
1.583.2.3 raeburn 1774: .&Apache::loncommon::end_data_table();
1.400 albertel 1775: }
1776: if ($pdf_result) {
1.583.2.3 raeburn 1777: $output .='<h3>'.&mt('Recently generated printouts')."</h3>\n"
1.544 bisitz 1778: .&Apache::loncommon::start_data_table()
1779: .&Apache::loncommon::start_data_table_header_row()
1780: .'<th>'.&mt('Download').'</th>'
1781: .'<th>'.&mt('Creation Date').'</th>'
1782: .'<th>'.&mt('File Size (Bytes)').'</th>'
1783: .&Apache::loncommon::end_data_table_header_row()
1784: .$pdf_result
1.583.2.3 raeburn 1785: .&Apache::loncommon::end_data_table();
1.396 albertel 1786: }
1.583.2.3 raeburn 1787: return $output;
1.395 www 1788: }
1789:
1790: #
1.363 foxr 1791: # Retrieve the hash of page breaks.
1792: #
1793: # Inputs:
1794: # helper - reference to helper object.
1795: # Outputs
1796: # A reference to a page break hash.
1797: #
1798: #
1.562 foxr 1799: # use Data::Dumper;
1.569 foxr 1800: # sub dump_helper_vars {
1.418 foxr 1801: # my ($helper) = @_;
1802: # my $helpervars = Dumper($helper->{'VARS'});
1803: # &Apache::lonnet::logthis("Dump of helper vars:\n $helpervars");
1804: #}
1.363 foxr 1805:
1.481 albertel 1806: sub get_page_breaks {
1807: my ($helper) = @_;
1808: my %page_breaks;
1809:
1810: foreach my $break (split /\|\|\|/, $helper->{'VARS'}->{'FINISHPAGE'}) {
1811: $page_breaks{$break} = 1;
1812: }
1813: return %page_breaks;
1814: }
1.569 foxr 1815: #
1816: # Returns text to insert for any extra vskip prior to the resource.
1817: # Parameters:
1818: # helper - Reference to the helper object driving the printout.
1819: # resource - Identifies the resource about to be printed.
1820: #
1821: # This is done as follows:
1822: # POSSIBLE_RESOURCES has the list of possible resources.
1823: # EXTRASPACE has the list of extra space values.
1.570 foxr 1824: # EXTRASPACE_UNITS is the set of resources for which the units are
1825: # mm. All others are 'in'.
1.569 foxr 1826: #
1827: # The resource is found in the POSSIBLE_RESOURCES to get the index
1828: # of the EXTRASPACE value.
1829: #
1830: # In order to speed this up for lengthy printouts, the first time,
1831: # POSSIBLE_RESOURCES is turned into a look up hash and
1832: # EXTRASPACE is turned into an array.
1833: #
1834:
1835:
1836: my %possible_resources;
1.570 foxr 1837: my %extraspace_mm;
1.569 foxr 1838: my @extraspace;
1839: my $skips_loaded = 0;
1840:
1841: # Function to load the skips hash and array
1842:
1843: sub load_skips {
1844:
1845: my ($helper) = @_;
1846:
1847: # If this is the first time, unrap the resources and extra spaces:
1848:
1849: if (!$skips_loaded) {
1850: @extraspace = (split(/\|\|\|/, $helper->{'VARS'}->{'EXTRASPACE'}));
1851: my @resource_list = (split(/\|\|\|/, $helper->{'VARS'}->{'POSSIBLE_RESOURCES'}));
1852: my $i = 0;
1853: foreach my $resource (@resource_list) {
1854: $possible_resources{$resource} = $i;
1855: $i++;
1856: }
1.570 foxr 1857: foreach my $mm_resource (split(/\|\|\|/, $helper->{'VARS'}->{'EXTRASPACE_UNITS'})) {
1858: $extraspace_mm{$mm_resource} = 1;
1859: }
1.569 foxr 1860: $skips_loaded = 1;
1861: }
1862: }
1863:
1864: sub get_extra_vspaces {
1865: my ($helper, $resource) = @_;
1866:
1867: &load_skips($helper);
1868:
1869: # Lookup the resource in the possible resources hash.. that is the index
1870: # into the extraspace array that gives us either an empty string or
1871: # the number of mm to skip:
1872:
1873: my $index = $possible_resources{$resource};
1874: my $skip = $extraspace[$index];
1875:
1876: my $result = '';
1877: if ($skip ne '') {
1.570 foxr 1878: my $units = 'in';
1879: if (defined($extraspace_mm{$resource})) {
1880: $units = 'mm';
1881: }
1882: $result = '\vskip '.$skip.' '.$units;
1.569 foxr 1883: }
1.570 foxr 1884:
1885:
1.569 foxr 1886: return $result;
1887:
1888:
1889: }
1890:
1891: #
1892: # The resource chooser part of the helper needs more than just
1893: # the value of the extraspaces var to recover the value into a text
1894: # field option. This sub produces the required format for the saved var:
1895: # specifically
1896: # ||| separated fields of the form resourcename=value
1897: #
1898: # Parameters:
1899: # $helper - Refers to the helper we are configuring
1900: # Implicit input:
1901: # $helper->{'VARS'}->{'EXTRASPACE'} - the spaces helper var has the text field
1902: # value.
1.570 foxr 1903: # $helper->{'VARS'}->{'EXTRASPACE_UNITS'} - units for the skips (checkboxes).
1.569 foxr 1904: # $helper->{'VARS'}->{'POSSIBLE_RESOURCES'} - has the list of resources. |||
1905: # separated of course.
1906: # Implicit outputs:
1.570 foxr 1907: # $env{'form.extraspace'}
1908: # $env{'form.extraspace_units'}
1.569 foxr 1909: #
1910: sub set_form_extraspace {
1911: my ($helper) = @_;
1912:
1913: # the most convenient way to do this is to drive from the skips arrays/hash.
1914: # may not be the fastest, but this is once per print request so it's not so
1915: # speed critical:
1916:
1917: &load_skips($helper);
1918:
1919: my $result = '';
1920:
1921: foreach my $resource (keys(%possible_resources)) {
1922: my $vskip = $extraspace[$possible_resources{$resource}];
1923: $result .= $resource .'=' . $vskip . '|||';
1924: }
1925:
1926: $env{'form.extraspace'} = $result;
1.570 foxr 1927: $env{'form.extraspace_units'} = $helper->{'VARS'}->{'EXTRASPACE_UNITS'};
1.569 foxr 1928: return $result;
1929:
1930: }
1.363 foxr 1931:
1.459 foxr 1932: # Output a sequence (recursively if neeed)
1933: # from construction space.
1934: # Parameters:
1935: # url = URL of the sequence to print.
1936: # helper - Reference to the helper hash.
1937: # form - Copy of the format hash.
1938: # LaTeXWidth
1939: # Returns:
1940: # Text to add to the printout.
1941: # NOTE if the first element of the outermost sequence
1942: # is itself a sequence, the outermost caller may need to
1943: # prefix the latex with the page headers stuff.
1944: #
1945: sub print_construction_sequence {
1946: my ($currentURL, $helper, %form, $LaTeXwidth) = @_;
1947: my $result;
1948: my $rndseed=time;
1949: if ($helper->{'VARS'}->{'curseed'}) {
1950: $rndseed=$helper->{'VARS'}->{'curseed'};
1951: }
1.491 albertel 1952: my $errtext=&LONCAPA::map::mapread($currentURL);
1.459 foxr 1953: #
1954: # These make this all support recursing for subsequences.
1955: #
1.491 albertel 1956: my @order = @LONCAPA::map::order;
1957: my @resources = @LONCAPA::map::resources;
1.459 foxr 1958: for (my $member=0;$member<=$#order;$member++) {
1959: $resources[$order[$member]]=~/^([^:]*):([^:]*):/;
1960: my $urlp=$2;
1961: if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) {
1962: my $texversion='';
1963: if ($helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only') {
1964: $form{'problem_split'}=$parmhash{'problem_stream_switch'};
1965: $form{'suppress_tries'}=$parmhash{'suppress_tries'};
1966: $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1967: $form{'rndseed'}=$rndseed;
1968: $resources_printed .=$urlp.':';
1.515 foxr 1969: $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
1.459 foxr 1970: }
1971: if((($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
1972: ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) &&
1973: ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) {
1974: # Don't permanently modify %$form...
1975: my %answerform = %form;
1976: $answerform{'grade_target'}='answer';
1977: $answerform{'answer_output_mode'}='tex';
1978: $answerform{'rndseed'}=$rndseed;
1979: $answerform{'problem_split'}=$parmhash{'problem_stream_switch'};
1.481 albertel 1980: if ($urlp=~/\/res\//) {$env{'request.state'}='published';}
1.459 foxr 1981: $resources_printed .= $urlp.':';
1.515 foxr 1982: my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
1.459 foxr 1983: if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
1984: $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
1985: } else {
1986: # If necessary, encapsulate answer in minipage:
1987:
1988: $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.477 albertel 1989: my $title = &Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'});
1990: $title = &Apache::lonxml::latex_special_symbols($title);
1991: my $body ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
1.459 foxr 1992: $body.=&path_to_problem($urlp,$LaTeXwidth);
1993: $body.='\vskip 1 mm '.$answer.'\end{document}';
1994: $body = &encapsulate_minipage($body);
1995: $texversion.=$body;
1996: }
1997: }
1998: $texversion = &latex_header_footer_remove($texversion);
1999:
2000: if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
2001: $texversion=&IndexCreation($texversion,$urlp);
2002: }
2003: if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') {
2004: $texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /;
2005: }
2006: $result.=$texversion;
2007:
2008: } elsif ($urlp=~/\.(sequence|page)$/) {
1.557 foxr 2009:
1.459 foxr 2010: # header:
2011:
2012: $result.='\strut\newline\noindent Sequence/page '.$urlp.'\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent ';
2013:
2014: # IF sequence, recurse:
2015:
2016: if ($urlp =~ /\.sequence$/) {
2017: my $sequence_url = $urlp;
2018: my $domain = $env{'user.domain'}; # Constr. space only on local
2019: my $user = $env{'user.name'};
2020:
2021: $sequence_url =~ s/^\/res\/$domain/\/home/;
2022: $sequence_url =~ s/^(\/home\/$user)/$1\/public_html/;
2023: # $sequence_url =~ s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;
2024: $result .= &print_construction_sequence($sequence_url,
2025: $helper, %form,
2026: $LaTeXwidth);
2027: }
1.550 foxr 2028: }
2029: elsif ($urlp =~ /\.pdf$/i) {
1.552 foxr 2030: my $texversion;
2031: if ($member != 0) {
2032: $texversion .= '\cleardoublepage';
2033: }
2034:
2035: $texversion .= &include_pdf($urlp);
2036: $texversion = &latex_header_footer_remove($texversion);
2037: if ($member != $#order) {
2038: $texversion .= '\\ \cleardoublepage';
2039: }
1.551 foxr 2040:
2041: $result .= $texversion;
1.550 foxr 2042: }
1.459 foxr 2043: }
2044: if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\begin{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;}
2045: return $result;
2046: }
2047:
1.177 sakharuk 2048: sub output_data {
1.184 sakharuk 2049: my ($r,$helper,$rparmhash) = @_;
2050: my %parmhash = %$rparmhash;
1.515 foxr 2051: $ssi_error = 0; # This will be set nonzero by failing ssi's.
1.459 foxr 2052: $resources_printed = '';
1.556 foxr 2053: $font_size = $helper->{'VARS'}->{'fontsize'};
1.499 foxr 2054: my $do_postprocessing = 1;
1.433 albertel 2055: my $js = <<ENDPART;
2056: <script type="text/javascript">
1.264 sakharuk 2057: var editbrowser;
2058: function openbrowser(formname,elementname,only,omit) {
2059: var url = '/res/?';
2060: if (editbrowser == null) {
2061: url += 'launch=1&';
2062: }
2063: url += 'catalogmode=interactive&';
2064: url += 'mode=parmset&';
2065: url += 'form=' + formname + '&';
2066: if (only != null) {
2067: url += 'only=' + only + '&';
2068: }
2069: if (omit != null) {
2070: url += 'omit=' + omit + '&';
2071: }
2072: url += 'element=' + elementname + '';
2073: var title = 'Browser';
2074: var options = 'scrollbars=1,resizable=1,menubar=0';
2075: options += ',width=700,height=600';
2076: editbrowser = open(url,title,options,'1');
2077: editbrowser.focus();
2078: }
2079: </script>
1.140 sakharuk 2080: ENDPART
2081:
1.512 foxr 2082:
1.558 bisitz 2083: # Breadcrumbs
2084: #FIXME: Choose better/different breadcrumbs?!? Links?
2085: my $brcrum = [{'href' => '',
2086: 'text' => 'Helper'}, #FIXME: Different origin possible than print out helper?
2087: {'href' => '',
2088: 'text' => 'Preparing Printout'}];
2089:
2090: my $start_page = &Apache::loncommon::start_page('Preparing Printout',
2091: $js,
2092: {'bread_crumbs' => $brcrum,});
1.433 albertel 2093: my $msg = &mt('Please stand by while processing your print request, this may take some time ...');
1.363 foxr 2094:
1.433 albertel 2095: $r->print($start_page."\n<p>\n$msg\n</p>\n");
1.372 foxr 2096:
1.363 foxr 2097: # fetch the pagebreaks and store them in the course environment
2098: # The page breaks will be pulled into the hash %page_breaks which is
2099: # indexed by symb and contains 1's for each break.
2100:
1.373 albertel 2101: $env{'form.pagebreaks'} = $helper->{'VARS'}->{'FINISHPAGE'};
1.569 foxr 2102: &set_form_extraspace($helper);
1.373 albertel 2103: $env{'form.lastprinttype'} = $helper->{'VARS'}->{'PRINT_TYPE'};
1.363 foxr 2104: &Apache::loncommon::store_course_settings('print',
1.366 foxr 2105: {'pagebreaks' => 'scalar',
1.569 foxr 2106: 'extraspace' => 'scalar',
1.570 foxr 2107: 'extraspace_units' => 'scalar',
1.366 foxr 2108: 'lastprinttype' => 'scalar'});
1.364 albertel 2109: my %page_breaks = &get_page_breaks($helper);
1.363 foxr 2110:
1.140 sakharuk 2111: my $format_from_helper = $helper->{'VARS'}->{'FORMAT'};
2112: my ($result,$selectionmade) = ('','');
2113: my $number_of_columns = 1; #used only for pages to determine the width of the cell
2114: my @temporary_array=split /\|/,$format_from_helper;
1.539 onken 2115: my ($laystyle,$numberofcolumns,$papersize,$pdfFormFields)=@temporary_array;
1.559 foxr 2116:
2117: $laystyle = &map_laystyle($laystyle);
1.177 sakharuk 2118: my ($textwidth,$textheight,$oddoffset,$evenoffset) = &page_format($papersize,$laystyle,$numberofcolumns);
1.373 albertel 2119: my $assignment = $env{'form.assignment'};
1.275 sakharuk 2120: my $LaTeXwidth=&recalcto_mm($textwidth);
1.272 sakharuk 2121: my @print_array=();
1.274 sakharuk 2122: my @student_names=();
1.360 albertel 2123:
1.512 foxr 2124:
1.360 albertel 2125: # Common settings for the %form has:
2126: # In some cases these settings get overriddent by specific cases, but the
2127: # settings are common enough to make it worthwhile factoring them out
2128: # here.
2129: #
2130: my %form;
2131: $form{'grade_target'} = 'tex';
2132: $form{'textwidth'} = &get_textwidth($helper, $LaTeXwidth);
1.583.2.2 raeburn 2133: $form{'pdfFormFields'} = 'no';
1.372 foxr 2134:
2135: # If form.showallfoils is set, then request all foils be shown:
2136: # privilege will be enforced both by not allowing the
2137: # check box selecting this option to be presnt unless it's ok,
2138: # and by lonresponse's priv. check.
2139: # The if is here because lonresponse.pm only cares that
2140: # showallfoils is defined, not what the value is.
2141:
2142: if ($helper->{'VARS'}->{'showallfoils'} eq "1") {
2143: $form{'showallfoils'} = $helper->{'VARS'}->{'showallfoils'};
2144: }
1.504 albertel 2145:
2146: if ($helper->{'VARS'}->{'style_file'}=~/\w/) {
1.520 raeburn 2147: &Apache::lonnet::appenv({'construct.style' =>
2148: $helper->{'VARS'}->{'style_file'}});
1.504 albertel 2149: } elsif ($env{'construct.style'}) {
1.549 raeburn 2150: &Apache::lonnet::delenv('construct.style');
1.504 albertel 2151: }
2152:
1.140 sakharuk 2153: if ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'current_document') {
1.143 sakharuk 2154: #-- single document - problem, page, html, xml, ...
1.343 albertel 2155: my ($currentURL,$cleanURL);
1.375 foxr 2156:
1.162 sakharuk 2157: if ($helper->{'VARS'}->{'construction'} ne '1') {
1.185 sakharuk 2158: #prints published resource
1.153 sakharuk 2159: $currentURL=$helper->{'VARS'}->{'postdata'};
1.343 albertel 2160: $cleanURL=&Apache::lonenc::check_decrypt($currentURL);
1.143 sakharuk 2161: } else {
1.512 foxr 2162:
1.185 sakharuk 2163: #prints resource from the construction space
1.240 albertel 2164: $currentURL='/'.$helper->{'VARS'}->{'filename'};
1.206 sakharuk 2165: if ($currentURL=~/([^?]+)/) {$currentURL=$1;}
1.343 albertel 2166: $cleanURL=$currentURL;
1.143 sakharuk 2167: }
1.140 sakharuk 2168: $selectionmade = 1;
1.413 albertel 2169: if ($cleanURL!~m|^/adm/|
1.557 foxr 2170: && $cleanURL=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) {
1.169 albertel 2171: my $rndseed=time;
1.242 sakharuk 2172: my $texversion='';
2173: if ($helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only') {
2174: my %moreenv;
1.343 albertel 2175: $moreenv{'request.filename'}=$cleanURL;
1.290 sakharuk 2176: if ($helper->{'VARS'}->{'probstatus'} eq 'exam') {$form{'problemtype'}='exam';}
1.242 sakharuk 2177: $form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.310 sakharuk 2178: $form{'suppress_tries'}=$parmhash{'suppress_tries'};
1.242 sakharuk 2179: $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.309 sakharuk 2180: $form{'print_discussions'}=$helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
1.511 foxr 2181: $form{'print_annotations'}=$helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
2182: if (($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes') ||
2183: ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes')) {
2184: $form{'problem_split'}='yes';
2185: }
1.242 sakharuk 2186: if ($helper->{'VARS'}->{'curseed'}) {
2187: $rndseed=$helper->{'VARS'}->{'curseed'};
2188: }
2189: $form{'rndseed'}=$rndseed;
1.520 raeburn 2190: &Apache::lonnet::appenv(\%moreenv);
1.428 albertel 2191:
2192: &Apache::lonxml::clear_problem_counter();
2193:
1.375 foxr 2194: $resources_printed .= $currentURL.':';
1.515 foxr 2195: $texversion.=&ssi_with_retries($currentURL,$ssi_retry_count, %form);
1.428 albertel 2196:
1.511 foxr 2197: # Add annotations if required:
2198:
1.428 albertel 2199: &Apache::lonxml::clear_problem_counter();
2200:
1.242 sakharuk 2201: &Apache::lonnet::delenv('request.filename');
1.230 albertel 2202: }
1.423 foxr 2203: # current document with answers.. no need to encap in minipage
2204: # since there's only one answer.
2205:
1.242 sakharuk 2206: if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
2207: ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.353 foxr 2208: $form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.166 albertel 2209: $form{'grade_target'}='answer';
1.167 albertel 2210: $form{'answer_output_mode'}='tex';
1.169 albertel 2211: $form{'rndseed'}=$rndseed;
1.401 albertel 2212: if ($helper->{'VARS'}->{'probstatus'} eq 'exam') {
2213: $form{'problemtype'}='exam';
2214: }
1.375 foxr 2215: $resources_printed .= $currentURL.':';
1.515 foxr 2216: my $answer=&ssi_with_retries($currentURL,$ssi_retry_count, %form);
1.511 foxr 2217:
2218:
1.242 sakharuk 2219: if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
2220: $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
2221: } else {
2222: $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.245 sakharuk 2223: if ($helper->{'VARS'}->{'construction'} ne '1') {
1.477 albertel 2224: my $title = &Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'});
2225: $title = &Apache::lonxml::latex_special_symbols($title);
2226: $texversion.='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
1.343 albertel 2227: $texversion.=&path_to_problem($cleanURL,$LaTeXwidth);
1.245 sakharuk 2228: } else {
2229: $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
1.343 albertel 2230: my $URLpath=$cleanURL;
1.245 sakharuk 2231: $URLpath=~s/~([^\/]+)/public_html\/$1\/$1/;
1.504 albertel 2232: $texversion.=&path_to_problem($URLpath,$LaTeXwidth);
1.245 sakharuk 2233: }
1.242 sakharuk 2234: $texversion.='\vskip 1 mm '.$answer.'\end{document}';
2235: }
1.511 foxr 2236:
2237:
2238:
2239:
1.550 foxr 2240:
1.511 foxr 2241: }
2242: # Print annotations.
2243:
2244:
2245: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
2246: my $annotation .= &annotate($currentURL);
2247: $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
1.163 sakharuk 2248: }
1.511 foxr 2249:
2250:
1.214 sakharuk 2251: if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
1.215 sakharuk 2252: $texversion=&IndexCreation($texversion,$currentURL);
1.214 sakharuk 2253: }
1.219 sakharuk 2254: if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') {
2255: $texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$currentURL| \\strut\\\\\\strut /;
2256:
2257: }
1.162 sakharuk 2258: $result .= $texversion;
2259: if ($currentURL=~m/\.page\s*$/) {
2260: ($result,$number_of_columns) = &page_cleanup($result);
2261: }
1.413 albertel 2262: } elsif ($cleanURL!~m|^/adm/|
1.557 foxr 2263: && $currentURL=~/\.(sequence|page)$/ && $helper->{'VARS'}->{'construction'} eq '1') {
1.227 sakharuk 2264: #printing content of sequence from the construction space
1.559 foxr 2265:
2266:
1.227 sakharuk 2267: $currentURL=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;
1.459 foxr 2268: $result .= &print_construction_sequence($currentURL, $helper, %form,
2269: $LaTeXwidth);
2270: $result .= '\end{document}';
2271: if (!($result =~ /\\begin\{document\}/)) {
2272: $result = &print_latex_header() . $result;
1.227 sakharuk 2273: }
1.459 foxr 2274: # End construction space sequence.
1.456 raeburn 2275: } elsif ($cleanURL=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) {
1.258 sakharuk 2276: $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.298 sakharuk 2277: if ($currentURL=~/\/syllabus$/) {$currentURL=~s/\/res//;}
1.375 foxr 2278: $resources_printed .= $currentURL.':';
1.567 foxr 2279: my $texversion = &ssi_with_retries($currentURL, $ssi_retry_count, %form);
1.511 foxr 2280: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
2281: my $annotation = &annotate($currentURL);
2282: $texversion =~ s/(\\end{document})/$annotation$1/;
2283: }
1.258 sakharuk 2284: $result .= $texversion;
1.550 foxr 2285: } elsif ($cleanURL =~/\.tex$/) {
1.498 foxr 2286: # For this sort of print of a single LaTeX file,
2287: # We can just print the LaTeX file as it is uninterpreted in any way:
2288: #
2289:
2290: $result = &fetch_raw_resource($currentURL);
1.511 foxr 2291: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
2292: my $annotation = &annotate($currentURL);
2293: $result =~ s/(\\end{document})/$annotation$1/;
2294: }
2295:
1.499 foxr 2296: $do_postprocessing = 0; # Don't massage the result.
1.498 foxr 2297:
1.550 foxr 2298: } elsif ($cleanURL =~ /\.pdf$/i) {
2299: $result .= &include_pdf($cleanURL);
1.551 foxr 2300: $result .= '\end{document}';
1.559 foxr 2301: } elsif ($cleanURL =~ /\.page$/i) { # Print page in non construction space contexts.
2302:
2303: # Determine the set of resources in the map of the page:
2304:
2305: my $navmap = Apache::lonnavmaps::navmap->new();
2306: my @page_resources = $navmap->retrieveResources($cleanURL);
2307: $result .= &print_page_in_course($helper, $rparmhash,
2308: $cleanURL, \@page_resources);
2309:
2310:
1.162 sakharuk 2311: } else {
1.414 albertel 2312: $result.=&unsupported($currentURL,$helper->{'VARS'}->{'LATEX_TYPE'},
2313: $helper->{'VARS'}->{'symb'});
1.162 sakharuk 2314: }
1.354 foxr 2315: } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems') or
1.562 foxr 2316: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_in_page') or
2317: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_resources_in_page') or
1.142 sakharuk 2318: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_pages') or
1.354 foxr 2319: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems') or
2320: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_resources') or # BUGBUG
1.536 foxr 2321: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences')
1.582 raeburn 2322: ) {
1.511 foxr 2323:
1.582 raeburn 2324:
1.141 sakharuk 2325: #-- produce an output string
1.562 foxr 2326: if (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems') or
2327: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_in_page') ) {
1.296 sakharuk 2328: $selectionmade = 2;
1.562 foxr 2329: } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_pages') or
2330: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_resources_in_page'))
2331: {
1.296 sakharuk 2332: $selectionmade = 3;
1.536 foxr 2333: } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems')
2334: ) {
1.296 sakharuk 2335: $selectionmade = 4;
1.354 foxr 2336: } elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_resources') { #BUGBUG
2337: $selectionmade = 4;
1.296 sakharuk 2338: } elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences') {
2339: $selectionmade = 7;
2340: }
1.193 sakharuk 2341: $form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.310 sakharuk 2342: $form{'suppress_tries'}=$parmhash{'suppress_tries'};
1.203 sakharuk 2343: $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.309 sakharuk 2344: $form{'print_discussions'}=$helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
1.511 foxr 2345: $form{'print_annotations'} = $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
2346: if (($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes') ||
2347: ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') ) {
2348: $form{'problem_split'}='yes';
2349: }
1.141 sakharuk 2350: my $flag_latex_header_remove = 'NO';
2351: my $flag_page_in_sequence = 'NO';
2352: my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
1.193 sakharuk 2353: my $prevassignment='';
1.428 albertel 2354:
2355: &Apache::lonxml::clear_problem_counter();
2356:
1.416 foxr 2357: my $pbreakresources = keys %page_breaks;
1.141 sakharuk 2358: for (my $i=0;$i<=$#master_seq;$i++) {
1.350 foxr 2359:
1.521 foxr 2360: &Apache::lonenc::reset_enc();
2361:
2362:
1.350 foxr 2363: # Note due to document structure, not allowed to put \newpage
2364: # prior to the first resource
2365:
1.351 foxr 2366: if (defined $page_breaks{$master_seq[$i]}) {
1.350 foxr 2367: if($i != 0) {
2368: $result.="\\newpage\n";
2369: }
2370: }
1.569 foxr 2371: $result .= &get_extra_vspaces($helper, $master_seq[$i]);
1.564 foxr 2372: my ($sequence,$middle_thingy,$urlp)=&Apache::lonnet::decode_symb($master_seq[$i]);
1.237 albertel 2373: $urlp=&Apache::lonnet::clutter($urlp);
1.166 albertel 2374: $form{'symb'}=$master_seq[$i];
1.407 albertel 2375:
2376: my $assignment=&Apache::lonxml::latex_special_symbols(&Apache::lonnet::gettitle($sequence),'header'); #title of the assignment which contains this problem
1.521 foxr 2377:
1.267 sakharuk 2378: if ($selectionmade==7) {$helper->{VARS}->{'assignment'}=$assignment;}
1.247 sakharuk 2379: if ($i==0) {$prevassignment=$assignment;}
1.297 sakharuk 2380: my $texversion='';
1.413 albertel 2381: if ($urlp!~m|^/adm/|
2382: && $urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
1.375 foxr 2383: $resources_printed .= $urlp.':';
1.428 albertel 2384: &Apache::lonxml::remember_problem_counter();
1.566 foxr 2385: if ($flag_latex_header_remove eq 'NO') {
2386: $texversion.=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); # RF
1.582 raeburn 2387: unless (($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only') ||
2388: (($i==0) &&
2389: (($urlp=~/\.page$/) ||
2390: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_in_page') ||
2391: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_resources_in_page')))) {
2392: $flag_latex_header_remove = 'YES';
2393: }
1.566 foxr 2394: }
1.515 foxr 2395: $texversion.=&ssi_with_retries($urlp, $ssi_retry_count, %form);
1.296 sakharuk 2396: if ($urlp=~/\.page$/) {
2397: ($texversion,my $number_of_columns_page) = &page_cleanup($texversion);
2398: if ($number_of_columns_page > $number_of_columns) {$number_of_columns=$number_of_columns_page;}
2399: $texversion =~ s/\\end{document}\d*/\\end{document}/;
2400: $flag_page_in_sequence = 'YES';
1.582 raeburn 2401: }
1.428 albertel 2402:
1.296 sakharuk 2403: if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
2404: ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.380 foxr 2405: # Don't permanently pervert the %form hash
2406: my %answerform = %form;
2407: $answerform{'grade_target'}='answer';
2408: $answerform{'answer_output_mode'}='tex';
1.375 foxr 2409: $resources_printed .= $urlp.':';
1.428 albertel 2410:
2411: &Apache::lonxml::restore_problem_counter();
1.515 foxr 2412: my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
1.582 raeburn 2413: if ($urlp =~ /\.page$/) {
2414: $answer =~ s/\\end{document}(\d*)$//;
2415: }
1.296 sakharuk 2416: if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
1.582 raeburn 2417: if ($urlp =~ /\.page$/) {
2418: my @probs = split(/\\keephidden{ENDOFPROBLEM}/,$texversion);
2419: my $lastprob = pop(@probs);
2420: $texversion = join('\keephidden{ENDOFPROBLEM}',@probs).
2421: $answer.'\keephidden{ENDOFPROBLEM}'.$lastprob;
2422: } else {
2423: $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
2424: }
1.249 sakharuk 2425: } else {
1.582 raeburn 2426: if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page)$/) {
1.296 sakharuk 2427: $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.582 raeburn 2428: # $texversion =~ s/\\begin{document}//; # FIXME
1.477 albertel 2429: my $title = &Apache::lonnet::gettitle($master_seq[$i]);
2430: $title = &Apache::lonxml::latex_special_symbols($title);
2431: my $body ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
1.423 foxr 2432: $body .= &path_to_problem ($urlp,$LaTeXwidth);
2433: $body .='\vskip 1 mm '.$answer;
2434: $body = &encapsulate_minipage($body);
2435: $texversion .= $body;
1.296 sakharuk 2436: } else {
2437: $texversion='';
2438: }
1.249 sakharuk 2439: }
1.511 foxr 2440:
1.246 sakharuk 2441: }
1.511 foxr 2442: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
2443: my $annotation .= &annotate($urlp);
2444: $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
2445: }
2446:
1.296 sakharuk 2447: if ($flag_latex_header_remove ne 'NO') {
2448: $texversion = &latex_header_footer_remove($texversion);
2449: } else {
2450: $texversion =~ s/\\end{document}//;
2451: }
2452: if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
2453: $texversion=&IndexCreation($texversion,$urlp);
2454: }
2455: if (($selectionmade == 4) and ($assignment ne $prevassignment)) {
2456: my $name = &get_name();
2457: my $courseidinfo = &get_course();
1.583.2.1 raeburn 2458: if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo }
1.296 sakharuk 2459: $prevassignment=$assignment;
1.455 albertel 2460: my $header_text = $parmhash{'print_header_format'};
1.486 foxr 2461: $header_text = &format_page_header($textwidth, $header_text,
1.455 albertel 2462: $assignment,
2463: $courseidinfo,
2464: $name);
1.552 foxr 2465:
1.417 foxr 2466: if ($numberofcolumns eq '1') {
1.455 albertel 2467: $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{'.$header_text.'}} \vskip 5 mm ';
1.416 foxr 2468: } else {
1.455 albertel 2469: $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{'.$header_text.'}} \vskip 5 mm ';
1.416 foxr 2470: }
1.296 sakharuk 2471: }
2472: $result .= $texversion;
2473: $flag_latex_header_remove = 'YES';
1.456 raeburn 2474: } elsif ($urlp=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) {
1.301 sakharuk 2475: $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
2476: if ($urlp=~/\/syllabus$/) {$urlp=~s/\/res//;}
1.375 foxr 2477: $resources_printed .= $urlp.':';
1.567 foxr 2478: my $texversion = &ssi_with_retries($urlp, $ssi_retry_count, %form);
1.511 foxr 2479: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
2480: my $annotation = &annotate($urlp);
2481: $texversion =~ s/(\\end{document)/$annotation$1/;
2482: }
2483:
1.301 sakharuk 2484: if ($flag_latex_header_remove ne 'NO') {
2485: $texversion = &latex_header_footer_remove($texversion);
1.550 foxr 2486: } else {
1.301 sakharuk 2487: $texversion =~ s/\\end{document}/\\vskip 0\.5mm\\noindent\\makebox\[\\textwidth\/\$number_of_columns\]\[b\]\{\\hrulefill\}/;
2488: }
2489: $result .= $texversion;
2490: $flag_latex_header_remove = 'YES';
1.550 foxr 2491: } elsif ($urlp=~ /\.pdf$/i) {
2492: if ($i > 0) {
2493: $result .= '\cleardoublepage';
2494: }
1.580 raeburn 2495: my $texfrompdf = &include_pdf($urlp);
2496: if ($flag_latex_header_remove ne 'NO') {
2497: $texfrompdf = &latex_header_footer_remove($texfrompdf);
2498: }
2499: $result .= $texfrompdf;
1.550 foxr 2500: if ($i != $#master_seq) {
2501: if ($numberofcolumns eq '1') {
2502: $result .= '\newpage';
2503: } else {
2504: # the \\'s seem to be needed to let LaTeX know there's something
2505: # on the page since LaTeX seems to not like to clear an empty page.
2506: #
2507: $result .= '\\ \cleardoublepage';
2508: }
2509: }
2510: $flag_latex_header_remove = 'YES';
2511:
1.141 sakharuk 2512: } else {
1.414 albertel 2513: $texversion=&unsupported($urlp,$helper->{'VARS'}->{'LATEX_TYPE'},
2514: $master_seq[$i]);
1.297 sakharuk 2515: if ($flag_latex_header_remove ne 'NO') {
2516: $texversion = &latex_header_footer_remove($texversion);
2517: } else {
2518: $texversion =~ s/\\end{document}//;
2519: }
2520: $result .= $texversion;
2521: $flag_latex_header_remove = 'YES';
1.582 raeburn 2522: }
1.550 foxr 2523: if (&Apache::loncommon::connection_aborted($r)) {
2524: last;
2525: }
1.141 sakharuk 2526: }
1.428 albertel 2527: &Apache::lonxml::clear_problem_counter();
1.344 foxr 2528: if ($flag_page_in_sequence eq 'YES') {
2529: $result =~ s/\\usepackage{calc}/\\usepackage{calc}\\usepackage{longtable}/;
2530: }
1.141 sakharuk 2531: $result .= '\end{document}';
1.284 albertel 2532: } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students') ||
1.562 foxr 2533: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students_from_page') ||
1.536 foxr 2534: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems_students') ||
1.284 albertel 2535: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_students')){
1.353 foxr 2536:
2537:
1.150 sakharuk 2538: #-- prints assignments for whole class or for selected students
1.284 albertel 2539: my $type;
1.536 foxr 2540: if (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students') ||
1.562 foxr 2541: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students_from_page') ||
1.536 foxr 2542: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems_students') ) {
1.254 sakharuk 2543: $selectionmade=5;
1.284 albertel 2544: $type='problems';
1.254 sakharuk 2545: } elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_students') {
2546: $selectionmade=8;
1.284 albertel 2547: $type='resources';
1.254 sakharuk 2548: }
1.150 sakharuk 2549: my @students=split /\|\|\|/, $helper->{'VARS'}->{'STUDENTS'};
1.341 foxr 2550: # The normal sort order is by section then by students within the
2551: # section. If the helper var student_sort is 1, then the user has elected
2552: # to override this and output the students by name.
2553: # Each element of the students array is of the form:
2554: # username:domain:section:last, first:status
2555: #
1.429 foxr 2556: # Note that student sort is not compatible with printing
2557: # 1 section per pdf...so that setting overrides.
1.341 foxr 2558: #
1.429 foxr 2559: if (($helper->{'VARS'}->{'student_sort'} eq 1) &&
2560: ($helper->{'VARS'}->{'SPLIT_PDFS'} ne "sections")) {
1.341 foxr 2561: @students = sort compare_names @students;
2562: }
1.429 foxr 2563: &adjust_number_to_print($helper);
2564:
1.278 albertel 2565: if ($helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq '0' ||
2566: $helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'all' ) {
2567: $helper->{'VARS'}->{'NUMBER_TO_PRINT'}=$#students+1;
2568: }
1.429 foxr 2569: # If we are splitting on section boundaries, we need
2570: # to remember that in split_on_sections and
2571: # print all of the students in the list.
2572: #
2573: my $split_on_sections = 0;
2574: if ($helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'section') {
2575: $split_on_sections = 1;
2576: $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = $#students+1;
2577: }
1.150 sakharuk 2578: my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
1.350 foxr 2579:
1.150 sakharuk 2580: #loop over students
1.562 foxr 2581:
2582: my $flag_latex_header_remove = 'NO';
1.150 sakharuk 2583: my %moreenv;
1.330 sakharuk 2584: $moreenv{'instructor_comments'}='hide';
1.285 albertel 2585: $moreenv{'textwidth'}=&get_textwidth($helper,$LaTeXwidth);
1.309 sakharuk 2586: $moreenv{'print_discussions'}=$helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
1.511 foxr 2587: $moreenv{'print_annotations'} = $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
1.353 foxr 2588: $moreenv{'problem_split'} = $parmhash{'problem_stream_switch'};
1.369 foxr 2589: $moreenv{'suppress_tries'} = $parmhash{'suppress_tries'};
1.511 foxr 2590: if (($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes') ||
2591: ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes')) {
2592: $moreenv{'problem_split'}='yes';
2593: }
1.318 albertel 2594: my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Print Status','Class Print Status',$#students+1,'inline','75');
1.272 sakharuk 2595: my $student_counter=-1;
1.429 foxr 2596: my $i = 0;
1.430 albertel 2597: my $last_section = (split(/:/,$students[0]))[2];
1.150 sakharuk 2598: foreach my $person (@students) {
1.350 foxr 2599:
1.373 albertel 2600: my $duefile="/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due";
1.311 sakharuk 2601: if (-e $duefile) {
2602: my $temp_file = Apache::File->new('>>'.$duefile);
2603: print $temp_file "1969\n";
2604: }
1.272 sakharuk 2605: $student_counter++;
1.429 foxr 2606: if ($split_on_sections) {
1.430 albertel 2607: my $this_section = (split(/:/,$person))[2];
1.429 foxr 2608: if ($this_section ne $last_section) {
2609: $i++;
2610: $last_section = $this_section;
2611: }
2612: } else {
2613: $i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'});
2614: }
1.375 foxr 2615: my ($output,$fullname, $printed)=&print_resources($r,$helper,
1.353 foxr 2616: $person,$type,
2617: \%moreenv,\@master_seq,
1.360 albertel 2618: $flag_latex_header_remove,
1.422 albertel 2619: $LaTeXwidth);
1.375 foxr 2620: $resources_printed .= ":";
1.284 albertel 2621: $print_array[$i].=$output;
2622: $student_names[$i].=$person.':'.$fullname.'_END_';
1.581 bisitz 2623: # &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,&mt('last student').' '.$fullname);
2624: &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
1.284 albertel 2625: $flag_latex_header_remove = 'YES';
1.331 albertel 2626: if (&Apache::loncommon::connection_aborted($r)) { last; }
1.284 albertel 2627: }
2628: &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
2629: $result .= $print_array[0].' \end{document}';
2630: } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon') ||
1.562 foxr 2631: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon_page') ||
1.284 albertel 2632: ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon') ) {
1.373 albertel 2633: my $cdom =$env{'course.'.$env{'request.course.id'}.'.domain'};
2634: my $cnum =$env{'course.'.$env{'request.course.id'}.'.num'};
1.288 albertel 2635: my $num_todo=$helper->{'VARS'}->{'NUMBER_TO_PRINT_TOTAL'};
2636: my $code_name=$helper->{'VARS'}->{'ANON_CODE_STORAGE_NAME'};
1.292 albertel 2637: my $old_name=$helper->{'VARS'}->{'REUSE_OLD_CODES'};
1.385 foxr 2638: my $single_code = $helper->{'VARS'}->{'SINGLE_CODE'};
1.388 foxr 2639: my $selected_code = $helper->{'VARS'}->{'CODE_SELECTED_FROM_LIST'};
2640:
1.381 albertel 2641: my $code_option=$helper->{'VARS'}->{'CODE_OPTION'};
1.542 raeburn 2642: my @lines = &Apache::grades::get_scantronformat_file();
1.381 albertel 2643: my ($code_type,$code_length)=('letter',6);
1.542 raeburn 2644: foreach my $line (@lines) {
1.381 albertel 2645: my ($name,$type,$length) = (split(/:/,$line))[0,2,4];
2646: if ($name eq $code_option) {
2647: $code_length=$length;
2648: if ($type eq 'number') { $code_type = 'number'; }
2649: }
2650: }
1.288 albertel 2651: my %moreenv = ('textwidth' => &get_textwidth($helper,$LaTeXwidth));
1.353 foxr 2652: $moreenv{'problem_split'} = $parmhash{'problem_stream_switch'};
1.420 albertel 2653: $moreenv{'instructor_comments'}='hide';
1.288 albertel 2654: my $seed=time+($$<<16)+($$);
1.292 albertel 2655: my @allcodes;
2656: if ($old_name) {
1.381 albertel 2657: my %result=&Apache::lonnet::get('CODEs',
2658: [$old_name,"type\0$old_name"],
2659: $cdom,$cnum);
2660: $code_type=$result{"type\0$old_name"};
1.292 albertel 2661: @allcodes=split(',',$result{$old_name});
1.336 albertel 2662: $num_todo=scalar(@allcodes);
1.389 foxr 2663: } elsif ($selected_code) { # Selection value is always numeric.
1.388 foxr 2664: $num_todo = 1;
2665: @allcodes = ($selected_code);
1.385 foxr 2666: } elsif ($single_code) {
2667:
1.387 foxr 2668: $num_todo = 1; # Unconditionally one code to do.
1.385 foxr 2669: # If an alpha code have to convert to numbers so it can be
2670: # converted back to letters again :-)
2671: #
2672: if ($code_type ne 'number') {
2673: $single_code = &letters_to_num($single_code);
2674: }
2675: @allcodes = ($single_code);
1.292 albertel 2676: } else {
2677: my %allcodes;
1.299 albertel 2678: srand($seed);
1.292 albertel 2679: for (my $i=0;$i<$num_todo;$i++) {
1.381 albertel 2680: $moreenv{'CODE'}=&get_CODE(\%allcodes,$i,$seed,$code_length,
2681: $code_type);
1.292 albertel 2682: }
2683: if ($code_name) {
2684: &Apache::lonnet::put('CODEs',
1.381 albertel 2685: {
2686: $code_name =>join(',',keys(%allcodes)),
2687: "type\0$code_name" => $code_type
2688: },
1.292 albertel 2689: $cdom,$cnum);
2690: }
2691: @allcodes=keys(%allcodes);
2692: }
1.336 albertel 2693: my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
2694: my ($type) = split(/_/,$helper->{'VARS'}->{'PRINT_TYPE'});
1.452 albertel 2695: &adjust_number_to_print($helper);
1.336 albertel 2696: my $number_per_page=$helper->{'VARS'}->{'NUMBER_TO_PRINT'};
1.583.2.5 raeburn 2697: if ($number_per_page eq '0' || $number_per_page eq 'all'
2698: || $number_per_page eq 'section') {
1.336 albertel 2699: $number_per_page=$num_todo;
2700: }
2701: my $flag_latex_header_remove = 'NO';
2702: my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Print Status','Class Print Status',$num_todo,'inline','75');
1.295 albertel 2703: my $count=0;
1.292 albertel 2704: foreach my $code (sort(@allcodes)) {
1.295 albertel 2705: my $file_num=int($count/$number_per_page);
1.381 albertel 2706: if ($code_type eq 'number') {
2707: $moreenv{'CODE'}=$code;
2708: } else {
2709: $moreenv{'CODE'}=&num_to_letters($code);
2710: }
1.375 foxr 2711: my ($output,$fullname, $printed)=
1.288 albertel 2712: &print_resources($r,$helper,'anonymous',$type,\%moreenv,
1.360 albertel 2713: \@master_seq,$flag_latex_header_remove,
2714: $LaTeXwidth);
1.375 foxr 2715: $resources_printed .= ":";
1.295 albertel 2716: $print_array[$file_num].=$output;
1.288 albertel 2717: &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
2718: &mt('last assignment').' '.$fullname);
2719: $flag_latex_header_remove = 'YES';
1.295 albertel 2720: $count++;
1.331 albertel 2721: if (&Apache::loncommon::connection_aborted($r)) { last; }
1.288 albertel 2722: }
2723: &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
2724: $result .= $print_array[0].' \end{document}';
2725: } elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_from_directory') {
1.151 sakharuk 2726: #prints selected problems from the subdirectory
2727: $selectionmade = 6;
2728: my @list_of_files=split /\|\|\|/, $helper->{'VARS'}->{'FILES'};
1.154 sakharuk 2729: @list_of_files=sort @list_of_files;
1.175 sakharuk 2730: my $flag_latex_header_remove = 'NO';
2731: my $rndseed=time;
1.230 albertel 2732: if ($helper->{'VARS'}->{'curseed'}) {
2733: $rndseed=$helper->{'VARS'}->{'curseed'};
2734: }
1.151 sakharuk 2735: for (my $i=0;$i<=$#list_of_files;$i++) {
1.521 foxr 2736:
2737: &Apache::lonenc::reset_enc();
2738:
1.152 sakharuk 2739: my $urlp = $list_of_files[$i];
1.253 sakharuk 2740: $urlp=~s|//|/|;
1.152 sakharuk 2741: if ($urlp=~/\//) {
1.353 foxr 2742: $form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.175 sakharuk 2743: $form{'rndseed'}=$rndseed;
1.152 sakharuk 2744: if ($urlp =~ m|/home/([^/]+)/public_html|) {
2745: $urlp =~ s|/home/([^/]*)/public_html|/~$1|;
2746: } else {
1.302 sakharuk 2747: $urlp =~ s|^$Apache::lonnet::perlvar{'lonDocRoot'}||;
1.152 sakharuk 2748: }
1.375 foxr 2749: $resources_printed .= $urlp.':';
1.515 foxr 2750: my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
1.251 sakharuk 2751: if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
1.253 sakharuk 2752: ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.380 foxr 2753: # Don't permanently pervert %form:
2754: my %answerform = %form;
2755: $answerform{'grade_target'}='answer';
2756: $answerform{'answer_output_mode'}='tex';
2757: $answerform{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
2758: $answerform{'rndseed'}=$rndseed;
1.375 foxr 2759: $resources_printed .= $urlp.':';
1.515 foxr 2760: my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
1.251 sakharuk 2761: if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
2762: $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
2763: } else {
1.253 sakharuk 2764: $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
2765: if ($helper->{'VARS'}->{'construction'} ne '1') {
2766: $texversion.='\vskip 0 mm \noindent ';
2767: $texversion.=&path_to_problem ($urlp,$LaTeXwidth);
2768: } else {
2769: $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
2770: my $URLpath=$urlp;
2771: $URLpath=~s/~([^\/]+)/public_html\/$1\/$1/;
2772: $texversion.=&path_to_problem ($URLpath,$LaTeXwidth);
2773: }
2774: $texversion.='\vskip 1 mm '.$answer.'\end{document}';
1.251 sakharuk 2775: }
1.174 sakharuk 2776: }
1.515 foxr 2777: #this chunk is responsible for printing the path to problem
2778:
1.253 sakharuk 2779: my $newurlp=$urlp;
2780: if ($newurlp=~/~/) {$newurlp=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;}
2781: $newurlp=&path_to_problem($newurlp,$LaTeXwidth);
1.242 sakharuk 2782: $texversion =~ s/(\\begin{minipage}{\\textwidth})/$1 $newurlp/;
1.152 sakharuk 2783: if ($flag_latex_header_remove ne 'NO') {
2784: $texversion = &latex_header_footer_remove($texversion);
2785: } else {
2786: $texversion =~ s/\\end{document}//;
1.216 sakharuk 2787: }
2788: if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
2789: $texversion=&IndexCreation($texversion,$urlp);
1.152 sakharuk 2790: }
1.219 sakharuk 2791: if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') {
2792: $texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /;
2793:
2794: }
1.152 sakharuk 2795: $result .= $texversion;
2796: }
2797: $flag_latex_header_remove = 'YES';
1.151 sakharuk 2798: }
1.175 sakharuk 2799: if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\typeout)/ RANDOM SEED IS $rndseed $1/;}
1.152 sakharuk 2800: $result .= '\end{document}';
1.140 sakharuk 2801: }
2802: #-------------------------------------------------------- corrections for the different page formats
1.499 foxr 2803:
2804: # Only post process if that has not been turned off e.g. by a raw latex resource.
2805:
2806: if ($do_postprocessing) {
2807: $result = &page_format_transformation($papersize,$laystyle,$numberofcolumns,$helper->{'VARS'}->{'PRINT_TYPE'},$result,$helper->{VARS}->{'assignment'},$helper->{'VARS'}->{'TABLE_CONTENTS'},$helper->{'VARS'}->{'TABLE_INDEX'},$selectionmade);
2808: $result = &latex_corrections($number_of_columns,$result,$selectionmade,
2809: $helper->{'VARS'}->{'ANSWER_TYPE'});
2810: #if ($numberofcolumns == 1) {
1.451 albertel 2811: $result =~ s/\\textwidth\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textwidth= $helper->{'VARS'}->{'pagesize.width'} $helper->{'VARS'}->{'pagesize.widthunit'} /;
2812: $result =~ s/\\textheight\s*=?\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textheight $helper->{'VARS'}->{'pagesize.height'} $helper->{'VARS'}->{'pagesize.heightunit'} /;
2813: $result =~ s/\\evensidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\evensidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /;
2814: $result =~ s/\\oddsidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\oddsidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /;
1.499 foxr 2815: #}
2816: }
1.367 foxr 2817:
1.515 foxr 2818: # Set URLback if this is a construction space print so we can provide
2819: # a link to the resource being edited.
2820: #
1.274 sakharuk 2821:
1.276 sakharuk 2822: my $URLback=''; #link to original document
1.510 albertel 2823: if ($helper->{'VARS'}->{'construction'} eq '1') {
1.276 sakharuk 2824: #prints resource from the construction space
2825: $URLback='/'.$helper->{'VARS'}->{'filename'};
1.279 albertel 2826: if ($URLback=~/([^?]+)/) {
2827: $URLback=$1;
2828: $URLback=~s|^/~|/priv/|;
2829: }
1.276 sakharuk 2830: }
1.556 foxr 2831: #
2832: # Final adjustment of the font size:
2833: #
2834:
2835: $result = set_font_size($result);
1.375 foxr 2836:
1.525 www 2837: #-- writing .tex file in prtspool
2838: my $temp_file;
2839: my $identifier = &Apache::loncommon::get_cgi_id();
2840: my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout_$identifier.tex";
2841: if (!($#print_array>0)) {
2842: unless ($temp_file = Apache::File->new('>'.$filename)) {
2843: $r->log_error("Couldn't open $filename for output $!");
2844: return SERVER_ERROR;
2845: }
2846: print $temp_file $result;
2847: my $begin=index($result,'\begin{document}',0);
2848: my $inc=substr($result,0,$begin+16);
1.515 foxr 2849: } else {
1.525 www 2850: my $begin=index($result,'\begin{document}',0);
2851: my $inc=substr($result,0,$begin+16);
2852: for (my $i=0;$i<=$#print_array;$i++) {
2853: if ($i==0) {
2854: $print_array[$i]=$result;
2855: } else {
2856: $print_array[$i].='\end{document}';
2857: $print_array[$i] =
2858: &latex_corrections($number_of_columns,$print_array[$i],
2859: $selectionmade,
2860: $helper->{'VARS'}->{'ANSWER_TYPE'});
1.515 foxr 2861:
1.525 www 2862: my $anobegin=index($print_array[$i],'\setcounter{page}',0);
2863: substr($print_array[$i],0,$anobegin)='';
2864: $print_array[$i]=$inc.$print_array[$i];
2865: }
2866: my $temp_file;
2867: my $newfilename=$filename;
2868: my $num=$i+1;
2869: $newfilename =~s/\.tex$//;
2870: $newfilename=sprintf("%s_%03d.tex",$newfilename, $num);
2871: unless ($temp_file = Apache::File->new('>'.$newfilename)) {
2872: $r->log_error("Couldn't open $newfilename for output $!");
2873: return SERVER_ERROR;
2874: }
2875: print $temp_file $print_array[$i];
2876: }
2877: }
2878: my $student_names='';
2879: if ($#print_array>0) {
2880: for (my $i=0;$i<=$#print_array;$i++) {
2881: $student_names.=$student_names[$i].'_ENDPERSON_';
1.515 foxr 2882: }
1.525 www 2883: } else {
2884: if ($#student_names>-1) {
2885: $student_names=$student_names[0].'_ENDPERSON_';
1.515 foxr 2886: } else {
1.525 www 2887: my $fullname = &get_name($env{'user.name'},$env{'user.domain'});
2888: $student_names=join(':',$env{'user.name'},$env{'user.domain'},
1.515 foxr 2889: $env{'request.course.sec'},$fullname).
2890: '_ENDPERSON_'.'_END_';
2891: }
1.525 www 2892: }
1.515 foxr 2893:
1.525 www 2894: # logic for now is too complex to trace if this has been defined
2895: # yet.
2896: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
2897: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
2898: &Apache::lonnet::appenv({'cgi.'.$identifier.'.file' => $filename,
1.515 foxr 2899: 'cgi.'.$identifier.'.layout' => $laystyle,
2900: 'cgi.'.$identifier.'.numcol' => $numberofcolumns,
2901: 'cgi.'.$identifier.'.paper' => $papersize,
2902: 'cgi.'.$identifier.'.selection' => $selectionmade,
2903: 'cgi.'.$identifier.'.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'},
2904: 'cgi.'.$identifier.'.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'},
2905: 'cgi.'.$identifier.'.role' => $perm{'pav'},
2906: 'cgi.'.$identifier.'.numberoffiles' => $#print_array,
2907: 'cgi.'.$identifier.'.studentnames' => $student_names,
1.520 raeburn 2908: 'cgi.'.$identifier.'.backref' => $URLback,});
1.525 www 2909: &Apache::lonnet::appenv({"cgi.$identifier.user" => $env{'user.name'},
1.515 foxr 2910: "cgi.$identifier.domain" => $env{'user.domain'},
2911: "cgi.$identifier.courseid" => $cnum,
2912: "cgi.$identifier.coursedom" => $cdom,
1.520 raeburn 2913: "cgi.$identifier.resources" => $resources_printed});
1.515 foxr 2914:
1.525 www 2915: my $end_page = &Apache::loncommon::end_page();
1.529 raeburn 2916: my $continue_text = &mt('Continue');
1.525 www 2917: # If there's been an unrecoverable SSI error, report it to the user
2918: if ($ssi_error) {
2919: my $helpurl = &Apache::loncommon::top_nav_help('Helpdesk');
1.554 bisitz 2920: $r->print('<br /><p class="LC_error">'.&mt('An unrecoverable network error occurred:').'</p><p>'.
1.526 www 2921: &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:').
2922: '<br />'.$ssi_last_error_resource.'<br />'.$ssi_last_error.
2923: '</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 2924: &mt('You may be able to reprint the individual resources for which this error occurred, as the issue may be temporary.').
1.525 www 2925: '<br />'.&mt('If the error persists, please contact the [_1] for assistance.',$helpurl).'</p><p>'.
2926: &mt('We apologize for the inconvenience.').'</p>'.
1.528 raeburn 2927: '<a href="/cgi-bin/printout.pl?'.$identifier.'">'.$continue_text.'</a>'.$end_page);
1.525 www 2928: } else {
1.515 foxr 2929: $r->print(<<FINALEND);
1.317 albertel 2930: <br />
1.288 albertel 2931: <meta http-equiv="Refresh" content="0; url=/cgi-bin/printout.pl?$identifier" />
1.528 raeburn 2932: <a href="/cgi-bin/printout.pl?$identifier">$continue_text</a>
1.431 albertel 2933: $end_page
1.140 sakharuk 2934: FINALEND
1.528 raeburn 2935: } # endif ssi errors.
1.140 sakharuk 2936: }
2937:
1.288 albertel 2938:
2939: sub get_CODE {
1.381 albertel 2940: my ($all_codes,$num,$seed,$size,$type)=@_;
1.288 albertel 2941: my $max='1'.'0'x$size;
2942: my $newcode;
2943: while(1) {
1.392 albertel 2944: $newcode=sprintf("%0".$size."d",int(rand($max)));
1.288 albertel 2945: if (!exists($$all_codes{$newcode})) {
2946: $$all_codes{$newcode}=1;
1.381 albertel 2947: if ($type eq 'number' ) {
2948: return $newcode;
2949: } else {
2950: return &num_to_letters($newcode);
2951: }
1.288 albertel 2952: }
2953: }
2954: }
1.140 sakharuk 2955:
1.284 albertel 2956: sub print_resources {
1.360 albertel 2957: my ($r,$helper,$person,$type,$moreenv,$master_seq,$remove_latex_header,
1.422 albertel 2958: $LaTeXwidth)=@_;
1.284 albertel 2959: my $current_output = '';
1.375 foxr 2960: my $printed = '';
1.284 albertel 2961: my ($username,$userdomain,$usersection) = split /:/,$person;
2962: my $fullname = &get_name($username,$userdomain);
1.492 foxr 2963: my $namepostfix = "\\\\"; # Both anon and not anon should get the same vspace.
1.288 albertel 2964: if ($person =~ 'anon') {
1.492 foxr 2965: $namepostfix .="Name: ";
1.288 albertel 2966: $fullname = "CODE - ".$moreenv->{'CODE'};
2967: }
1.444 foxr 2968: # Fullname may have special latex characters that need \ prefixing:
2969: #
2970:
1.350 foxr 2971: my $i = 0;
1.284 albertel 2972: #goes through all resources, checks if they are available for
2973: #current student, and produces output
1.428 albertel 2974:
2975: &Apache::lonxml::clear_problem_counter();
1.364 albertel 2976: my %page_breaks = &get_page_breaks($helper);
1.476 albertel 2977: my $columns_in_format = (split(/\|/,$helper->{'VARS'}->{'FORMAT'}))[1];
1.440 foxr 2978: #
1.441 foxr 2979: # end each student with a
1.440 foxr 2980: # Special that allows the post processor to even out the page
2981: # counts later. Nasty problem this... it would be really
2982: # nice to put the special in as a postscript comment
1.441 foxr 2983: # e.g. \special{ps:\ENDOFSTUDENTSTAMP} unfortunately,
1.440 foxr 2984: # The special gets passed the \ and dvips puts it in the output file
1.441 foxr 2985: # so we will just rely on prntout.pl to strip ENDOFSTUDENTSTAMP from the
2986: # postscript. Each ENDOFSTUDENTSTAMP will go on a line by itself.
1.440 foxr 2987: #
1.568 foxr 2988: my $syllabus_first = 0;
1.284 albertel 2989: foreach my $curresline (@{$master_seq}) {
1.351 foxr 2990: if (defined $page_breaks{$curresline}) {
1.350 foxr 2991: if($i != 0) {
2992: $current_output.= "\\newpage\n";
2993: }
2994: }
1.569 foxr 2995: $current_output .= &get_extra_vspaces($helper, $curresline);
1.350 foxr 2996: $i++;
1.511 foxr 2997:
1.284 albertel 2998: if ( !($type eq 'problems' &&
1.582 raeburn 2999: ($curresline!~ m/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) ) {
1.284 albertel 3000: my ($map,$id,$res_url) = &Apache::lonnet::decode_symb($curresline);
3001: if (&Apache::lonnet::allowed('bre',$res_url)) {
1.414 albertel 3002: if ($res_url!~m|^ext/|
1.413 albertel 3003: && $res_url=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
1.375 foxr 3004: $printed .= $curresline.':';
1.428 albertel 3005: &Apache::lonxml::remember_problem_counter();
3006:
1.526 www 3007: my $rendered = &get_student_view_with_retries($curresline,$ssi_retry_count,$username,$userdomain,$env{'request.course.id'},'tex',$moreenv);
1.582 raeburn 3008: if ($res_url =~ /\.page$/) {
3009: if ($remove_latex_header eq 'NO') {
3010: if (!($rendered =~ /\\begin\{document\}/)) {
3011: $rendered = &print_latex_header().$rendered;
3012: }
3013: }
3014: if ($remove_latex_header eq 'YES') {
3015: $rendered = &latex_header_footer_remove($rendered);
3016: } else {
3017: $rendered =~ s/\\end{document}\d*//;
3018: }
3019: }
1.305 sakharuk 3020: if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
3021: ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.380 foxr 3022: # Use a copy of the hash so we don't pervert it on future loop passes.
3023: my %answerenv = %{$moreenv};
3024: $answerenv{'answer_output_mode'}='tex';
3025: $answerenv{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.428 albertel 3026:
3027: &Apache::lonxml::restore_problem_counter();
3028:
1.380 foxr 3029: my $ansrendered = &Apache::loncommon::get_student_answers($curresline,$username,$userdomain,$env{'request.course.id'},%answerenv);
1.428 albertel 3030:
1.305 sakharuk 3031: if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
3032: $rendered=~s/(\\keephidden{ENDOFPROBLEM})/$ansrendered$1/;
3033: } else {
1.423 foxr 3034:
3035:
3036: my $header =&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.582 raeburn 3037: unless ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only') {
3038: $header =~ s/\\begin{document}//; #<<<<<
3039: }
1.477 albertel 3040: my $title = &Apache::lonnet::gettitle($curresline);
3041: $title = &Apache::lonxml::latex_special_symbols($title);
3042: my $body ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
3043: $body .=&path_to_problem($res_url,$LaTeXwidth);
1.423 foxr 3044: $body .='\vskip 1 mm '.$ansrendered;
3045: $body = &encapsulate_minipage($body);
3046: $rendered = $header.$body;
1.305 sakharuk 3047: }
3048: }
1.511 foxr 3049: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
3050: my $url = &Apache::lonnet::clutter($res_url);
3051: my $annotation = &annotate($url);
3052: $rendered =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
3053: }
1.562 foxr 3054: my $junk;
1.305 sakharuk 3055: if ($remove_latex_header eq 'YES') {
3056: $rendered = &latex_header_footer_remove($rendered);
3057: } else {
3058: $rendered =~ s/\\end{document}//;
3059: }
3060: $current_output .= $rendered;
1.456 raeburn 3061: } elsif ($res_url=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) {
1.568 foxr 3062: if ($i == 1) {
3063: $syllabus_first = 1;
3064: }
1.375 foxr 3065: $printed .= $curresline.':';
1.528 raeburn 3066: my $rendered = &get_student_view_with_retries($curresline,$ssi_retry_count,$username,$userdomain,$env{'request.course.id'},'tex',$moreenv);
1.511 foxr 3067: if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
3068: my $url = &Apache::lonnet::clutter($res_url);
3069: my $annotation = &annotate($url);
3070: $annotation =~ s/(\\end{document})/$annotation$1/;
3071: }
1.305 sakharuk 3072: if ($remove_latex_header eq 'YES') {
3073: $rendered = &latex_header_footer_remove($rendered);
1.284 albertel 3074: } else {
1.305 sakharuk 3075: $rendered =~ s/\\end{document}//;
1.284 albertel 3076: }
1.421 foxr 3077: $current_output .= $rendered.'\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\strut \vskip 0 mm \strut ';
1.552 foxr 3078: } elsif($res_url = ~/\.pdf$/) {
3079: my $url = &Apache::lonnet::clutter($res_url);
3080: my $rendered = &include_pdf($url);
3081: if ($remove_latex_header ne 'NO') {
3082: $rendered = &latex_header_footer_remove($rendered);
3083: }
3084: $current_output .= $rendered;
1.284 albertel 3085: } else {
1.414 albertel 3086: my $rendered = &unsupported($res_url,$helper->{'VARS'}->{'LATEX_TYPE'},$curresline);
1.305 sakharuk 3087: if ($remove_latex_header ne 'NO') {
3088: $rendered = &latex_header_footer_remove($rendered);
3089: } else {
3090: $rendered =~ s/\\end{document}//;
3091: }
3092: $current_output .= $rendered;
1.284 albertel 3093: }
3094: }
3095: $remove_latex_header = 'YES';
1.550 foxr 3096: }
1.331 albertel 3097: if (&Apache::loncommon::connection_aborted($r)) { last; }
1.284 albertel 3098: }
1.552 foxr 3099:
1.583 raeburn 3100: if ($syllabus_first) {
3101: $current_output =~ s/\\\\ Last updated:/Last updated:/
3102: }
1.284 albertel 3103: my $courseidinfo = &get_course();
1.583.2.1 raeburn 3104: if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo }
3105: if ($usersection ne '') {$courseidinfo.=' - Sec. '.$usersection}
1.284 albertel 3106: my $currentassignment=&Apache::lonxml::latex_special_symbols($helper->{VARS}->{'assignment'},'header');
1.476 albertel 3107: my $header_line =
1.486 foxr 3108: &format_page_header($LaTeXwidth, $parmhash{'print_header_format'},
1.583.2.1 raeburn 3109: $currentassignment, $courseidinfo, $fullname);
1.476 albertel 3110: my $header_start = ($columns_in_format == 1) ? '\lhead'
3111: : '\fancyhead[LO]';
3112: $header_line = $header_start.'{'.$header_line.'}';
1.583 raeburn 3113: if ($current_output=~/\\documentclass/) {
1.476 albertel 3114: $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$header_line$namepostfix}\\vskip 5 mm /;
1.284 albertel 3115: } else {
1.476 albertel 3116: my $blankpages =
3117: '\clearpage\strut\clearpage'x$helper->{'VARS'}->{'EMPTY_PAGES'};
3118:
3119: $current_output = '\strut\vspace*{-6 mm}\\newline'.
3120: ©right_line().' \newpage '.$blankpages.$end_of_student.
3121: '\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent'.
3122: $header_line.$namepostfix.'} \vskip 5 mm '.$current_output;
1.284 albertel 3123: }
1.440 foxr 3124: #
3125: # Close the student bracketing.
3126: #
1.375 foxr 3127: return ($current_output,$fullname, $printed);
1.284 albertel 3128:
3129: }
1.140 sakharuk 3130:
1.3 sakharuk 3131: sub handler {
3132:
3133: my $r = shift;
1.397 albertel 3134:
3135: &init_perm();
1.114 bowersj2 3136:
1.416 foxr 3137:
1.67 www 3138:
1.397 albertel 3139: my $helper = printHelper($r);
3140: if (!ref($helper)) {
3141: return $helper;
1.60 sakharuk 3142: }
1.177 sakharuk 3143:
1.184 sakharuk 3144:
1.454 foxr 3145: %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'});
1.353 foxr 3146:
1.416 foxr 3147:
1.350 foxr 3148:
3149:
1.367 foxr 3150: # If a figure conversion queue file exists for this user.domain
3151: # we delete it since it can only be bad (if it were good, printout.pl
3152: # would have deleted it the last time around.
3153:
1.373 albertel 3154: my $conversion_queuefile = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat";
1.367 foxr 3155: if(-e $conversion_queuefile) {
3156: unlink $conversion_queuefile;
3157: }
1.515 foxr 3158:
3159:
1.184 sakharuk 3160: &output_data($r,$helper,\%parmhash);
1.2 sakharuk 3161: return OK;
1.60 sakharuk 3162: }
1.2 sakharuk 3163:
1.131 bowersj2 3164: use Apache::lonhelper;
1.130 sakharuk 3165:
1.223 bowersj2 3166: sub addMessage {
3167: my $text = shift;
3168: my $paramHash = Apache::lonhelper::getParamHash();
3169: $paramHash->{MESSAGE_TEXT} = $text;
3170: Apache::lonhelper::message->new();
3171: }
3172:
1.416 foxr 3173:
1.238 bowersj2 3174:
1.397 albertel 3175: sub init_perm {
3176: undef(%perm);
3177: $perm{'pav'}=&Apache::lonnet::allowed('pav',$env{'request.course.id'});
3178: if (!$perm{'pav'}) {
3179: $perm{'pav'}=&Apache::lonnet::allowed('pav',
3180: $env{'request.course.id'}.'/'.$env{'request.course.sec'});
3181: }
1.465 albertel 3182: $perm{'pfo'}=&Apache::lonnet::allowed('pfo',$env{'request.course.id'});
1.397 albertel 3183: if (!$perm{'pfo'}) {
3184: $perm{'pfo'}=&Apache::lonnet::allowed('pfo',
3185: $env{'request.course.id'}.'/'.$env{'request.course.sec'});
3186: }
1.583.2.4 raeburn 3187: $perm{'vgr'}=&Apache::lonnet::allowed('vgr',$env{'request.course.id'});
3188: if (!$perm{'vgr'}) {
3189: $perm{'vgr'}=&Apache::lonnet::allowed('vgr',
3190: $env{'request.course.id'}.'/'.$env{'request.course.sec'});
3191: }
1.397 albertel 3192: }
3193:
1.507 albertel 3194: sub get_randomly_ordered_warning {
3195: my ($helper,$map) = @_;
3196:
3197: my $message;
3198:
3199: my $postdata = $env{'form.postdata'} || $helper->{VARS}{'postdata'};
3200: my $navmap = Apache::lonnavmaps::navmap->new();
1.547 raeburn 3201: if (defined($navmap)) {
3202: my $res = $navmap->getResourceByUrl($map);
3203: if ($res) {
3204: my $func =
3205: sub { return ($_[0]->is_map() && $_[0]->randomorder); };
3206: my @matches = $navmap->retrieveResources($res, $func,1,1,1);
3207: if (@matches) {
3208: $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.";
3209: }
3210: }
3211: if ($message) {
3212: return '<message type="warning">'.$message.'</message>';
3213: }
3214: } else {
3215: $message = "Retrieval of information about ordering of resources failed.";
3216: return '<message type="warning">'.$message.'</message>';
1.507 albertel 3217: }
3218: return;
3219: }
3220:
1.131 bowersj2 3221: sub printHelper {
1.115 bowersj2 3222: my $r = shift;
3223:
3224: if ($r->header_only) {
1.373 albertel 3225: if ($env{'browser.mathml'}) {
1.241 www 3226: &Apache::loncommon::content_type($r,'text/xml');
1.131 bowersj2 3227: } else {
1.241 www 3228: &Apache::loncommon::content_type($r,'text/html');
1.131 bowersj2 3229: }
3230: $r->send_http_header;
3231: return OK;
1.115 bowersj2 3232: }
3233:
1.131 bowersj2 3234: # Send header, nocache
1.373 albertel 3235: if ($env{'browser.mathml'}) {
1.241 www 3236: &Apache::loncommon::content_type($r,'text/xml');
1.115 bowersj2 3237: } else {
1.241 www 3238: &Apache::loncommon::content_type($r,'text/html');
1.115 bowersj2 3239: }
3240: &Apache::loncommon::no_cache($r);
3241: $r->send_http_header;
3242: $r->rflush();
3243:
1.131 bowersj2 3244: # Unfortunately, this helper is so complicated we have to
3245: # write it by hand
3246:
3247: Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
3248:
1.176 bowersj2 3249: my $helper = Apache::lonhelper::helper->new("Printing Helper");
1.146 bowersj2 3250: $helper->declareVar('symb');
1.156 bowersj2 3251: $helper->declareVar('postdata');
1.290 sakharuk 3252: $helper->declareVar('curseed');
3253: $helper->declareVar('probstatus');
1.156 bowersj2 3254: $helper->declareVar('filename');
3255: $helper->declareVar('construction');
1.178 sakharuk 3256: $helper->declareVar('assignment');
1.262 sakharuk 3257: $helper->declareVar('style_file');
1.340 foxr 3258: $helper->declareVar('student_sort');
1.363 foxr 3259: $helper->declareVar('FINISHPAGE');
1.366 foxr 3260: $helper->declareVar('PRINT_TYPE');
1.372 foxr 3261: $helper->declareVar("showallfoils");
1.483 foxr 3262: $helper->declareVar("STUDENTS");
1.569 foxr 3263: $helper->declareVar("EXTRASPACE");
1.518 foxr 3264:
3265:
3266:
3267:
1.569 foxr 3268: # The page breaks and extra spaces
3269: # can get loaded initially from the course environment:
1.394 foxr 3270: # But we only do this in the initial state so that they are allowed to change.
3271: #
1.366 foxr 3272:
1.363 foxr 3273:
3274: &Apache::loncommon::restore_course_settings('print',
1.366 foxr 3275: {'pagebreaks' => 'scalar',
1.569 foxr 3276: 'extraspace' => 'scalar',
1.570 foxr 3277: 'extraspace_units' => 'scalar',
1.366 foxr 3278: 'lastprinttype' => 'scalar'});
3279:
1.483 foxr 3280: # This will persistently load in the data we want from the
3281: # very first screen.
1.394 foxr 3282:
3283: if($helper->{VARS}->{PRINT_TYPE} eq $env{'form.lastprinttype'}) {
3284: if (!defined ($env{"form.CURRENT_STATE"})) {
3285:
3286: $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'};
1.569 foxr 3287: $helper->{VARS}->{EXTRASPACE} = $env{'form.extraspace'};
1.570 foxr 3288: $helper->{VARS}->{EXTRASPACE_UNITS} = $env{'form.extraspace_units'};
1.394 foxr 3289: } else {
3290: my $state = $env{"form.CURRENT_STATE"};
3291: if ($state eq "START") {
3292: $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'};
1.569 foxr 3293: $helper->{VARS}->{EXTRASPACE} = $env{'form.extraspace'};
1.570 foxr 3294: $helper->{VARS}->{EXTRASPACE_UNITS} = $env{'form.extraspace_units'};
3295:
1.394 foxr 3296: }
3297: }
3298:
1.366 foxr 3299: }
1.481 albertel 3300:
1.156 bowersj2 3301: # Detect whether we're coming from construction space
1.373 albertel 3302: if ($env{'form.postdata'}=~/^(?:http:\/\/[^\/]+\/|\/|)\~([^\/]+)\/(.*)$/) {
1.235 bowersj2 3303: $helper->{VARS}->{'filename'} = "~$1/$2";
1.156 bowersj2 3304: $helper->{VARS}->{'construction'} = 1;
1.481 albertel 3305: } else {
1.373 albertel 3306: if ($env{'form.postdata'}) {
3307: $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($env{'form.postdata'});
1.482 albertel 3308: if ( $helper->{VARS}->{'symb'} eq '') {
3309: $helper->{VARS}->{'postdata'} = $env{'form.postdata'};
3310: }
1.156 bowersj2 3311: }
1.373 albertel 3312: if ($env{'form.symb'}) {
3313: $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.156 bowersj2 3314: }
1.373 albertel 3315: if ($env{'form.url'}) {
1.156 bowersj2 3316: $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
3317: }
1.416 foxr 3318:
1.157 bowersj2 3319: }
1.481 albertel 3320:
1.373 albertel 3321: if ($env{'form.symb'}) {
3322: $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.146 bowersj2 3323: }
1.373 albertel 3324: if ($env{'form.url'}) {
1.140 sakharuk 3325: $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
1.153 sakharuk 3326:
1.140 sakharuk 3327: }
1.343 albertel 3328: $helper->{VARS}->{'symb'}=
3329: &Apache::lonenc::check_encrypt($helper->{VARS}->{'symb'});
1.335 albertel 3330: my ($resourceTitle,$sequenceTitle,$mapTitle) = &details_for_menu($helper);
1.178 sakharuk 3331: if ($sequenceTitle ne '') {$helper->{VARS}->{'assignment'}=$sequenceTitle;}
1.481 albertel 3332:
1.156 bowersj2 3333:
1.146 bowersj2 3334: # Extract map
3335: my $symb = $helper->{VARS}->{'symb'};
1.156 bowersj2 3336: my ($map, $id, $url);
3337: my $subdir;
1.483 foxr 3338: my $is_published=0; # True when printing from resource space.
1.156 bowersj2 3339:
3340: # Get the resource name from construction space
3341: if ($helper->{VARS}->{'construction'}) {
3342: $resourceTitle = substr($helper->{VARS}->{'filename'},
3343: rindex($helper->{VARS}->{'filename'}, '/')+1);
3344: $subdir = substr($helper->{VARS}->{'filename'},
3345: 0, rindex($helper->{VARS}->{'filename'}, '/') + 1);
1.481 albertel 3346: } else {
1.562 foxr 3347: # From course space:
3348:
1.482 albertel 3349: if ($symb ne '') {
3350: ($map, $id, $url) = &Apache::lonnet::decode_symb($symb);
3351: $helper->{VARS}->{'postdata'} =
3352: &Apache::lonenc::check_encrypt(&Apache::lonnet::clutter($url));
3353: } else {
3354: $url = $helper->{VARS}->{'postdata'};
1.483 foxr 3355: $is_published=1; # From resource space.
1.482 albertel 3356: }
3357: $url = &Apache::lonnet::clutter($url);
1.156 bowersj2 3358: if (!$resourceTitle) { # if the resource doesn't have a title, use the filename
1.238 bowersj2 3359: my $postdata = $helper->{VARS}->{'postdata'};
3360: $resourceTitle = substr($postdata, rindex($postdata, '/') + 1);
1.156 bowersj2 3361: }
3362: $subdir = &Apache::lonnet::filelocation("", $url);
1.128 bowersj2 3363: }
1.373 albertel 3364: if (!$helper->{VARS}->{'curseed'} && $env{'form.curseed'}) {
3365: $helper->{VARS}->{'curseed'}=$env{'form.curseed'};
1.230 albertel 3366: }
1.373 albertel 3367: if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) {
1.512 foxr 3368: $helper->{VARS}->{'probstatus'}=$env{'form.problemstatus'};
1.290 sakharuk 3369: }
1.115 bowersj2 3370:
1.192 bowersj2 3371: my $userCanSeeHidden = Apache::lonnavmaps::advancedUser();
3372:
1.481 albertel 3373: Apache::lonhelper::registerHelperTags();
1.119 bowersj2 3374:
1.131 bowersj2 3375: # "Delete everything after the last slash."
1.119 bowersj2 3376: $subdir =~ s|/[^/]+$||;
3377:
1.131 bowersj2 3378: # What can be printed is a very dynamic decision based on
3379: # lots of factors. So we need to dynamically build this list.
3380: # To prevent security leaks, states are only added to the wizard
3381: # if they can be reached, which ensures manipulating the form input
3382: # won't allow anyone to reach states they shouldn't have permission
3383: # to reach.
3384:
3385: # printChoices is tracking the kind of printing the user can
3386: # do, and will be used in a choices construction later.
3387: # In the meantime we will be adding states and elements to
3388: # the helper by hand.
3389: my $printChoices = [];
3390: my $paramHash;
1.130 sakharuk 3391:
1.240 albertel 3392: if ($resourceTitle) {
1.458 www 3393: push @{$printChoices}, ["<b><i>$resourceTitle</i></b> (".&mt('the resource you just saw on the screen').")", 'current_document', 'PAGESIZE'];
1.156 bowersj2 3394: }
3395:
1.238 bowersj2 3396: # Useful filter strings
1.540 raeburn 3397: my $isProblem = '($res->is_problem()||$res->contains_problem||$res->is_practice()) ';
1.238 bowersj2 3398: $isProblem .= ' && !$res->randomout()' if !$userCanSeeHidden;
1.541 raeburn 3399: my $isProblemOrMap = '$res->is_problem() || $res->contains_problem() || $res->is_sequence() || $res->is_practice()';
1.287 albertel 3400: my $isNotMap = '!$res->is_sequence()';
1.238 bowersj2 3401: $isNotMap .= ' && !$res->randomout()' if !$userCanSeeHidden;
3402: my $isMap = '$res->is_map()';
1.342 albertel 3403: my $symbFilter = '$res->shown_symb()';
3404: my $urlValue = '$res->link()';
1.238 bowersj2 3405:
3406: $helper->declareVar('SEQUENCE');
3407:
1.465 albertel 3408: # If we're in a sequence...
1.416 foxr 3409:
1.465 albertel 3410: my $start_new_option;
3411: if ($perm{'pav'}) {
3412: $start_new_option =
3413: "<option text='".&mt('Start new page<br />before selected').
1.569 foxr 3414: "' variable='FINISHPAGE' />".
1.570 foxr 3415: "<option text='".&mt('Extra space<br />before selected').
1.569 foxr 3416: "' variable='EXTRASPACE' type='text' />" .
3417: "<option " .
1.570 foxr 3418: "' variable='POSSIBLE_RESOURCES' type='hidden' />".
3419: "<option text='".&mt('Space units<br />check for mm').
3420: "' variable='EXTRASPACE_UNITS' type='checkbox' />"
3421: ;
3422:
1.569 foxr 3423:
1.465 albertel 3424: }
1.238 bowersj2 3425:
1.562 foxr 3426: # If not construction space user can print the components of a page:
3427:
3428: my $page_ispage;
3429: my $page_title;
3430: if (!$helper->{VARS}->{'construction'}) {
3431: my $varspostdata = $helper->{VARS}->{'postdata'};
3432: my $varsassignment = $helper->{VARS}->{'assignment'};
3433: my $page_navmap = Apache::lonnavmaps::navmap->new();
1.563 foxr 3434: if (defined($page_navmap)) {
3435: my @page_resources = $page_navmap->retrieveResources($url);
3436: if(defined($page_resources[0])) {
3437: $page_ispage = $page_resources[0]->is_page();
3438: $page_title = $page_resources[0]->title();
3439: my $resourcesymb = $page_resources[0]->symb();
3440: my ($pagemap, $pageid, $pageurl) = &Apache::lonnet::decode_symb($symb);
3441: if ($page_ispage) {
3442: push @{$printChoices},
3443: [&mt('Selected [_1]Problems[_2] from page [_3]', '<b>', '</b>', '<b><i>'.$page_title.'</i></b>'),
3444: 'map_problems_in_page',
3445: 'CHOOSE_PROBLEMS_PAGE'];
3446: push @{$printChoices},
3447: [&mt('Selected [_1]Resources[_2] from page [_3]', '<b>', '</b>', '<b><i>'.$page_title.'</i></b>'),
3448: 'map_resources_in_page',
3449: 'CHOOSE_RESOURCES_PAGE'];
3450: }
1.562 foxr 3451: my $helperFragment = &generate_resource_chooser('CHOOSE_PROBLEMS_PAGE',
3452: 'Select Problem(s) to print',
3453: "multichoice='1' toponly='1' addstatus='1' closeallpages='1'",
3454: 'RESOURCES',
3455: 'PAGESIZE',
3456: $url,
3457: $isProblem, '', $symbFilter,
3458: $start_new_option);
3459:
3460:
3461: $helperFragment .= &generate_resource_chooser('CHOOSE_RESOURCES_PAGE',
3462: 'Select Resource(s) to print',
3463: 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
3464: 'RESOURCES',
3465: 'PAGESIZE',
3466: $url,
3467: $isNotMap, '', $symbFilter,
3468: $start_new_option);
3469:
3470:
3471:
3472:
3473:
3474: &Apache::lonxml::xmlparse($r, 'helper', $helperFragment);
3475:
1.563 foxr 3476: }
3477: }
1.562 foxr 3478: }
3479:
3480: if (($helper->{'VAR'}->{'construction'} ne '1' ) &&
1.243 bowersj2 3481: $helper->{VARS}->{'postdata'} &&
3482: $helper->{VARS}->{'assignment'}) {
1.131 bowersj2 3483: # Allow problems from sequence
1.562 foxr 3484: push @{$printChoices},
3485: [&mt('Selected [_1]Problems[_2] from folder [_3]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>'),
3486: 'map_problems',
3487: 'CHOOSE_PROBLEMS'];
1.131 bowersj2 3488: # Allow all resources from sequence
1.562 foxr 3489: push @{$printChoices}, [&mt('Selected [_1]Resources[_2] from folder [_3]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>'),
3490: 'map_problems_pages',
3491: 'CHOOSE_PROBLEMS_HTML'];
3492: my $helperFragment = &generate_resource_chooser('CHOOSE_PROBLEMS',
3493: 'Select Problem(s) to print',
3494: 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
3495: 'RESOURCES',
3496: 'PAGESIZE',
3497: $map,
3498: $isProblem, '',
3499: $symbFilter,
3500: $start_new_option);
3501: $helperFragment .= &generate_resource_chooser('CHOOSE_PROBLEMS_HTML',
3502: 'Select Resource(s) to print',
3503: 'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
3504: 'RESOURCES',
3505: 'PAGESIZE',
3506: $map,
3507: $isNotMap, '',
3508: $symbFilter,
3509: $start_new_option);
1.121 bowersj2 3510:
1.326 sakharuk 3511: &Apache::lonxml::xmlparse($r, 'helper', $helperFragment);
1.121 bowersj2 3512: }
3513:
1.546 bisitz 3514: # If the user has pfo (print for others) allow them to print all
3515: # problems and resources in the entire course, optionally for selected students
1.562 foxr 3516: my $post_data = $helper->{VARS}->{'postdata'};
1.483 foxr 3517: if ($perm{'pfo'} && !$is_published &&
1.562 foxr 3518: ($post_data=~/\/res\// || $post_data =~/\/(syllabus|smppg|aboutme|bulletinboard)$/)) {
1.481 albertel 3519:
1.509 albertel 3520: push @{$printChoices}, [&mtn('Selected <b>Problems</b> from <b>entire course</b>'), 'all_problems', 'ALL_PROBLEMS'];
3521: push @{$printChoices}, [&mtn('Selected <b>Resources</b> from <b>entire course</b>'), 'all_resources', 'ALL_RESOURCES'];
1.536 foxr 3522: 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 3523: my $suffixXml = <<ALL_PROBLEMS;
1.536 foxr 3524: <state name="STUDENTS1" title="Select People">
3525: <message><b>Select sorting order of printout</b> </message>
3526: <choices variable='student_sort'>
3527: <choice computer='0'>Sort by section then student</choice>
3528: <choice computer='1'>Sort by students across sections.</choice>
3529: </choices>
3530: <message><br /><hr /><br /> </message>
3531: <student multichoice='1' variable="STUDENTS" nextstate="PRINT_FORMATTING" coursepersonnel="1"/>
3532: </state>
1.284 albertel 3533: ALL_PROBLEMS
1.562 foxr 3534: &Apache::lonxml::xmlparse($r, 'helper',
3535: &generate_resource_chooser('ALL_PROBLEMS',
3536: 'SelectProblem(s) to print',
3537: 'multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1"',
3538: 'RESOURCES',
3539: 'PAGESIZE',
3540: '',
3541: $isProblemOrMap, $isNotMap,
3542: $symbFilter,
3543: $start_new_option) .
3544: &generate_resource_chooser('ALL_RESOURCES',
3545: 'Select Resource(s) to print',
3546: " toponly='0' multichoice='1' suppressEmptySequences='0' addstatus='1' closeallpages='1'",
3547: 'RESOURCES',
3548: 'PAGESIZE',
3549: '',
3550: $isNotMap,'',$symbFilter,
3551: $start_new_option) .
3552: &generate_resource_chooser('ALL_PROBLEMS_STUDENTS',
3553: 'Select Problem(s) to print',
3554: 'toponly="0" multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1"',
3555: 'RESOURCES',
3556: 'STUDENTS1',
3557: '',
3558: $isProblemOrMap,'' , $symbFilter,
3559: $start_new_option) .
3560: $suffixXml
3561: );
1.132 bowersj2 3562:
1.284 albertel 3563: if ($helper->{VARS}->{'assignment'}) {
1.562 foxr 3564:
3565: # If we were looking at a page, allow a selection of problems from the page
3566: # either for selected students or for coded assignments.
3567:
3568: if ($page_ispage) {
3569: push @{$printChoices}, [&mt('Selected [_1]Problems[_2] from page [_3] for [_4]selected people[_5]',
3570: '<b>', '</b>', '<b><i>'.$page_title.'</i></b>', '<b>', '</b>'),
3571: 'problems_for_students_from_page', 'CHOOSE_TGT_STUDENTS_PAGE'];
3572: push @{$printChoices}, [&mt('Selected [_1]Problems[_2] from page [_3] for [_4]CODEd assignments[_5]',
3573: '<b>', '</b>', '<b><i>'.$page_title.'</i></b>', '<b>', '</b>'),
3574: 'problems_for_anon_page', 'CHOOSE_ANON1_PAGE'];
3575: }
3576: push @{$printChoices}, [&mt('Selected [_1]Problems[_2] from folder [_3] for [_4]selected people[_5]',
3577: '<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>','<b>','</b>'),
3578: 'problems_for_students', 'CHOOSE_STUDENTS'];
3579: push @{$printChoices}, [&mt('Selected [_1]Problems[_2] from folder [_3] for [_4]CODEd assignments[_5]',
3580: '<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>','<b>','</b>'),
3581: 'problems_for_anon', 'CHOOSE_ANON1'];
1.284 albertel 3582: }
1.424 foxr 3583:
1.507 albertel 3584: my $randomly_ordered_warning =
3585: &get_randomly_ordered_warning($helper,$map);
3586:
1.424 foxr 3587: # resource_selector will hold a few states that:
3588: # - Allow resources to be selected for printing.
3589: # - Determine pagination between assignments.
3590: # - Determine how many assignments should be bundled into a single PDF.
3591: # TODO:
3592: # Probably good to do things like separate this up into several vars, each
3593: # with one state, and use REGEXPs at inclusion time to set state names
3594: # and next states for better mix and match capability
3595: #
1.562 foxr 3596: my $resource_selector= &generate_resource_chooser('SELECT_PROBLEMS',
3597: 'Select resources to print',
3598: 'multichoice="1" addstatus="1" closeallpages="1"',
3599: 'RESOURCES',
3600: 'PRINT_FORMATTING',
1.571 droeschl 3601: $map,
1.562 foxr 3602: $isProblem, '', $symbFilter,
3603: $start_new_option);
1.583.2.5 raeburn 3604: $resource_selector .= &generate_format_selector($helper,
3605: 'How should results be printed?',
3606: 'PRINT_FORMATTING').
3607: &generate_resource_chooser('CHOOSE_STUDENTS_PAGE',
1.562 foxr 3608: 'Select Problem(s) to print',
3609: "multichoice='1' addstatus='1' closeallpages ='1'",
3610: 'RESOURCES',
3611: 'PRINT_FORMATTING',
3612: $url,
3613: $isProblem, '', $symbFilter,
3614: $start_new_option);
3615:
3616:
3617: # Generate student choosers.
3618:
3619:
1.284 albertel 3620:
1.562 foxr 3621: &Apache::lonxml::xmlparse($r, 'helper',
3622: &generate_student_chooser('CHOOSE_TGT_STUDENTS_PAGE',
3623: 'student_sort',
3624: 'STUDENTS',
3625: 'CHOOSE_STUDENTS_PAGE'));
3626: &Apache::lonxml::xmlparse($r, 'helper',
3627: &generate_student_chooser('CHOOSE_STUDENTS',
3628: 'student_sort',
3629: 'STUDENTS',
3630: 'SELECT_PROBLEMS'));
3631: &Apache::lonxml::xmlparse($r, 'helper', $resource_selector);
1.292 albertel 3632:
1.373 albertel 3633: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
3634: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.292 albertel 3635: my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum);
3636: my $namechoice='<choice></choice>';
1.337 albertel 3637: foreach my $name (sort {uc($a) cmp uc($b)} @names) {
1.294 albertel 3638: if ($name =~ /^error: 2 /) { next; }
1.381 albertel 3639: if ($name =~ /^type\0/) { next; }
1.292 albertel 3640: $namechoice.='<choice computer="'.$name.'">'.$name.'</choice>';
3641: }
1.389 foxr 3642:
3643:
3644: my %code_values;
1.405 albertel 3645: my %codes_to_print;
1.411 albertel 3646: foreach my $key (@names) {
1.389 foxr 3647: %code_values = &Apache::grades::get_codes($key, $cdom, $cnum);
1.405 albertel 3648: foreach my $key (keys(%code_values)) {
3649: $codes_to_print{$key} = 1;
1.388 foxr 3650: }
3651: }
1.389 foxr 3652:
1.452 albertel 3653: my $code_selection;
1.405 albertel 3654: foreach my $code (sort {uc($a) cmp uc($b)} (keys(%codes_to_print))) {
1.389 foxr 3655: my $choice = $code;
3656: if ($code =~ /^[A-Z]+$/) { # Alpha code
3657: $choice = &letters_to_num($code);
3658: }
1.432 albertel 3659: push(@{$helper->{DATA}{ALL_CODE_CHOICES}},[$code,$choice]);
1.388 foxr 3660: }
1.436 albertel 3661: if (%codes_to_print) {
3662: $code_selection .='
1.472 albertel 3663: <message><b>Choose single CODE from list:</b></message>
1.448 albertel 3664: <message></td><td></message>
1.452 albertel 3665: <dropdown variable="CODE_SELECTED_FROM_LIST" multichoice="0" allowempty="0">
3666: <choice></choice>
1.448 albertel 3667: <exec>
3668: push(@{$state->{CHOICES}},@{$helper->{DATA}{ALL_CODE_CHOICES}});
3669: </exec>
1.452 albertel 3670: </dropdown>
1.468 foxr 3671: <message></td></tr><tr><td></message>
1.436 albertel 3672: '.$/;
1.448 albertel 3673:
1.436 albertel 3674: }
1.432 albertel 3675:
1.542 raeburn 3676: my @lines = &Apache::grades::get_scantronformat_file();
1.381 albertel 3677: my $codechoice='';
1.542 raeburn 3678: foreach my $line (@lines) {
1.381 albertel 3679: my ($name,$description,$code_type,$code_length)=
3680: (split(/:/,$line))[0,1,2,4];
3681: if ($code_length > 0 &&
3682: $code_type =~/^(letter|number|-1)/) {
3683: $codechoice.='<choice computer="'.$name.'">'.$description.'</choice>';
3684: }
3685: }
3686: if ($codechoice eq '') {
3687: $codechoice='<choice computer="default">Default</choice>';
3688: }
1.562 foxr 3689: my $anon1 = &generate_code_selector($helper,
3690: 'CHOOSE_ANON1',
3691: 'SELECT_PROBLEMS',
3692: $codechoice,
3693: $code_selection,
3694: $namechoice) . $resource_selector;
3695:
3696:
3697: &Apache::lonxml::xmlparse($r, 'helper',$anon1);
3698:
3699: my $anon_page = &generate_code_selector($helper,
3700: 'CHOOSE_ANON1_PAGE',
3701: 'SELECT_PROBLEMS_PAGE',
3702: $codechoice,
3703: $code_selection,
3704: $namechoice) .
3705: &generate_resource_chooser('SELECT_PROBLEMS_PAGE',
3706: 'Select Problem(s) to print',
3707: "multichoice='1' addstatus='1' closeallpages ='1'",
3708: 'RESOURCES',
3709: 'PRINT_FORMATTING',
3710: $url,
3711: $isProblem, '', $symbFilter,
3712: $start_new_option);
3713: &Apache::lonxml::xmlparse($r, 'helper', $anon_page);
1.254 sakharuk 3714:
1.272 sakharuk 3715:
1.254 sakharuk 3716: if ($helper->{VARS}->{'assignment'}) {
1.546 bisitz 3717: 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'];
3718: 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 3719: }
1.284 albertel 3720:
3721:
3722: $resource_selector=<<RESOURCE_SELECTOR;
1.424 foxr 3723: <state name="SELECT_RESOURCES" title="Select Resources">
1.507 albertel 3724: $randomly_ordered_warning
1.424 foxr 3725: <nextstate>PRINT_FORMATTING</nextstate>
1.254 sakharuk 3726: <message><br /><big><i><b>Select resources for the assignment</b></i></big><br /></message>
1.287 albertel 3727: <resource variable="RESOURCES" multichoice="1" addstatus="1"
3728: closeallpages="1">
1.254 sakharuk 3729: <filterfunc>return $isNotMap;</filterfunc>
3730: <mapurl>$map</mapurl>
3731: <valuefunc>return $symbFilter;</valuefunc>
1.465 albertel 3732: $start_new_option
1.254 sakharuk 3733: </resource>
1.424 foxr 3734: </state>
1.284 albertel 3735: RESOURCE_SELECTOR
3736:
1.583.2.5 raeburn 3737: $resource_selector .= &generate_format_selector($helper,
3738: 'Format of the print job',
3739: 'PRINT_FORMATTING');
1.284 albertel 3740: &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_STUDENTS1);
3741: <state name="CHOOSE_STUDENTS1" title="Select Students and Resources">
1.340 foxr 3742: <choices variable='student_sort'>
3743: <choice computer='0'>Sort by section then student</choice>
3744: <choice computer='1'>Sort by students across sections.</choice>
3745: </choices>
1.437 foxr 3746: <message><br /><hr /><br /></message>
1.426 foxr 3747: <student multichoice='1' variable="STUDENTS" nextstate="SELECT_RESOURCES" coursepersonnel="1" />
1.340 foxr 3748:
1.424 foxr 3749: </state>
1.284 albertel 3750: $resource_selector
1.254 sakharuk 3751: CHOOSE_STUDENTS1
3752:
1.284 albertel 3753: &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_ANON2);
1.472 albertel 3754: <state name="CHOOSE_ANON2" title="Select CODEd Assignments">
1.424 foxr 3755: <nextstate>SELECT_RESOURCES</nextstate>
1.472 albertel 3756: <message><h4>Fill out one of the forms below</h4></message>
3757: <message><br /><hr /> <br /></message>
3758: <message><h3>Generate new CODEd Assignments</h3></message>
3759: <message><table><tr><td><b>Number of CODEd assignments to print:</b></td><td></message>
1.579 foxr 3760: <string variable="NUMBER_TO_PRINT_TOTAL" maxlength="5" size="5" noproceed="1">
1.362 albertel 3761: <validator>
3762: if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) &&
1.386 foxr 3763: !\$helper->{'VARS'}{'REUSE_OLD_CODES'} &&
1.388 foxr 3764: !\$helper->{'VARS'}{'SINGLE_CODE'} &&
3765: !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.362 albertel 3766: return "You need to specify the number of assignments to print";
3767: }
1.578 foxr 3768: if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) >= 1) &&
3769: (\$helper->{'VARS'}{'SINGLE_CODE'} ne '') ) {
3770: return 'Specifying number of codes to print and a specific code is not compatible';
3771: }
1.362 albertel 3772: return undef;
3773: </validator>
3774: </string>
3775: <message></td></tr><tr><td></message>
1.501 albertel 3776: <message><b>Names to save the CODEs under for later:</b></message>
1.412 albertel 3777: <message></td><td></message>
3778: <string variable="ANON_CODE_STORAGE_NAME" maxlength="50" size="20" />
3779: <message></td></tr><tr><td></message>
3780: <message><b>Bubble sheet type:</b></message>
3781: <message></td><td></message>
3782: <dropdown variable="CODE_OPTION" multichoice="0" allowempty="0">
3783: $codechoice
3784: </dropdown>
1.472 albertel 3785: <message></td></tr><tr><td></table></message>
3786: <message><br /><hr /><h3>Print a Specific CODE </h3><br /><table></message>
3787: <message><tr><td><b>Enter a CODE to print:</b></td><td></message>
1.412 albertel 3788: <string variable="SINGLE_CODE" size="10">
1.386 foxr 3789: <validator>
3790: if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'} &&
1.388 foxr 3791: !\$helper->{'VARS'}{'REUSE_OLD_CODES'} &&
3792: !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.386 foxr 3793: return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'},
3794: \$helper->{'VARS'}{'CODE_OPTION'});
1.577 foxr 3795: } elsif (\$helper->{'VARS'}{'SINGLE_CODE'} ne ''){
1.578 foxr 3796: return 'Specifying a code name is incompatible specifying number of codes.';
1.386 foxr 3797: } else {
3798: return undef; # Other forces control us.
3799: }
3800: </validator>
3801: </string>
1.472 albertel 3802: <message></td></tr><tr><td></message>
1.432 albertel 3803: $code_selection
1.472 albertel 3804: <message></td></tr></table></message>
3805: <message><hr /><h3>Reprint a Set of Saved CODEs</h3><table><tr><td></message>
3806: <message><b>Select saved CODEs:</b></message>
1.381 albertel 3807: <message></td><td></message>
1.294 albertel 3808: <dropdown variable="REUSE_OLD_CODES">
3809: $namechoice
3810: </dropdown>
1.412 albertel 3811: <message></td></tr></table></message>
1.424 foxr 3812: </state>
1.284 albertel 3813: $resource_selector
3814: CHOOSE_ANON2
1.481 albertel 3815: }
3816:
1.121 bowersj2 3817: # FIXME: That RE should come from a library somewhere.
1.483 foxr 3818: if (($perm{'pav'}
1.482 albertel 3819: && $subdir ne $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'
3820: && (defined($helper->{'VARS'}->{'construction'})
3821: ||
3822: (&Apache::lonnet::allowed('bre',$subdir) eq 'F'
3823: &&
3824: $helper->{VARS}->{'postdata'}=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)/)
1.483 foxr 3825: ))
3826: && $helper->{VARS}->{'assignment'} eq ""
1.482 albertel 3827: ) {
3828: my $pretty_dir = &Apache::lonnet::hreflocation($subdir);
1.546 bisitz 3829: 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 3830: my $xmlfrag = <<CHOOSE_FROM_SUBDIR;
1.482 albertel 3831: <state name="CHOOSE_FROM_SUBDIR" title="Select File(s) from <b><small>$pretty_dir</small></b> to print">
1.458 www 3832:
1.138 bowersj2 3833: <files variable="FILES" multichoice='1'>
1.144 bowersj2 3834: <nextstate>PAGESIZE</nextstate>
1.138 bowersj2 3835: <filechoice>return '$subdir';</filechoice>
1.139 bowersj2 3836: CHOOSE_FROM_SUBDIR
3837:
1.238 bowersj2 3838: # this is broken up because I really want interpolation above,
3839: # and I really DON'T want it below
1.139 bowersj2 3840: $xmlfrag .= <<'CHOOSE_FROM_SUBDIR';
1.225 bowersj2 3841: <filefilter>return Apache::lonhelper::files::not_old_version($filename) &&
3842: $filename =~ m/\.(problem|exam|quiz|assess|survey|form|library)$/;
1.131 bowersj2 3843: </filefilter>
1.138 bowersj2 3844: </files>
1.131 bowersj2 3845: </state>
3846: CHOOSE_FROM_SUBDIR
1.139 bowersj2 3847: &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
1.131 bowersj2 3848: }
1.238 bowersj2 3849:
3850: # Allow the user to select any sequence in the course, feed it to
3851: # another resource selector for that sequence
1.483 foxr 3852: if (!$helper->{VARS}->{'construction'} && !$is_published) {
1.509 albertel 3853: push @$printChoices, [&mtn("Selected <b>Resources</b> from <b>selected folder</b> in course"),
1.249 sakharuk 3854: 'select_sequences', 'CHOOSE_SEQUENCE'];
1.244 bowersj2 3855: my $escapedSequenceName = $helper->{VARS}->{'SEQUENCE'};
3856: #Escape apostrophes and backslashes for Perl
3857: $escapedSequenceName =~ s/\\/\\\\/g;
3858: $escapedSequenceName =~ s/'/\\'/g;
1.239 bowersj2 3859: &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_FROM_ANY_SEQUENCE);
1.238 bowersj2 3860: <state name="CHOOSE_SEQUENCE" title="Select Sequence To Print From">
3861: <message>Select the sequence to print resources from:</message>
3862: <resource variable="SEQUENCE">
3863: <nextstate>CHOOSE_FROM_ANY_SEQUENCE</nextstate>
3864: <filterfunc>return \$res->is_sequence;</filterfunc>
3865: <valuefunc>return $urlValue;</valuefunc>
1.447 foxr 3866: <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
1.391 foxr 3867: </choicefunc>
1.238 bowersj2 3868: </resource>
3869: </state>
3870: <state name="CHOOSE_FROM_ANY_SEQUENCE" title="Select Resources To Print">
3871: <message>(mark desired resources then click "next" button) <br /></message>
1.435 foxr 3872: <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287 albertel 3873: closeallpages="1">
1.238 bowersj2 3874: <nextstate>PAGESIZE</nextstate>
1.466 albertel 3875: <filterfunc>return $isNotMap</filterfunc>
1.244 bowersj2 3876: <mapurl evaluate='1'>return '$escapedSequenceName';</mapurl>
1.238 bowersj2 3877: <valuefunc>return $symbFilter;</valuefunc>
1.465 albertel 3878: $start_new_option
1.238 bowersj2 3879: </resource>
3880: </state>
3881: CHOOSE_FROM_ANY_SEQUENCE
1.239 bowersj2 3882: }
1.481 albertel 3883:
1.131 bowersj2 3884: # Generate the first state, to select which resources get printed.
1.223 bowersj2 3885: Apache::lonhelper::state->new("START", "Select Printing Options:");
1.131 bowersj2 3886: $paramHash = Apache::lonhelper::getParamHash();
1.155 sakharuk 3887: $paramHash->{MESSAGE_TEXT} = "";
1.131 bowersj2 3888: Apache::lonhelper::message->new();
3889: $paramHash = Apache::lonhelper::getParamHash();
3890: $paramHash->{'variable'} = 'PRINT_TYPE';
3891: $paramHash->{CHOICES} = $printChoices;
3892: Apache::lonhelper::choices->new();
1.161 bowersj2 3893:
1.223 bowersj2 3894: my $startedTable = 0; # have we started an HTML table yet? (need
3895: # to close it later)
3896:
1.583.2.4 raeburn 3897: if (($perm{'pav'} and $perm{'vgr'}) or
1.170 sakharuk 3898: ($helper->{VARS}->{'construction'} eq '1')) {
1.544 bisitz 3899: &addMessage('<br />'
3900: .'<h3>'.&mt('Print Options').'</h3>'
3901: .&Apache::lonhtmlcommon::start_pick_box()
3902: .&Apache::lonhtmlcommon::row_title(
3903: '<label for="ANSWER_TYPE_forminput">'
3904: .&mt('Print Answers')
3905: .'</label>'
3906: )
3907: );
1.161 bowersj2 3908: $paramHash = Apache::lonhelper::getParamHash();
1.162 sakharuk 3909: $paramHash->{'variable'} = 'ANSWER_TYPE';
3910: $helper->declareVar('ANSWER_TYPE');
1.161 bowersj2 3911: $paramHash->{CHOICES} = [
1.242 sakharuk 3912: ['Without Answers', 'yes'],
3913: ['With Answers', 'no'],
1.368 albertel 3914: ['Only Answers', 'only']
1.289 sakharuk 3915: ];
1.210 sakharuk 3916: Apache::lonhelper::dropdown->new();
1.544 bisitz 3917: &addMessage(&Apache::lonhtmlcommon::row_closure());
1.223 bowersj2 3918: $startedTable = 1;
1.556 foxr 3919:
3920: #
3921: # Select font size.
3922: #
3923:
3924: $helper->declareVar('fontsize');
3925: &addMessage(&Apache::lonhtmlcommon::row_title(&mt('Font Size')));
3926: my $xmlfrag = << "FONT_SELECTION";
3927:
3928:
3929: <dropdown variable='fontsize' multichoice='0', allowempty='0'>
3930: <defaultvalue>
3931: return 'normalsize';
3932: </defaultvalue>
3933: <choice computer='tiny'>Tiny</choice>
3934: <choice computer='sub/superscriptsize'>Script Size</choice>
3935: <choice computer='footnotesize'>Footnote Size</choice>
3936: <choice computer='small'>Small</choice>
3937: <choice computer='normalsize'>Normal (default)</choice>
3938: <choice computer='large'>larger than normal</choice>
3939: <choice computer='Large'>Even larger than normal</choice>
3940: <choice computer='LARGE'>Still larger than normal</choice>
3941: <choice computer='huge'>huge font size</choice>
3942: <choice computer='Huge'>Largest possible size</choice>
3943: </dropdown>
3944: FONT_SELECTION
3945: &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
3946: &addMessage(&Apache::lonhtmlcommon::row_closure(1));
1.161 bowersj2 3947: }
1.209 sakharuk 3948:
1.397 albertel 3949: if ($perm{'pav'}) {
1.223 bowersj2 3950: if (!$startedTable) {
1.497 www 3951: addMessage("<hr width='33%' /><table><tr><td align='right'>".
3952: '<label for="LATEX_TYPE_forminput">'.
3953: &mt('LaTeX mode').
3954: "</label>: </td><td>");
1.223 bowersj2 3955: $startedTable = 1;
3956: } else {
1.544 bisitz 3957: &addMessage(&Apache::lonhtmlcommon::row_title(
3958: '<label for="LATEX_TYPE_forminput">'
3959: .&mt('LaTeX mode')
3960: .'</label>'
3961: )
3962: );
1.223 bowersj2 3963: }
1.203 sakharuk 3964: $paramHash = Apache::lonhelper::getParamHash();
3965: $paramHash->{'variable'} = 'LATEX_TYPE';
3966: $helper->declareVar('LATEX_TYPE');
3967: if ($helper->{VARS}->{'construction'} eq '1') {
3968: $paramHash->{CHOICES} = [
1.223 bowersj2 3969: ['standard LaTeX mode', 'standard'],
3970: ['LaTeX batchmode', 'batchmode'], ];
1.203 sakharuk 3971: } else {
3972: $paramHash->{CHOICES} = [
1.223 bowersj2 3973: ['LaTeX batchmode', 'batchmode'],
3974: ['standard LaTeX mode', 'standard'] ];
1.203 sakharuk 3975: }
1.210 sakharuk 3976: Apache::lonhelper::dropdown->new();
1.218 sakharuk 3977:
1.544 bisitz 3978: &addMessage(&Apache::lonhtmlcommon::row_closure()
3979: .&Apache::lonhtmlcommon::row_title(
3980: '<label for="TABLE_CONTENTS_forminput">'
3981: .&mt('Print Table of Contents')
3982: .'</label>'
3983: )
3984: );
1.209 sakharuk 3985: $paramHash = Apache::lonhelper::getParamHash();
3986: $paramHash->{'variable'} = 'TABLE_CONTENTS';
3987: $helper->declareVar('TABLE_CONTENTS');
3988: $paramHash->{CHOICES} = [
1.223 bowersj2 3989: ['No', 'no'],
3990: ['Yes', 'yes'] ];
1.210 sakharuk 3991: Apache::lonhelper::dropdown->new();
1.544 bisitz 3992: &addMessage(&Apache::lonhtmlcommon::row_closure());
1.214 sakharuk 3993:
1.220 sakharuk 3994: if (not $helper->{VARS}->{'construction'}) {
1.545 bisitz 3995: &addMessage(&Apache::lonhtmlcommon::row_title(
3996: '<label for="TABLE_INDEX_forminput">'
3997: .&mt('Print Index')
3998: .'</label>'
3999: )
4000: );
1.220 sakharuk 4001: $paramHash = Apache::lonhelper::getParamHash();
4002: $paramHash->{'variable'} = 'TABLE_INDEX';
4003: $helper->declareVar('TABLE_INDEX');
4004: $paramHash->{CHOICES} = [
1.223 bowersj2 4005: ['No', 'no'],
4006: ['Yes', 'yes'] ];
1.220 sakharuk 4007: Apache::lonhelper::dropdown->new();
1.545 bisitz 4008: &addMessage(&Apache::lonhtmlcommon::row_closure());
4009: &addMessage(&Apache::lonhtmlcommon::row_title(
4010: '<label for="PRINT_DISCUSSIONS_forminput">'
4011: .&mt('Print Discussions')
4012: .'</label>'
4013: )
4014: );
1.309 sakharuk 4015: $paramHash = Apache::lonhelper::getParamHash();
4016: $paramHash->{'variable'} = 'PRINT_DISCUSSIONS';
4017: $helper->declareVar('PRINT_DISCUSSIONS');
4018: $paramHash->{CHOICES} = [
4019: ['No', 'no'],
4020: ['Yes', 'yes'] ];
4021: Apache::lonhelper::dropdown->new();
1.545 bisitz 4022: &addMessage(&Apache::lonhtmlcommon::row_closure());
1.372 foxr 4023:
1.511 foxr 4024: # Prompt for printing annotations too.
4025:
1.545 bisitz 4026: &addMessage(&Apache::lonhtmlcommon::row_title(
4027: '<label for="PRINT_ANNOTATIONS_forminput">'
4028: .&mt('Print Annotations')
4029: .'</label>'
4030: )
4031: );
1.511 foxr 4032: $paramHash = Apache::lonhelper::getParamHash();
4033: $paramHash->{'variable'} = "PRINT_ANNOTATIONS";
4034: $helper->declareVar("PRINT_ANNOTATIONS");
4035: $paramHash->{CHOICES} = [
4036: ['No', 'no'],
4037: ['Yes', 'yes']];
4038: Apache::lonhelper::dropdown->new();
1.545 bisitz 4039: &addMessage(&Apache::lonhtmlcommon::row_closure());
1.511 foxr 4040:
1.545 bisitz 4041: &addMessage(&Apache::lonhtmlcommon::row_title(&mt('Foils')));
1.397 albertel 4042: $paramHash = Apache::lonhelper::getParamHash();
4043: $paramHash->{'multichoice'} = "true";
4044: $paramHash->{'allowempty'} = "true";
4045: $paramHash->{'variable'} = "showallfoils";
1.555 bisitz 4046: $paramHash->{'CHOICES'} = [ [&mt('Show All Foils'), "1"] ];
1.397 albertel 4047: Apache::lonhelper::choices->new();
1.545 bisitz 4048: &addMessage(&Apache::lonhtmlcommon::row_closure(1));
1.220 sakharuk 4049: }
1.219 sakharuk 4050:
1.230 albertel 4051: if ($helper->{'VARS'}->{'construction'}) {
1.505 albertel 4052: my $stylevalue='$Apache::lonnet::env{"construct.style"}';
1.497 www 4053: my $randseedtext=&mt("Use random seed");
4054: my $stylefiletext=&mt("Use style file");
1.506 albertel 4055: my $selectfiletext=&mt("Select style file");
1.497 www 4056:
1.544 bisitz 4057: my $xmlfrag .= '<message>'
4058: .&Apache::lonhtmlcommon::row_title('<label for="curseed_forminput">'
4059: .$randseedtext
4060: .'</label>'
4061: )
4062: .'</message>
4063: <string variable="curseed" size="15" maxlength="15">
4064: <defaultvalue>
4065: return '.$helper->{VARS}->{'curseed'}.';
4066: </defaultvalue>'
4067: .'</string>'
4068: .'<message>'
4069: .&Apache::lonhtmlcommon::row_closure()
4070: .&Apache::lonhtmlcommon::row_title('<label for="style_file">'
4071: .$stylefiletext
4072: .'</label>'
4073: )
4074: .'</message>
1.504 albertel 4075: <string variable="style_file" size="40">
1.544 bisitz 4076: <defaultvalue>
4077: return '.$stylevalue.';
4078: </defaultvalue>
4079: </string><message> '
4080: .qq|<a href="javascript:openbrowser('helpform','style_file_forminput','sty')">|
4081: .$selectfiletext.'</a>'
4082: .&Apache::lonhtmlcommon::row_closure()
1.555 bisitz 4083: .&Apache::lonhtmlcommon::row_title(&mt('Show All Foils'))
1.544 bisitz 4084: .'</message>
1.371 foxr 4085: <choices allowempty="1" multichoice="true" variable="showallfoils">
1.544 bisitz 4086: <choice computer="1"> </choice>
4087: </choices>'
4088: .'<message>'
4089: .&Apache::lonhtmlcommon::row_closure()
4090: .'</message>';
1.230 albertel 4091: &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
1.512 foxr 4092:
4093:
1.544 bisitz 4094: &addMessage(&Apache::lonhtmlcommon::row_title(&mt('Problem Type')));
1.512 foxr 4095: #
4096: # Initial value from construction space:
4097: #
4098: if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) {
4099: $helper->{VARS}->{'probstatus'} = $env{'form.problemtype'}; # initial value
4100: }
1.518 foxr 4101: $xmlfrag = << "PROBTYPE";
4102: <dropdown variable="probstatus" multichoice="0" allowempty="0">
4103: <defaultvalue>
4104: return "$helper->{VARS}->{'probstatus'}";
4105: </defaultvalue>
4106: <choice computer="problem">Homework Problem</choice>
4107: <choice computer="exam">Exam Problem</choice>
4108: <choice computer="survey">Survey question</choice>
1.572 raeburn 4109: ,choice computer="anonsurvey"Anonymous survey question</choice>
1.518 foxr 4110: </dropdown>
4111: PROBTYPE
4112: &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
1.544 bisitz 4113: &addMessage(&Apache::lonhtmlcommon::row_closure(1));
1.512 foxr 4114:
1.556 foxr 4115:
4116:
1.544 bisitz 4117: }
1.223 bowersj2 4118: }
1.264 sakharuk 4119:
4120:
4121:
1.218 sakharuk 4122:
1.223 bowersj2 4123: if ($startedTable) {
1.544 bisitz 4124: &addMessage(&Apache::lonhtmlcommon::end_pick_box());
1.215 sakharuk 4125: }
1.161 bowersj2 4126:
1.131 bowersj2 4127: Apache::lonprintout::page_format_state->new("FORMAT");
4128:
1.144 bowersj2 4129: # Generate the PAGESIZE state which will offer the user the margin
4130: # choices if they select one column
4131: Apache::lonhelper::state->new("PAGESIZE", "Set Margins");
4132: Apache::lonprintout::page_size_state->new('pagesize', 'FORMAT', 'FINAL');
4133:
4134:
1.131 bowersj2 4135: $helper->process();
4136:
1.416 foxr 4137:
1.131 bowersj2 4138: # MANUAL BAILOUT CONDITION:
4139: # If we're in the "final" state, bailout and return to handler
4140: if ($helper->{STATE} eq 'FINAL') {
4141: return $helper;
4142: }
1.130 sakharuk 4143:
1.583.2.3 raeburn 4144: my $footer;
1.395 www 4145: if ($helper->{STATE} eq 'START') {
1.583.2.3 raeburn 4146: my $prtspool=$r->dir_config('lonPrtDir');
4147: $footer = &recently_generated($prtspool);
1.395 www 4148: }
1.583.2.3 raeburn 4149: $r->print($helper->display($footer));
1.333 albertel 4150: &Apache::lonhelper::unregisterHelperTags();
1.115 bowersj2 4151:
4152: return OK;
4153: }
4154:
1.1 www 4155:
4156: 1;
1.119 bowersj2 4157:
4158: package Apache::lonprintout::page_format_state;
4159:
4160: =pod
4161:
1.131 bowersj2 4162: =head1 Helper element: page_format_state
4163:
4164: See lonhelper.pm documentation for discussion of the helper framework.
1.119 bowersj2 4165:
1.131 bowersj2 4166: Apache::lonprintout::page_format_state is an element that gives the
4167: user an opportunity to select the page layout they wish to print
4168: with: Number of columns, portrait/landscape, and paper size. If you
4169: want to change the paper size choices, change the @paperSize array
4170: contents in this package.
1.119 bowersj2 4171:
1.131 bowersj2 4172: page_format_state is always directly invoked in lonprintout.pm, so there
4173: is no tag interface. You actually pass parameters to the constructor.
1.119 bowersj2 4174:
4175: =over 4
4176:
1.131 bowersj2 4177: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
1.119 bowersj2 4178:
4179: =back
4180:
4181: =cut
4182:
1.131 bowersj2 4183: use Apache::lonhelper;
1.119 bowersj2 4184:
4185: no strict;
1.131 bowersj2 4186: @ISA = ("Apache::lonhelper::element");
1.119 bowersj2 4187: use strict;
1.266 sakharuk 4188: use Apache::lonlocal;
1.373 albertel 4189: use Apache::lonnet;
1.119 bowersj2 4190:
4191: my $maxColumns = 2;
1.376 albertel 4192: # it'd be nice if these all worked
4193: #my @paperSize = ("letter [8 1/2x11 in]", "legal [8 1/2x14 in]",
4194: # "tabloid (ledger) [11x17 in]", "executive [7 1/2x10 in]",
4195: # "a2 [420x594 mm]", "a3 [297x420 mm]", "a4 [210x297 mm]",
4196: # "a5 [148x210 mm]", "a6 [105x148 mm]" );
1.326 sakharuk 4197: my @paperSize = ("letter [8 1/2x11 in]", "legal [8 1/2x14 in]",
1.376 albertel 4198: "a4 [210x297 mm]");
1.119 bowersj2 4199:
4200: # Tentative format: Orientation (L = Landscape, P = portrait) | Colnum |
4201: # Paper type
4202:
4203: sub new {
1.131 bowersj2 4204: my $self = Apache::lonhelper::element->new();
1.119 bowersj2 4205:
1.135 bowersj2 4206: shift;
4207:
1.131 bowersj2 4208: $self->{'variable'} = shift;
1.134 bowersj2 4209: my $helper = Apache::lonhelper::getHelper();
1.135 bowersj2 4210: $helper->declareVar($self->{'variable'});
1.131 bowersj2 4211: bless($self);
1.119 bowersj2 4212: return $self;
4213: }
4214:
4215: sub render {
4216: my $self = shift;
1.131 bowersj2 4217: my $helper = Apache::lonhelper::getHelper();
1.119 bowersj2 4218: my $result = '';
1.131 bowersj2 4219: my $var = $self->{'variable'};
1.266 sakharuk 4220: my $PageLayout=&mt('Page layout');
4221: my $NumberOfColumns=&mt('Number of columns');
4222: my $PaperType=&mt('Paper type');
1.506 albertel 4223: my $landscape=&mt('Landscape');
4224: my $portrait=&mt('Portrait');
1.556 foxr 4225:
4226:
1.544 bisitz 4227: $result.='<h3>'.&mt('Layout Options').'</h3>'
4228: .&Apache::loncommon::start_data_table()
4229: .&Apache::loncommon::start_data_table_header_row()
4230: .'<th>'.$PageLayout.'</th>'
4231: .'<th>'.$NumberOfColumns.'</th>'
4232: .'<th>'.$PaperType.'</th>'
4233: .&Apache::loncommon::end_data_table_header_row()
4234: .&Apache::loncommon::start_data_table_row()
4235: .'<td>'
4236: .'<label><input type="radio" name="'.${var}.'.layout" value="L" />'.$landscape.'</label><br />'
4237: .'<label><input type="radio" name="'.${var}.'.layout" value="P" checked="checked" />'.$portrait.'</label>'
4238: .'</td>';
1.119 bowersj2 4239:
1.544 bisitz 4240: $result.='<td align="center">'
4241: .'<select name="'.${var}.'.cols">';
1.119 bowersj2 4242:
4243: my $i;
4244: for ($i = 1; $i <= $maxColumns; $i++) {
1.144 bowersj2 4245: if ($i == 2) {
1.553 bisitz 4246: $result .= '<option value="'.$i.'" selected="selected">'.$i.'</option>'."\n";
1.119 bowersj2 4247: } else {
1.553 bisitz 4248: $result .= '<option value="'.$i.'">'.$i.'</option>'."\n";
1.119 bowersj2 4249: }
4250: }
4251:
4252: $result .= "</select></td><td>\n";
4253: $result .= "<select name='${var}.paper'>\n";
4254:
1.373 albertel 4255: my %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'});
1.398 albertel 4256: my $DefaultPaperSize=lc($parmhash{'default_paper_size'});
4257: $DefaultPaperSize=~s/\s//g;
1.304 sakharuk 4258: if ($DefaultPaperSize eq '') {$DefaultPaperSize='letter';}
1.119 bowersj2 4259: $i = 0;
4260: foreach (@paperSize) {
1.326 sakharuk 4261: $_=~/(\w+)/;
4262: my $papersize=$1;
1.304 sakharuk 4263: if ($paperSize[$i]=~/$DefaultPaperSize/) {
1.553 bisitz 4264: $result .= '<option selected="selected" value="'.$papersize.'">'.$paperSize[$i].'</option>'."\n";
1.119 bowersj2 4265: } else {
1.553 bisitz 4266: $result .= '<option value="'.$papersize.'">'.$paperSize[$i].'</option>'."\n";
1.119 bowersj2 4267: }
4268: $i++;
4269: }
1.539 onken 4270: $result .= <<HTML;
4271: </select>
4272: </td>
4273: HTML
1.544 bisitz 4274: $result.=&Apache::loncommon::end_data_table_row()
4275: .&Apache::loncommon::end_data_table();
1.539 onken 4276:
1.119 bowersj2 4277: return $result;
1.135 bowersj2 4278: }
4279:
4280: sub postprocess {
4281: my $self = shift;
4282:
4283: my $var = $self->{'variable'};
1.136 bowersj2 4284: my $helper = Apache::lonhelper->getHelper();
1.135 bowersj2 4285: $helper->{VARS}->{$var} =
1.373 albertel 4286: $env{"form.$var.layout"} . '|' . $env{"form.$var.cols"} . '|' .
1.539 onken 4287: $env{"form.$var.paper"} . '|' . $env{"form.$var.pdfFormFields"};
1.135 bowersj2 4288: return 1;
1.119 bowersj2 4289: }
4290:
4291: 1;
1.144 bowersj2 4292:
4293: package Apache::lonprintout::page_size_state;
4294:
4295: =pod
4296:
4297: =head1 Helper element: page_size_state
4298:
4299: See lonhelper.pm documentation for discussion of the helper framework.
4300:
4301: Apache::lonprintout::page_size_state is an element that gives the
4302: user the opportunity to further refine the page settings if they
4303: select a single-column page.
4304:
4305: page_size_state is always directly invoked in lonprintout.pm, so there
4306: is no tag interface. You actually pass parameters to the constructor.
4307:
4308: =over 4
4309:
4310: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
4311:
4312: =back
4313:
4314: =cut
4315:
4316: use Apache::lonhelper;
1.373 albertel 4317: use Apache::lonnet;
1.144 bowersj2 4318: no strict;
4319: @ISA = ("Apache::lonhelper::element");
4320: use strict;
4321:
4322:
4323:
4324: sub new {
4325: my $self = Apache::lonhelper::element->new();
4326:
4327: shift; # disturbs me (probably prevents subclassing) but works (drops
4328: # package descriptor)... - Jeremy
4329:
4330: $self->{'variable'} = shift;
4331: my $helper = Apache::lonhelper::getHelper();
4332: $helper->declareVar($self->{'variable'});
4333:
4334: # The variable name of the format element, so we can look into
4335: # $helper->{VARS} to figure out whether the columns are one or two
4336: $self->{'formatvar'} = shift;
4337:
1.463 foxr 4338:
1.144 bowersj2 4339: $self->{NEXTSTATE} = shift;
4340: bless($self);
1.467 foxr 4341:
1.144 bowersj2 4342: return $self;
4343: }
4344:
4345: sub render {
4346: my $self = shift;
4347: my $helper = Apache::lonhelper::getHelper();
4348: my $result = '';
4349: my $var = $self->{'variable'};
4350:
1.467 foxr 4351:
4352:
1.144 bowersj2 4353: if (defined $self->{ERROR_MSG}) {
1.464 albertel 4354: $result .= '<br /><span class="LC_error">' . $self->{ERROR_MSG} . '</span><br />';
1.144 bowersj2 4355: }
4356:
1.438 foxr 4357: my $format = $helper->{VARS}->{$self->{'formatvar'}};
1.463 foxr 4358:
4359: # Use format to get sensible defaults for the margins:
4360:
4361:
4362: my ($laystyle, $cols, $papersize) = split(/\|/, $format);
4363: ($papersize) = split(/ /, $papersize);
4364:
1.559 foxr 4365: $laystyle = &Apache::lonprintout::map_laystyle($laystyle);
1.463 foxr 4366:
4367:
4368:
1.464 albertel 4369: my %size;
4370: ($size{'width_and_units'},
4371: $size{'height_and_units'},
4372: $size{'margin_and_units'})=
4373: &Apache::lonprintout::page_format($papersize, $laystyle, $cols);
1.463 foxr 4374:
1.464 albertel 4375: foreach my $dimension ('width','height','margin') {
4376: ($size{$dimension},$size{$dimension.'_unit'}) =
4377: split(/ +/, $size{$dimension.'_and_units'},2);
4378:
4379: foreach my $unit ('cm','in') {
4380: $size{$dimension.'_options'} .= '<option ';
4381: if ($size{$dimension.'_unit'} eq $unit) {
4382: $size{$dimension.'_options'} .= 'selected="selected" ';
4383: }
4384: $size{$dimension.'_options'} .= '>'.$unit.'</option>';
4385: }
1.438 foxr 4386: }
4387:
1.470 foxr 4388: # Adjust margin for LaTeX margin: .. requires units == cm or in.
4389:
4390: if ($size{'margin_unit'} eq 'in') {
4391: $size{'margin'} += 1;
4392: } else {
4393: $size{'margin'} += 2.54;
4394: }
1.548 bisitz 4395: my %lt = &Apache::lonlocal::texthash(
4396: 'format' => 'How should each column be formatted?',
4397: 'width' => 'Width',
4398: 'height' => 'Height',
4399: 'margin' => 'Left Margin'
4400: );
4401:
4402: $result .= '<p>'.$lt{'format'}.'</p>'
4403: .&Apache::lonhtmlcommon::start_pick_box()
4404: .&Apache::lonhtmlcommon::row_title($lt{'width'})
4405: .'<input type="text" name="'.$var.'.width" value="'.$size{'width'}.'" size="4" />'
4406: .'<select name="'.$var.'.widthunit">'
4407: .$size{'width_options'}
4408: .'</select>'
4409: .&Apache::lonhtmlcommon::row_closure()
4410: .&Apache::lonhtmlcommon::row_title($lt{'height'})
4411: .'<input type="text" name="'.$var.'.height" value="'.$size{'height'}.'" size="4" />'
4412: .'<select name="'.$var.'.heightunit">'
4413: .$size{'height_options'}
4414: .'</select>'
4415: .&Apache::lonhtmlcommon::row_closure()
4416: .&Apache::lonhtmlcommon::row_title($lt{'margin'})
4417: .'<input type="text" name="'.$var.'.lmargin" value="'.$size{'margin'}.'" size="4" />'
4418: .'<select name="'.$var.'.lmarginunit">'
4419: .$size{'margin_options'}
4420: .'</select>'
4421: .&Apache::lonhtmlcommon::row_closure(1)
4422: .&Apache::lonhtmlcommon::end_pick_box();
4423: # <p>Hint: Some instructors like to leave scratch space for the student by
4424: # making the width much smaller than the width of the page.</p>
1.144 bowersj2 4425:
4426: return $result;
4427: }
4428:
1.470 foxr 4429:
1.144 bowersj2 4430: sub preprocess {
4431: my $self = shift;
4432: my $helper = Apache::lonhelper::getHelper();
4433:
4434: my $format = $helper->{VARS}->{$self->{'formatvar'}};
1.467 foxr 4435:
4436: # If the user does not have 'pav' privilege, set default widths and
4437: # on to the next state right away.
4438: #
4439: if (!$perm{'pav'}) {
4440: my $var = $self->{'variable'};
4441: my $format = $helper->{VARS}->{$self->{'formatvar'}};
4442:
4443: my ($laystyle, $cols, $papersize) = split(/\|/, $format);
4444: ($papersize) = split(/ /, $papersize);
4445:
4446:
1.560 foxr 4447: $laystyle = &Apache::lonprintout::map_laystyle($laystyle);
1.559 foxr 4448:
1.467 foxr 4449: # Figure out some good defaults for the print out and set them:
4450:
4451: my %size;
4452: ($size{'width'},
4453: $size{'height'},
4454: $size{'lmargin'})=
4455: &Apache::lonprintout::page_format($papersize, $laystyle, $cols);
4456:
4457: foreach my $dim ('width', 'height', 'lmargin') {
4458: my ($value, $units) = split(/ /, $size{$dim});
1.470 foxr 4459:
1.467 foxr 4460: $helper->{VARS}->{"$var.".$dim} = $value;
4461: $helper->{VARS}->{"$var.".$dim.'unit'} = $units;
4462:
4463: }
4464:
4465:
4466: # Transition to the next state
4467:
4468: $helper->changeState($self->{NEXTSTATE});
4469: }
1.144 bowersj2 4470:
4471: return 1;
4472: }
4473:
4474: sub postprocess {
4475: my $self = shift;
4476:
4477: my $var = $self->{'variable'};
4478: my $helper = Apache::lonhelper->getHelper();
1.373 albertel 4479: my $width = $helper->{VARS}->{$var .'.width'} = $env{"form.${var}.width"};
4480: my $height = $helper->{VARS}->{$var .'.height'} = $env{"form.${var}.height"};
4481: my $lmargin = $helper->{VARS}->{$var .'.lmargin'} = $env{"form.${var}.lmargin"};
4482: $helper->{VARS}->{$var .'.widthunit'} = $env{"form.${var}.widthunit"};
4483: $helper->{VARS}->{$var .'.heightunit'} = $env{"form.${var}.heightunit"};
4484: $helper->{VARS}->{$var .'.lmarginunit'} = $env{"form.${var}.lmarginunit"};
1.144 bowersj2 4485:
4486: my $error = '';
4487:
4488: # /^-?[0-9]+(\.[0-9]*)?$/ -> optional minus, at least on digit, followed
4489: # by an optional period, followed by digits, ending the string
4490:
1.464 albertel 4491: if ($width !~ /^-?[0-9]*(\.[0-9]*)?$/) {
1.144 bowersj2 4492: $error .= "Invalid width; please type only a number.<br />\n";
4493: }
1.464 albertel 4494: if ($height !~ /^-?[0-9]*(\.[0-9]*)?$/) {
1.144 bowersj2 4495: $error .= "Invalid height; please type only a number.<br />\n";
4496: }
1.464 albertel 4497: if ($lmargin !~ /^-?[0-9]*(\.[0-9]*)?$/) {
1.144 bowersj2 4498: $error .= "Invalid left margin; please type only a number.<br />\n";
1.470 foxr 4499: } else {
4500: # Adjust for LaTeX 1.0 inch margin:
4501:
4502: if ($env{"form.${var}.lmarginunit"} eq "in") {
4503: $helper->{VARS}->{$var.'.lmargin'} = $lmargin - 1;
4504: } else {
4505: $helper->{VARS}->{$var.'.lmargin'} = $lmargin - 2.54;
4506: }
1.144 bowersj2 4507: }
4508:
4509: if (!$error) {
4510: Apache::lonhelper::getHelper()->changeState($self->{NEXTSTATE});
4511: return 1;
4512: } else {
4513: $self->{ERROR_MSG} = $error;
4514: return 0;
4515: }
4516: }
4517:
4518:
1.119 bowersj2 4519:
1.1 www 4520: __END__
1.6 sakharuk 4521:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>