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