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