![]() ![]() | ![]() |
- lots of \w -> probper regexp replacements
1: # The LearningOnline Network with CAPA 2: # Tags Default Definition Module 3: # 4: # $Id: londefdef.pm,v 1.345 2006/12/05 02:55:54 albertel Exp $ 5: # 6: # 7: # Copyright Michigan State University Board of Trustees 8: # 9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA). 10: # 11: # LON-CAPA is free software; you can redistribute it and/or modify 12: # it under the terms of the GNU General Public License as published by 13: # the Free Software Foundation; either version 2 of the License, or 14: # (at your option) any later version. 15: # 16: # LON-CAPA is distributed in the hope that it will be useful, 17: # but WITHOUT ANY WARRANTY; without even the implied warranty of 18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19: # GNU General Public License for more details. 20: # 21: # You should have received a copy of the GNU General Public License 22: # along with LON-CAPA; if not, write to the Free Software 23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24: # 25: # /home/httpd/html/adm/gpl.txt 26: # 27: # http://www.lon-capa.org/ 28: ## Copyright for TtHfunc and TtMfunc by Ian Hutchinson. 29: # TtHfunc and TtMfunc (the "Code") may be compiled and linked into 30: # binary executable programs or libraries distributed by the 31: # Michigan State University (the "Licensee"), but any binaries so 32: # distributed are hereby licensed only for use in the context 33: # of a program or computational system for which the Licensee is the 34: # primary author or distributor, and which performs substantial 35: # additional tasks beyond the translation of (La)TeX into HTML. 36: # The C source of the Code may not be distributed by the Licensee 37: # to any other parties under any circumstances. 38: # 39: 40: package Apache::londefdef; 41: 42: use Apache::lonnet; 43: use strict; 44: use Apache::lonxml; 45: use Apache::File(); 46: use Image::Magick; 47: use Apache::lonmenu(); 48: use Apache::lonmeta(); 49: use Apache::Constants qw(:common); 50: use File::Basename; 51: use LONCAPA(); 52: # use Data::Dumper; 53: 54: BEGIN { 55: 56: &Apache::lonxml::register('Apache::londefdef',('a','abbr','acronym','accessrule','address','allow','applet','area','b','base','basefont','bgo','bgsound','big','blink','blockquote','blankspace','body','br','button','caption','center','cite','code','col','colgroup','dd','del','dfn','dir','div','dl','dt','em','embed','externallink','fieldset','font','form','frame','frameset','h1','h2','h3','h4','h5','h6','head','hr','html','i','iframe','img','input','ins','insert','isindex','kbd','keygen','label','layer','legend','li','link','m','map','marquee','menu','meta','multicol','nobr','noembed','noframes','nolayer','noscript','object','ol','optgroup','option','output','p','param','pre','q','s','samp','select','server','small','spacer','span','strike','strong','sub','sup','table','tbody','td','textarea','tfoot','th','thead','title','tr','tt','tthoption','u','ul','var','wbr','hideweboutput')); 57: 58: } 59: 60: # 61: # Dumps all elements of the table structure. 62: # Need this 'cause evidently when given an array, Data::Dumper only seems 63: # to dump element 0. 64: # 65: #sub debug_dump_table { 66: # my $lastrow = $#Apache::londefdef::table; 67: # &Apache::lonnet::logthis("Dumping table: Last row index: $lastrow"); 68: # my $row; 69: # for ($row =0; $row <= $lastrow; $row++ ) { 70: # my $text = Dumper($Apache::londefdef::table[$row]); 71: # &Apache::lonnet::logthis("table [ $row ]".$text); 72: # } 73: #} 74: sub initialize_londefdef { 75: $Apache::londefdef::TD_redirection=0; 76: @Apache::londefdef::table = (); 77: $Apache::londefdef::select=0; 78: undef(@Apache::londefdef::description); 79: @Apache::londefdef::DD=(0); 80: @Apache::londefdef::DT=(0); 81: @Apache::londefdef::seenDT=(0); 82: $Apache::londefdef::list_index=0; 83: undef($Apache::londefdef::head); 84: undef($Apache::londefdef::title); 85: } 86: 87: #======================= TAG SUBROUTINES ===================== 88: #-- <output> 89: sub start_output { 90: my ($target) = @_; 91: if ($target eq 'meta') { $Apache::lonxml::metamode--; } 92: return ''; 93: } 94: sub end_output { 95: my ($target) = @_; 96: if ($target eq 'meta') { $Apache::lonxml::metamode++; } 97: return ''; 98: } 99: #-- <m> tag 100: sub start_m { 101: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; 102: my $currentstring = ''; 103: my $inside = &Apache::lonxml::get_all_text_unbalanced("/m",$parser); 104: if ($target eq 'web' || $target eq 'analyze') { 105: &Apache::lonxml::debug("M is starting with:$inside:"); 106: my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval); 107: if ($eval eq 'on') { 108: $inside=&Apache::run::evaluate($inside,$safeeval,$$parstack[-1]); 109: #&Apache::lonxml::debug("M is evaulated to:$inside:"); 110: } 111: my $tex = $inside; 112: my $display=&Apache::lonxml::get_param('display',$parstack,$safeeval); 113: $currentstring = &Apache::lontexconvert::converted(\$inside,$display); 114: if ($Apache::lontexconvert::errorstring) { 115: my $errormsg='<pre>'.&HTML::Entities::encode($Apache::lontexconvert::errorstring,'<>&"').'</pre> occured while attempting to convert this TeX: <pre>'; 116: $tex = &HTML::Entities::encode($tex,'<>&"'); 117: my ($linenumber) = 118: ($Apache::lontexconvert::errorstring =~ /Line (\d+)/); 119: if (defined($linenumber)) { 120: my @tex=split("\n",$tex); 121: $tex[$linenumber]='<b><font color="red">'. 122: $tex[$linenumber].'</font></b>'; 123: $tex=join("\n",@tex); 124: } 125: &Apache::lonxml::warning($errormsg.$tex.'</pre>'); 126: $Apache::lontexconvert::errorstring=''; 127: } 128: #&Apache::lonxml::debug("M is ends with:$currentstring:"); 129: $Apache::lonxml::post_evaluate=0; 130: } elsif ($target eq 'tex') { 131: $currentstring = $inside; 132: my $eval=&Apache::lonxml::get_param('eval',$parstack,$safeeval); 133: if ($eval eq 'on') { 134: $currentstring=&Apache::run::evaluate($currentstring,$safeeval,$$parstack[-1]); 135: } 136: if ($currentstring=~/^(\s*\\\\\s*)*$/) {$currentstring = ' \vskip 0 mm ';} 137: # detect simple math mode entry exits, and convert them 138: # to use \ensuremath 139: if ($currentstring=~/^\s*\$[^\$].*[^\$]\$\s*$/) { 140: $currentstring=~s/^(\s*)\$/$1/; 141: $currentstring=~s/\$(\s*)$/$1/; 142: $currentstring='\ensuremath{'.$currentstring.'}'; 143: } 144: $Apache::lonxml::post_evaluate=0; 145: } 146: return $currentstring; 147: } 148: 149: sub end_m { 150: my ($target,$token) = @_; 151: my $currentstring = ''; 152: if ($target eq 'tex') { 153: $currentstring = ""; 154: } 155: return $currentstring; 156: } 157: 158: sub start_tthoption { 159: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; 160: my $result; 161: if ($target eq 'web' || $target eq 'webgrade') { 162: my $inside = &Apache::lonxml::get_all_text("/tthoption",$parser, 163: $style); 164: $inside=~s/^\s*//; 165: if ($env{'browser.mathml'}) { 166: &tth::ttmoptions($inside); 167: } else { 168: &tth::tthoptions($inside); 169: } 170: } 171: return $result; 172: } 173: 174: sub end_tthoption { 175: my ($target,$token) = @_; 176: my $result; 177: return $result; 178: } 179: 180: #-- <html> tag (end tag optional) 181: sub start_html { 182: my ($target,$token) = @_; 183: my $currentstring = ''; 184: if ($target eq 'web' || $target eq 'edit' || $target eq 'webgrade' ) { 185: # start_body() takes care of emitting the <html> 186: } elsif ($target eq 'tex') { 187: $currentstring .= 188: '\documentclass[letterpaper,twoside]{article}\raggedbottom'; 189: if (($env{'form.latex_type'}=~'batchmode') || 190: (!$env{'request.role.adv'})) {$currentstring .='\batchmode';} 191: $currentstring .= '\newcommand{\keephidden}[1]{}'. 192: '\renewcommand{\deg}{$^{\circ}$}'. 193: '\usepackage{multirow}'. 194: '\usepackage{longtable}'. 195: '\usepackage{textcomp}'. 196: '\usepackage{makeidx}'. 197: '\usepackage[dvips]{graphicx}'. 198: '\usepackage{wrapfig}'. 199: '\usepackage{picins}'. 200: '\usepackage{epsfig}'. 201: '\usepackage{calc}'. 202: '\usepackage{amsmath}'. 203: '\usepackage{amssymb}'. 204: '\usepackage{amsfonts}'. 205: '\usepackage{amsthm}'. 206: '\usepackage{amscd}'. 207: '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}'. 208: '\renewenvironment{theindex}{\begin{list}{}{{\vskip 1mm \noindent \large\textbf{Index}} \newline \setlength{\rightmargin}{0in}\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.01in}\setlength{\itemsep}{0.1in}\setlength{\parsep}{-0.02in}\setlength{\belowdisplayskip}{0.01in}\setlength{\abovedisplayskip}{0.01in}\setlength{\abovedisplayshortskip}{-0.04in}\setlength{\belowdisplayshortskip}{0.01in}}}{\end{list}}'; 209: } 210: return $currentstring; 211: } 212: 213: sub end_html { 214: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 215: my $currentstring = ''; 216: if ($target eq 'web' || $target eq 'webgrade') { 217: # end_body takes care of the </html> 218: } 219: return $currentstring; 220: } 221: 222: #-- <head> tag (end tag optional) 223: sub start_head { 224: my ($target,$token) = @_; 225: my $currentstring = ''; 226: if ($target eq 'web' || $target eq 'webgrade') { 227: &Apache::lonxml::startredirection(); 228: } 229: return $currentstring; 230: } 231: 232: sub end_head { 233: my ($target,$token) = @_; 234: my $currentstring = ''; 235: if (($target eq 'web' && $env{'request.state'} eq 'published') || 236: ($target eq 'webgrade' && $env{'request.state'} eq 'published')) { 237: # in case there is a </head> but no <head> 238: if ($Apache::lonxml::redirection) { 239: $Apache::londefdef::head = &Apache::lonxml::endredirection(); 240: } 241: } 242: return $currentstring; 243: } 244: 245: #-- <map> tag (end tag required) 246: sub start_map { 247: my ($target,$token) = @_; 248: my $currentstring = ''; 249: if ($target eq 'web' || $target eq 'webgrade') { 250: $currentstring = $token->[4]; 251: } 252: return $currentstring; 253: } 254: 255: sub end_map { 256: my ($target,$token) = @_; 257: my $currentstring = ''; 258: if ($target eq 'web' || $target eq 'webgrade') { 259: $currentstring = $token->[2]; 260: } 261: return $currentstring; 262: } 263: 264: #-- <select> tag (end tag required) 265: sub start_select { 266: my ($target,$token) = @_; 267: my $currentstring = ''; 268: if ($target eq 'web' || $target eq 'webgrade') { 269: $currentstring = $token->[4]; 270: } elsif ($target eq 'tex') { 271: $Apache::londefdef::select=0; 272: } 273: return $currentstring; 274: } 275: 276: sub end_select { 277: my ($target,$token) = @_; 278: my $currentstring = ''; 279: if ($target eq 'web' || $target eq 'webgrade') { 280: $currentstring = $token->[2]; 281: } 282: return $currentstring; 283: } 284: 285: #-- <option> tag (end tag optional) 286: sub start_option { 287: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 288: my $currentstring = ''; 289: if ($target eq 'web' || $target eq 'webgrade') { 290: $currentstring = $token->[4]; 291: } elsif ($target eq 'tex') { 292: $Apache::londefdef::select++; 293: if ($Apache::londefdef::select == 1) { 294: $currentstring='\noindent\fbox{'.&Apache::lonxml::get_param('value',$parstack,$safeeval).'}\keephidden{'; 295: } else { 296: $currentstring='\keephidden{'; 297: } 298: } 299: return $currentstring; 300: } 301: 302: sub end_option { 303: my ($target,$token) = @_; 304: my $currentstring = ''; 305: if ($target eq 'web' || $target eq 'webgrade') { 306: $currentstring = $token->[2]; 307: } elsif ($target eq 'tex') { 308: $currentstring='}'; 309: } 310: return $currentstring; 311: } 312: 313: #-- <input> tag (end tag forbidden) 314: sub start_input { 315: my ($target,$token) = @_; 316: my $currentstring = ''; 317: if ($target eq 'web' || $target eq 'webgrade') { 318: $currentstring = $token->[4]; 319: } 320: return $currentstring; 321: } 322: 323: sub end_input { 324: my ($target,$token) = @_; 325: my $currentstring = ''; 326: if ($target eq 'web' || $target eq 'webgrade') { 327: $currentstring = $token->[2]; 328: } 329: return $currentstring; 330: } 331: 332: #-- <textarea> tag (end tag required) 333: sub start_textarea { 334: my ($target,$token) = @_; 335: my $currentstring = ''; 336: if ($target eq 'web' || $target eq 'webgrade') { 337: $currentstring = $token->[4]; 338: } 339: return $currentstring; 340: } 341: 342: sub end_textarea { 343: my ($target,$token) = @_; 344: my $currentstring = ''; 345: if ($target eq 'web' || $target eq 'webgrade') { 346: $currentstring = $token->[2]; 347: } 348: return $currentstring; 349: } 350: 351: #-- <form> tag (end tag required) 352: sub start_form { 353: my ($target,$token) = @_; 354: my $currentstring = ''; 355: if ($target eq 'web' || $target eq 'webgrade') { 356: $currentstring = $token->[4]; 357: } 358: return $currentstring; 359: } 360: 361: sub end_form { 362: my ($target,$token) = @_; 363: my $currentstring = ''; 364: if ($target eq 'web' || $target eq 'webgrade') { 365: $currentstring = $token->[2]; 366: } 367: return $currentstring; 368: } 369: 370: #-- <title> tag (end tag required) 371: sub start_title { 372: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; 373: my $currentstring = ''; 374: if ($target eq 'web' || $target eq 'webgrade') { 375: $Apache::londefdef::title = 376: &Apache::lonxml::get_all_text('/title',$parser,$style); 377: } elsif ($target eq 'tex') { 378: $currentstring .= '\keephidden{Title of the document: ' 379: } 380: if ($target eq 'meta') { 381: $currentstring='<title>'; 382: &start_output($target); 383: } 384: return $currentstring; 385: } 386: 387: sub end_title { 388: my ($target,$token) = @_; 389: my $currentstring = ''; 390: if ($target eq 'web' || $target eq 'webgrade') { 391: # start_title takes care of swallowing the title 392: } elsif ($target eq 'tex') { 393: $currentstring .= '}'; 394: } 395: if ($target eq 'meta') { 396: &end_output($target); 397: $currentstring='</title>'; 398: } 399: return $currentstring; 400: } 401: 402: #-- <meta> tag (end tag forbidden) 403: sub start_meta { 404: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; 405: my $currentstring = ''; 406: if ($target eq 'web' || $target eq 'webgrade') { 407: my $args=''; 408: if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; } 409: if ($args eq '') { 410: &Apache::lonxml::get_all_text("/meta",$parser,$style); 411: } else { 412: $currentstring = $token->[4]; 413: } 414: } elsif ($target eq 'meta') { 415: unless (&Apache::lonxml::get_param 416: ('http-equiv',$parstack,$safeeval,undef,1)) { 417: my $name=$token->[2]->{'name'}; 418: $name=~tr/A-Z/a-z/; 419: $name=~s/\s/\_/gs; 420: $name=~s/\W//gs; 421: if ($name) { 422: $currentstring='<'.$name; 423: my $display=&Apache::lonxml::get_param 424: ('display',$parstack,$safeeval,undef,1); 425: if ($display) { 426: $display=~s/\"/\'/g; 427: $currentstring.=' display="'.$display.'"'; 428: } 429: $currentstring.='>'. 430: &Apache::lonxml::get_param 431: ('content',$parstack,$safeeval,undef,1). 432: '</'.$name.'>'; 433: } 434: my $display=&Apache::lonxml::get_param 435: ('display',$parstack,$safeeval,undef,1); 436: if ($display) { 437: $display=&HTML::Entities::encode($display,'<>&"'); 438: $currentstring.='<'.$name.'.display>'.$display. 439: '</'.$name.'.display>'; 440: } 441: } 442: } elsif ($target eq 'tex') { 443: my $content=&Apache::lonxml::get_param('content',$parstack,$safeeval); 444: my $name=&Apache::lonxml::get_param('name',$parstack,$safeeval); 445: if ((not defined $content) && (not defined $name)) { 446: &Apache::lonxml::startredirection(); 447: } 448: } 449: return $currentstring; 450: } 451: 452: sub end_meta { 453: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 454: my $currentstring = ''; 455: if ($target eq 'web' || $target eq 'webgrade') { 456: my $args=''; 457: if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; } 458: if ($args ne '') { 459: $currentstring = $token->[4]; 460: } 461: } elsif ($target eq 'tex') { 462: my $content=&Apache::lonxml::get_param('content',$parstack,$safeeval); 463: my $name=&Apache::lonxml::get_param('name',$parstack,$safeeval); 464: if ((not defined $content) && (not defined $name)) { 465: &Apache::lonxml::endredirection(); 466: } 467: } 468: return $currentstring; 469: } 470: 471: # accessrule 472: sub start_accessrule { 473: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; 474: my $currentstring = ''; 475: my $eff=&Apache::lonxml::get_param 476: ('effect',$parstack,$safeeval,undef,1); 477: my $realm=&Apache::lonxml::get_param 478: ('realm',$parstack,$safeeval,undef,1); 479: my $role=&Apache::lonxml::get_param 480: ('role',$parstack,$safeeval,undef,1); 481: $realm=~s/\s+//g; 482: $realm=~s/\//\_/g; 483: $realm=~s/^\_//; 484: $realm=~s/\W/\;/g; 485: $role=~s/\s+//g; 486: $role=~s/\//\_/g; 487: $role=~s/\W/\;/g; 488: if ($target eq 'web') { 489: my $args=''; 490: if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; } 491: if ($args eq '') { 492: &Apache::lonxml::get_all_text("/accessrule",$parser,$style); 493: } else { 494: $currentstring = $token->[4]; 495: } 496: } 497: if ($target eq 'meta') { 498: $currentstring='<rule>'.$eff.':'.$realm.':'.$role.'</rule>'; 499: } 500: return $currentstring; 501: } 502: 503: sub end_accessrule { 504: my ($target,$token,$tagstack,$parstack,$parser) = @_; 505: my $currentstring = ''; 506: if ($target eq 'web') { 507: my $args=''; 508: if ( $#$parstack > -1 ) { $args=$$parstack[$#$parstack]; } 509: if ($args ne '') { 510: $currentstring = $token->[4]; 511: } 512: } 513: return $currentstring; 514: } 515: 516: #-- <body> tag (end tag required) 517: sub start_body { 518: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 519: my $currentstring = ''; 520: 521: if ($target eq 'web' || $target eq 'webgrade') { 522: if ($Apache::lonhomework::parsing_a_problem) { 523: &Apache::lonxml::warning("<body> tag found inside of <problem> tag this can cause problems."); 524: return ''; 525: } 526: 527: if (&is_inside_of($tagstack, "head")) { 528: &end_head(@_); 529: } 530: $currentstring = 531: &Apache::loncommon::start_page($Apache::londefdef::title, 532: $Apache::londefdef::head, 533: {'add_entries' => $token->[2], 534: 'no_title' => 1, 535: 'force_register' => 1}); 536: 537: if ($env{'request.state'} ne 'published') { 538: $currentstring.=&Apache::lonmenu::constspaceform(); 539: $currentstring.=(<<EDITBUTTON); 540: <form method="post"> 541: <input type="submit" name="editmode" accesskey="e" value="Edit" /> 542: </form> 543: <br /> 544: EDITBUTTON 545: } 546: $currentstring.=&Apache::lonxml::message_location(); 547: } elsif ($target eq 'tex') { 548: $currentstring = '\begin{document}'; 549: } 550: return $currentstring; 551: } 552: 553: sub end_body { 554: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 555: my $currentstring = &end_p(); # Close off unclosed <p> 556: if ($target eq 'web' || $target eq 'webgrade') { 557: $currentstring .= &Apache::loncommon::end_page({'discussion' => 1}); 558: } elsif ($target eq 'tex') { 559: $currentstring .= '\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent \end{document}'; 560: } 561: return $currentstring; 562: } 563: 564: # \begin{center} causes a new paragprah spacing that looks odd inside 565: # of a table cell. Same at the end of a \center but with a slightly 566: # larger space .. hence center_correction and center_end_correction. 567: # 568: sub center_correction { return '\vspace*{-6 mm}'; } 569: sub center_end_correction { return '\vspace*{-7 mm}'; } 570: 571: #-- <center> tag (end tag required) 572: sub start_center { 573: my ($target,$token,$tagstack) = @_; 574: my $currentstring = &end_p(); # Close off any prior para. 575: if ($target eq 'web' || $target eq 'webgrade') { 576: $currentstring .= $token->[4]; 577: } elsif ($target eq 'tex') { 578: if (&is_inside_of($tagstack, "table")) { 579: $currentstring .= ¢er_correction(); 580: } 581: $currentstring .= '\begin{center}'; 582: } 583: return $currentstring; 584: } 585: 586: sub end_center { 587: my ($target,$token,$tagstack) = @_; 588: my $currentstring = ''; 589: if ($target eq 'web' || $target eq 'webgrade') { 590: $currentstring = $token->[2]; 591: } elsif ($target eq 'tex') { 592: $currentstring = '\end{center}'; 593: if (&is_inside_of($tagstack, "table")) { 594: $currentstring .= ¢er_end_correction(); 595: } 596: } 597: return $currentstring; 598: } 599: 600: #-- <b> tag (end tag required) 601: # NOTE: In TeX mode disables internal <p> 602: sub start_b { 603: my ($target,$token) = @_; 604: my $currentstring = ''; 605: if ($target eq 'web' || $target eq 'webgrade') { 606: $currentstring = $token->[4]; 607: } elsif ($target eq 'tex') { 608: &disable_para(); 609: $currentstring .= '\textbf{'; 610: } 611: return $currentstring; 612: } 613: 614: sub end_b { 615: my ($target,$token) = @_; 616: my $currentstring = ''; 617: if ($target eq 'web' || $target eq 'webgrade') { 618: $currentstring = $token->[2]; 619: } elsif ($target eq 'tex') { 620: &enable_para(); 621: $currentstring = '}'; 622: } 623: return $currentstring; 624: } 625: 626: #-- <strong> tag (end tag required) 627: # NOTE: in TeX mode disables internal <p> 628: sub start_strong { 629: my ($target,$token) = @_; 630: my $currentstring = ''; 631: if ($target eq 'web' || $target eq 'webgrade') { 632: $currentstring = $token->[4]; 633: } elsif ($target eq 'tex') { 634: &disable_para(); 635: $currentstring = '\textbf{'; 636: } 637: return $currentstring; 638: } 639: 640: sub end_strong { 641: my ($target,$token) = @_; 642: my $currentstring = ''; 643: if ($target eq 'web' || $target eq 'webgrade') { 644: $currentstring = $token->[2]; 645: } elsif ($target eq 'tex') { 646: &enable_para(); 647: $currentstring = '}'; 648: } 649: return $currentstring; 650: } 651: 652: #-- <h1> tag (end tag required) 653: sub start_h1 { 654: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 655: my $currentstring = &end_p(); # Close off any prior para. 656: if ($target eq 'web' || $target eq 'webgrade') { 657: $currentstring .= $token->[4]; 658: } elsif ($target eq 'tex') { 659: my $pre; 660: my $align=lc(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1)); 661: if ($align eq 'center') { 662: $pre='\begin{center}'; 663: } elsif ($align eq 'left') { 664: $pre='\rlap{'; 665: } elsif ($align eq 'right') { 666: $pre=' \hfill \llap{'; 667: } 668: my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0); 669: if (not defined $TeXsize) {$TeXsize="large";} 670: $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 671: } elsif ($target eq 'meta') { 672: $currentstring.='<subject>'; 673: &start_output($target); 674: } 675: return $currentstring; 676: } 677: 678: sub end_h1 { 679: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 680: my $currentstring = ''; 681: if ($target eq 'web' || $target eq 'webgrade') { 682: $currentstring .= $token->[2]; 683: } elsif ($target eq 'tex') { 684: my $post='\vskip 0 mm '; 685: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 686: if ($align eq 'center') { 687: $post='\end{center}'; 688: } elsif ($align eq 'left') { 689: $post='} \hfill'.'\vskip 0 mm '; 690: } elsif ($align eq 'right') { 691: $post='}'.'\vskip 0 mm '; 692: } 693: $currentstring .= '}}'.$post; 694: } elsif ($target eq 'meta') { 695: &end_output($target); 696: $currentstring='</subject>'; 697: } 698: return $currentstring; 699: } 700: 701: #-- <h2> tag 702: sub start_h2 { 703: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 704: my $currentstring = &end_p(); # Close off any prior para. 705: if ($target eq 'web' || $target eq 'webgrade') { 706: $currentstring .= $token->[4]; 707: } elsif ($target eq 'tex') { 708: my $pre; 709: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 710: if ($align eq 'center') { 711: $pre='\begin{center}'; 712: } elsif ($align eq 'left') { 713: $pre='\rlap{'; 714: } elsif ($align eq 'right') { 715: $pre=' \hfill \llap{'; 716: } 717: my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0); 718: if (not defined $TeXsize) {$TeXsize="large";} 719: $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 720: } 721: return $currentstring; 722: } 723: 724: sub end_h2 { 725: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 726: my $currentstring = ''; 727: if ($target eq 'web' || $target eq 'webgrade') { 728: $currentstring .= $token->[2]; 729: } elsif ($target eq 'tex') { 730: my $post='\vskip 0 mm '; 731: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 732: if ($align eq 'center') { 733: $post='\end{center}'; 734: } elsif ($align eq 'left') { 735: $post='} \hfill'.'\vskip 0 mm '; 736: } elsif ($align eq 'right') { 737: $post='}'.'\vskip 0 mm '; 738: } 739: $currentstring .= '}}'.$post; 740: } 741: return $currentstring; 742: } 743: 744: #-- <h3> tag 745: sub start_h3 { 746: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 747: my $currentstring = &end_p(); # Close off any prior para. 748: if ($target eq 'web' || $target eq 'webgrade') { 749: $currentstring .= $token->[4]; 750: } elsif ($target eq 'tex') { 751: my $pre; 752: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 753: if ($align eq 'center') { 754: $pre='\begin{center}'; 755: } elsif ($align eq 'left') { 756: $pre='\rlap{'; 757: } elsif ($align eq 'right') { 758: $pre=' \hfill \llap{'; 759: } 760: my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0); 761: if (not defined $TeXsize) {$TeXsize="large";} 762: $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 763: } 764: return $currentstring; 765: } 766: 767: sub end_h3 { 768: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 769: my $currentstring = ''; 770: if ($target eq 'web' || $target eq 'webgrade') { 771: $currentstring .= $token->[2]; 772: } elsif ($target eq 'tex') { 773: my $post='\vskip 0 mm '; 774: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 775: if ($align eq 'center') { 776: $post='\end{center}'; 777: } elsif ($align eq 'left') { 778: $post='} \hfill'.'\vskip 0 mm '; 779: } elsif ($align eq 'right') { 780: $post='}'.'\vskip 0 mm '; 781: } 782: $currentstring .= '}}'.$post; 783: } 784: return $currentstring; 785: } 786: 787: #-- <h4> tag 788: sub start_h4 { 789: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 790: my $currentstring = &end_p(); # Close off any prior para. 791: if ($target eq 'web' || $target eq 'webgrade') { 792: $currentstring .= $token->[4]; 793: } elsif ($target eq 'tex') { 794: my $pre; 795: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 796: if ($align eq 'center') { 797: $pre='\begin{center}'; 798: } elsif ($align eq 'left') { 799: $pre='\rlap{'; 800: } elsif ($align eq 'right') { 801: $pre=' \hfill \llap{'; 802: } 803: my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0); 804: if (not defined $TeXsize) {$TeXsize="large";} 805: $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 806: } 807: return $currentstring; 808: } 809: 810: sub end_h4 { 811: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 812: my $currentstring = ''; 813: if ($target eq 'web' || $target eq 'webgrade') { 814: $currentstring .= $token->[2]; 815: } elsif ($target eq 'tex') { 816: my $post='\vskip 0 mm '; 817: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 818: if ($align eq 'center') { 819: $post='\end{center}'; 820: } elsif ($align eq 'left') { 821: $post='} \hfill'.'\vskip 0 mm '; 822: } elsif ($align eq 'right') { 823: $post='}'.'\vskip 0 mm '; 824: } 825: $currentstring .= '}}'.$post; 826: } 827: return $currentstring; 828: } 829: 830: #-- <h5> tag 831: sub start_h5 { 832: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 833: my $currentstring = &end_p(); # Close off any prior paras. 834: if ($target eq 'web' || $target eq 'webgrade') { 835: $currentstring .= $token->[4]; 836: } elsif ($target eq 'tex') { 837: my $pre; 838: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 839: if ($align eq 'center') { 840: $pre='\begin{center}'; 841: } elsif ($align eq 'left') { 842: $pre='\rlap{'; 843: } elsif ($align eq 'right') { 844: $pre=' \hfill \llap{'; 845: } 846: my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0); 847: if (not defined $TeXsize) {$TeXsize="large";} 848: $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 849: } 850: return $currentstring; 851: } 852: 853: sub end_h5 { 854: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 855: my $currentstring = ''; 856: if ($target eq 'web' || $target eq 'webgrade') { 857: $currentstring .= $token->[2]; 858: } elsif ($target eq 'tex') { 859: my $post='\vskip 0 mm '; 860: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 861: if ($align eq 'center') { 862: $post='\end{center}'; 863: } elsif ($align eq 'left') { 864: $post='} \hfill'.'\vskip 0 mm '; 865: } elsif ($align eq 'right') { 866: $post='}'.'\vskip 0 mm '; 867: } 868: $currentstring .= '}}'.$post; 869: } 870: return $currentstring; 871: } 872: 873: #-- <h6> tag 874: sub start_h6 { 875: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 876: my $currentstring = &end_p(); # Close off any prior paras. 877: if ($target eq 'web' || $target eq 'webgrade') { 878: $currentstring .= $token->[4]; 879: } elsif ($target eq 'tex') { 880: my $pre; 881: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 882: if ($align eq 'center') { 883: $pre='\begin{center}'; 884: } elsif ($align eq 'left') { 885: $pre='\rlap{'; 886: } elsif ($align eq 'right') { 887: $pre=' \hfill \llap{'; 888: } 889: my $TeXsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval,undef,0); 890: if (not defined $TeXsize) {$TeXsize="large";} 891: $currentstring .= '\strut\newline '.$pre.'{\\'.$TeXsize.' \textbf{'; 892: } 893: return $currentstring; 894: } 895: 896: sub end_h6 { 897: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 898: my $currentstring = ''; 899: if ($target eq 'web' || $target eq 'webgrade') { 900: $currentstring .= $token->[2]; 901: } elsif ($target eq 'tex') { 902: my $post='\vskip 0 mm '; 903: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 904: if ($align eq 'center') { 905: $post='\end{center}'; 906: } elsif ($align eq 'left') { 907: $post='} \hfill'.'\vskip 0 mm '; 908: } elsif ($align eq 'right') { 909: $post='}'.'\vskip 0 mm '; 910: } 911: $currentstring .= '}}'.$post; 912: } 913: return $currentstring; 914: } 915: 916: #--- <cite> tag (end tag required) 917: sub start_cite { 918: my ($target,$token) = @_; 919: my $currentstring = ''; 920: if ($target eq 'web' || $target eq 'webgrade') { 921: $currentstring .= $token->[4]; 922: } elsif ($target eq 'tex') { 923: $currentstring .= '\textit{'; 924: } 925: return $currentstring; 926: } 927: 928: sub end_cite { 929: my ($target,$token) = @_; 930: my $currentstring = ''; 931: if ($target eq 'web' || $target eq 'webgrade') { 932: $currentstring .= $token->[2]; 933: } elsif ($target eq 'tex') { 934: $currentstring .= '}'; 935: } 936: return $currentstring; 937: } 938: 939: #-- <i> tag (end tag required) 940: sub start_i { 941: my ($target,$token) = @_; 942: my $currentstring = ''; 943: if ($target eq 'web' || $target eq 'webgrade') { 944: $currentstring .= $token->[4]; 945: } elsif ($target eq 'tex') { 946: $currentstring .= '\textit{'; 947: } 948: return $currentstring; 949: } 950: 951: sub end_i { 952: my ($target,$token) = @_; 953: my $currentstring = ''; 954: if ($target eq 'web' || $target eq 'webgrade') { 955: $currentstring .= $token->[2]; 956: } elsif ($target eq 'tex') { 957: $currentstring .= '}'; 958: } 959: return $currentstring; 960: } 961: 962: #-- <address> tag (end tag required) 963: sub start_address { 964: my ($target,$token) = @_; 965: my $currentstring = ''; 966: if ($target eq 'web' || $target eq 'webgrade') { 967: $currentstring .= $token->[4]; 968: } elsif ($target eq 'tex') { 969: $currentstring .= '\textit{'; 970: } 971: return $currentstring; 972: } 973: 974: sub end_address { 975: my ($target,$token) = @_; 976: my $currentstring = ''; 977: if ($target eq 'web' || $target eq 'webgrade') { 978: $currentstring .= $token->[2]; 979: } elsif ($target eq 'tex') { 980: $currentstring .= '}'; 981: } 982: return $currentstring; 983: } 984: 985: #-- <dfn> tag (end tag required) 986: sub start_dfn { 987: my ($target,$token) = @_; 988: my $currentstring = ''; 989: if ($target eq 'web' || $target eq 'webgrade') { 990: $currentstring .= $token->[4]; 991: } elsif ($target eq 'tex') { 992: $currentstring .= '\textit{'; 993: } 994: return $currentstring; 995: } 996: 997: sub end_dfn { 998: my ($target,$token) = @_; 999: my $currentstring = ''; 1000: if ($target eq 'web' || $target eq 'webgrade') { 1001: $currentstring .= $token->[2]; 1002: } elsif ($target eq 'tex') { 1003: $currentstring .= '}'; 1004: } 1005: return $currentstring; 1006: } 1007: 1008: #-- <tt> tag (end tag required) 1009: sub start_tt { 1010: my ($target,$token) = @_; 1011: my $currentstring = ''; 1012: if ($target eq 'web' || $target eq 'webgrade') { 1013: $currentstring .= $token->[4]; 1014: } elsif ($target eq 'tex') { 1015: $currentstring .= '\texttt{'; 1016: } 1017: return $currentstring; 1018: } 1019: 1020: sub end_tt { 1021: my ($target,$token) = @_; 1022: my $currentstring = ''; 1023: if ($target eq 'web' || $target eq 'webgrade') { 1024: $currentstring .= $token->[2]; 1025: } elsif ($target eq 'tex') { 1026: $currentstring .= '}'; 1027: } 1028: return $currentstring; 1029: } 1030: 1031: #-- <kbd> tag (end tag required) 1032: sub start_kbd { 1033: my ($target,$token) = @_; 1034: my $currentstring = ''; 1035: if ($target eq 'web' || $target eq 'webgrade') { 1036: $currentstring .= $token->[4]; 1037: } elsif ($target eq 'tex') { 1038: $currentstring .= '\texttt{'; 1039: } 1040: return $currentstring; 1041: } 1042: 1043: sub end_kbd { 1044: my ($target,$token) = @_; 1045: my $currentstring = ''; 1046: if ($target eq 'web' || $target eq 'webgrade') { 1047: $currentstring .= $token->[2]; 1048: } elsif ($target eq 'tex') { 1049: $currentstring .= '}'; 1050: } 1051: return $currentstring; 1052: } 1053: 1054: #-- <code> tag (end tag required) 1055: sub start_code { 1056: my ($target,$token) = @_; 1057: my $currentstring = ''; 1058: if ($target eq 'web' || $target eq 'webgrade') { 1059: $currentstring .= $token->[4]; 1060: } elsif ($target eq 'tex') { 1061: $currentstring .= '\texttt{'; 1062: } 1063: return $currentstring; 1064: } 1065: 1066: sub end_code { 1067: my ($target,$token) = @_; 1068: my $currentstring = ''; 1069: if ($target eq 'web' || $target eq 'webgrade') { 1070: $currentstring .= $token->[2]; 1071: } elsif ($target eq 'tex') { 1072: $currentstring .= '}'; 1073: } 1074: return $currentstring; 1075: } 1076: 1077: #-- <em> tag (end tag required) 1078: sub start_em { 1079: my ($target,$token) = @_; 1080: my $currentstring = ''; 1081: if ($target eq 'web' || $target eq 'webgrade') { 1082: $currentstring .= $token->[4]; 1083: } elsif ($target eq 'tex') { 1084: $currentstring .= '\emph{'; 1085: } 1086: return $currentstring; 1087: } 1088: 1089: sub end_em { 1090: my ($target,$token) = @_; 1091: my $currentstring = ''; 1092: if ($target eq 'web' || $target eq 'webgrade') { 1093: $currentstring .= $token->[2]; 1094: } elsif ($target eq 'tex') { 1095: $currentstring .= '}'; 1096: } 1097: return $currentstring; 1098: } 1099: 1100: #-- <q> tag (end tag required) 1101: sub start_q { 1102: my ($target,$token) = @_; 1103: my $currentstring = ''; 1104: if ($target eq 'web' || $target eq 'webgrade') { 1105: $currentstring .= $token->[4]; 1106: } elsif ($target eq 'tex') { 1107: $currentstring .= '\emph{'; 1108: } 1109: return $currentstring; 1110: } 1111: 1112: sub end_q { 1113: my ($target,$token) = @_; 1114: my $currentstring = ''; 1115: if ($target eq 'web' || $target eq 'webgrade') { 1116: $currentstring .= $token->[2]; 1117: } elsif ($target eq 'tex') { 1118: $currentstring .= '}'; 1119: } 1120: return $currentstring; 1121: } 1122: 1123: # <p> is a bit strange since it does not require a closing </p> 1124: # However in latex, we must often output closing stuff to end 1125: # environments and {}'s etc. Therefore we do all the work 1126: # of figuring out the ending strings in the start tag processing, 1127: # and provide a mechanism to output the stop text external 1128: # to tag processing. 1129: # 1130: { 1131: 1132: my $closing_string = ''; # String required to close <p> 1133: 1134: # Some tags are <p> fragile meaning that <p> inside of them 1135: # does not work within TeX mode. This is managed via the 1136: # counter below: 1137: # 1138: 1139: my $para_disabled = 0; 1140: 1141: sub disable_para { 1142: $para_disabled++; 1143: } 1144: sub enable_para { 1145: $para_disabled--; 1146: } 1147: 1148: 1149: #-- <p> tag (end tag optional) 1150: #optional attribute - align="center|left|right" 1151: sub start_p { 1152: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1153: my $currentstring = ''; 1154: if ($target eq 'web' || $target eq 'webgrade') { 1155: $currentstring .= &end_p(); # close off prior para if in progress. 1156: $currentstring .= $token->[4]; 1157: if (! ($currentstring =~ /\//)) { 1158: $closing_string = '</p>'; # Deal correctly with <p /> e.g. 1159: } 1160: } elsif ($target eq 'tex' && !$para_disabled) { 1161: 1162: $currentstring .= &end_p(); # close off prior para if in progress. 1163: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 1164: if ($align eq 'center') { 1165: $currentstring .='\begin{center}\par '; 1166: $closing_string = '\end{center}'; 1167: if (&is_inside_of($tagstack, "table")) { 1168: $currentstring = ¢er_correction().$currentstring; 1169: } 1170: } elsif ($align eq 'right') { 1171: $currentstring.="\n".'{\flushright '; 1172: # $currentstring.='\makebox['.$env{'form.textwidth'}.']{\hfill\llap{'; 1173: $closing_string= "}\n"; 1174: } elsif ($align eq 'left') { 1175: $currentstring.= "\n".'{\flushleft '; 1176: # $currentstring.='\noindent\makebox['.$env{'form.textwidth'}.']{{'; 1177: $closing_string = "}\n"; 1178: } else { 1179: $currentstring.='\par '; 1180: if (&is_inside_of($tagstack, 'table')) { 1181: $closing_string = '\vskip 0pt'; # Seems to be consistent with <p> in tables. 1182: } else { 1183: $closing_string = '\strut\\\\\strut '; 1184: } 1185: } 1186: 1187: } 1188: return $currentstring; 1189: } 1190: # 1191: # End paragraph processing just requires that we output the 1192: # closing string that was saved and blank it. 1193: sub end_p { 1194: # Note only 'tex' mode uses disable_para and enable_para 1195: # so we don't need to know the target in the check below: 1196: 1197: if (!$para_disabled) { 1198: my $current_string = $closing_string; 1199: $closing_string = ''; # Not in a para anymore. 1200: return $current_string; 1201: } else { 1202: return ''; 1203: } 1204: 1205: } 1206: } 1207: #-- <br> tag (end tag forbidden) 1208: sub start_br { 1209: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 1210: my $currentstring = ''; 1211: if ($target eq 'web' || $target eq 'webgrade') { 1212: $currentstring .= $token->[4]; 1213: } elsif ($target eq 'tex') { 1214: my @tempo=@$tagstack; 1215: my $signal=0; 1216: # Not going to factor this to is_inside_of since that would require 1217: # multiple stack traversals. 1218: # 1219: for (my $i=$#tempo;$i>=0;$i--) { 1220: if (($tempo[$i] eq 'b') || ($tempo[$i] eq 'strong') || 1221: ($tempo[$i] eq 'ol') || ($tempo[$i] eq 'ul')) { 1222: $signal=1; 1223: } 1224: if (($tempo[$i] eq 'td') || ($tempo[$i] eq 'th')) { 1225: $signal = 1; 1226: } 1227: } 1228: if ($signal eq 1) { 1229: $currentstring .= ' \vskip 0 mm '; 1230: } elsif ($$tagstack[-2] ne 'sub' && $$tagstack[-2] ne 'sup') { 1231: $currentstring .= '\strut \\\\ \strut '; 1232: } else { # Honor break in simple <sup></sup> 1233: $currentstring .= '}} \strut \\\\ \strut \ensuremath{^{'; 1234: } 1235: } 1236: return $currentstring; 1237: } 1238: 1239: sub end_br { 1240: my ($target,$token) = @_; 1241: my $currentstring = ''; 1242: if ($target eq 'web' || $target eq 'webgrade') { 1243: $currentstring .= $token->[2]; 1244: } 1245: return $currentstring; 1246: } 1247: 1248: #-- <big> tag (end tag required) 1249: sub start_big { 1250: my ($target,$token) = @_; 1251: my $currentstring = ''; 1252: if ($target eq 'web' || $target eq 'webgrade') { 1253: $currentstring .= $token->[4]; 1254: } elsif ($target eq 'tex') { 1255: $currentstring .= '{\large '; 1256: } 1257: return $currentstring; 1258: } 1259: 1260: sub end_big { 1261: my ($target,$token) = @_; 1262: my $currentstring = ''; 1263: if ($target eq 'web' || $target eq 'webgrade') { 1264: $currentstring .= $token->[2]; 1265: } elsif ($target eq 'tex') { 1266: $currentstring .= '}'; 1267: } 1268: return $currentstring; 1269: } 1270: 1271: #-- <small> tag (end tag required) 1272: sub start_small { 1273: my ($target,$token) = @_; 1274: my $currentstring = ''; 1275: if ($target eq 'web' || $target eq 'webgrade') { 1276: $currentstring .= $token->[4]; 1277: } elsif ($target eq 'tex') { 1278: $currentstring .= '{\footnotesize '; 1279: } 1280: return $currentstring; 1281: } 1282: 1283: sub end_small { 1284: my ($target,$token) = @_; 1285: my $currentstring = ''; 1286: if ($target eq 'web' || $target eq 'webgrade') { 1287: $currentstring .= $token->[2]; 1288: } elsif ($target eq 'tex') { 1289: $currentstring .= '}'; 1290: } 1291: return $currentstring; 1292: } 1293: 1294: #-- <basefont> tag (end tag forbidden) 1295: sub start_basefont { 1296: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 1297: my $currentstring = ''; 1298: if ($target eq 'web' || $target eq 'webgrade') { 1299: $currentstring = $token->[4]; 1300: } elsif ($target eq 'tex') { 1301: my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval); 1302: if (defined $basesize) { 1303: $currentstring = '{\\'.$basesize.' '; 1304: } 1305: } 1306: return $currentstring; 1307: } 1308: 1309: sub end_basefont { 1310: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1311: my $currentstring = ''; 1312: if ($target eq 'web' || $target eq 'webgrade') { 1313: $currentstring = $token->[4]; 1314: } elsif ($target eq 'tex') { 1315: my $basesize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval); 1316: if (defined $basesize) { 1317: $currentstring = '}'; 1318: } 1319: } 1320: return $currentstring; 1321: } 1322: 1323: #-- <font> tag (end tag required) 1324: sub start_font { 1325: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 1326: my $currentstring = ''; 1327: if ($target eq 'web' || $target eq 'webgrade') { 1328: my $face=&Apache::lonxml::get_param('face',$parstack,$safeeval); 1329: if ($face!~/symbol/i) { 1330: if (($env{'browser.fontenhance'} eq 'on') || 1331: ($env{'browser.blackwhite'} eq 'on')) { return ''; } 1332: } 1333: $currentstring = $token->[4]; 1334: } elsif ($target eq 'tex') { 1335: my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval); 1336: if (defined $fontsize) { 1337: $currentstring = '{\\'.$fontsize.' '; 1338: } 1339: } 1340: return $currentstring; 1341: } 1342: 1343: sub end_font { 1344: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 1345: my $currentstring = ''; 1346: if ($target eq 'web' || $target eq 'webgrade') { 1347: $currentstring = $token->[2]; 1348: } elsif ($target eq 'tex') { 1349: my $fontsize=&Apache::lonxml::get_param('TeXsize',$parstack,$safeeval); 1350: if (defined $fontsize) { 1351: $currentstring = '}'; 1352: } 1353: } 1354: return $currentstring; 1355: } 1356: 1357: #-- <strike> tag (end tag required) 1358: sub start_strike { 1359: my ($target,$token) = @_; 1360: my $currentstring = ''; 1361: if ($target eq 'web' || $target eq 'webgrade') { 1362: $currentstring .= $token->[4]; 1363: } elsif ($target eq 'tex') { 1364: &Apache::lonxml::startredirection(); 1365: } 1366: return $currentstring; 1367: } 1368: 1369: sub end_strike { 1370: my ($target,$token) = @_; 1371: my $currentstring = ''; 1372: if ($target eq 'web' || $target eq 'webgrade') { 1373: $currentstring .= $token->[2]; 1374: } elsif ($target eq 'tex') { 1375: $currentstring=&Apache::lonxml::endredirection(); 1376: $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g; 1377: $currentstring=~s/^\s*(\S)/\\underline\{$1/; 1378: $currentstring=~s/(\S)\s*$/$1\}/; 1379: } 1380: return $currentstring; 1381: } 1382: 1383: #-- <s> tag (end tag required) 1384: sub start_s { 1385: my ($target,$token) = @_; 1386: my $currentstring = ''; 1387: if ($target eq 'web' || $target eq 'webgrade') { 1388: $currentstring .= $token->[4]; 1389: } elsif ($target eq 'tex') { 1390: &Apache::lonxml::startredirection(); 1391: } 1392: return $currentstring; 1393: } 1394: 1395: sub end_s { 1396: my ($target,$token) = @_; 1397: my $currentstring = ''; 1398: if ($target eq 'web' || $target eq 'webgrade') { 1399: $currentstring .= $token->[2]; 1400: } elsif ($target eq 'tex') { 1401: $currentstring=&Apache::lonxml::endredirection(); 1402: $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g; 1403: $currentstring=~s/^\s*(\S)/\\underline\{$1/; 1404: $currentstring=~s/(\S)\s*$/$1\}/; 1405: } 1406: return $currentstring; 1407: } 1408: 1409: #-- <sub> tag (end tag required) 1410: sub start_sub { 1411: my ($target,$token) = @_; 1412: my $currentstring = ''; 1413: if ($target eq 'web' || $target eq 'webgrade') { 1414: $currentstring .= $token->[4]; 1415: } elsif ($target eq 'tex') { 1416: $currentstring .= '\ensuremath{_{'; 1417: } 1418: return $currentstring; 1419: } 1420: 1421: sub end_sub { 1422: my ($target,$token) = @_; 1423: my $currentstring = ''; 1424: if ($target eq 'web' || $target eq 'webgrade') { 1425: $currentstring .= $token->[2]; 1426: } elsif ($target eq 'tex') { 1427: $currentstring .= '}}'; 1428: } 1429: return $currentstring; 1430: } 1431: 1432: #-- <sup> tag (end tag required) 1433: sub start_sup { 1434: my ($target,$token) = @_; 1435: my $currentstring = ''; 1436: if ($target eq 'web' || $target eq 'webgrade') { 1437: $currentstring .= $token->[4]; 1438: } elsif ($target eq 'tex') { 1439: $currentstring .= '\ensuremath{^{'; 1440: } 1441: return $currentstring; 1442: } 1443: 1444: sub end_sup { 1445: my ($target,$token) = @_; 1446: my $currentstring = ''; 1447: if ($target eq 'web' || $target eq 'webgrade') { 1448: $currentstring .= $token->[2]; 1449: } elsif ($target eq 'tex') { 1450: $currentstring .= '}}'; 1451: } 1452: return $currentstring; 1453: } 1454: 1455: #-- <hr> tag (end tag forbidden) 1456: sub start_hr { 1457: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1458: my $currentstring = &end_p(); # End enclosing para. 1459: if ($target eq 'web' || $target eq 'webgrade') { 1460: $currentstring .= $token->[4]; 1461: } elsif ($target eq 'tex') { 1462: my $LaTeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); 1463: if (defined $LaTeXwidth) { 1464: if ($LaTeXwidth=~/^%/) { 1465: substr($LaTeXwidth,0,1)=''; 1466: $LaTeXwidth=($LaTeXwidth/100).'\textwidth'; 1467: } 1468: } else { 1469: $LaTeXwidth ='0.9\textwidth'; 1470: } 1471: my ($pre,$post); 1472: my $align=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 1473: if (($align eq 'center') || (not defined $align)) { 1474: $pre=''; $post=''; 1475: } elsif ($align eq 'left') { 1476: $pre='\rlap{'; $post='} \hfill'; 1477: } elsif ($align eq 'right') { 1478: $pre=' \hfill \llap{'; $post='}'; 1479: } 1480: $currentstring .= ' \vskip 0 mm \noindent\makebox['.$LaTeXwidth.']{'.$pre.'\makebox['. 1481: $LaTeXwidth.'][b]{\hrulefill}'.$post.'}\vskip 0 mm '; 1482: } 1483: return $currentstring; 1484: } 1485: 1486: sub end_hr { 1487: my ($target,$token) = @_; 1488: my $currentstring = ''; 1489: if ($target eq 'web' || $target eq 'webgrade') { 1490: $currentstring .= $token->[2]; 1491: } 1492: return $currentstring; 1493: } 1494: 1495: #-- <div> tag (end tag required) 1496: { 1497: 1498: # Since div can be nested, the stack below is used 1499: # in 'tex' mode to store the ending strings 1500: # for the div stack. 1501: 1502: my @div_end_stack; 1503: 1504: sub start_div { 1505: my ($target,$token, $tagstack, $parstack, $parser, $safeeval) = @_; 1506: my $currentstring = &end_p(); # Close enclosing para. 1507: if ($target eq 'web' || $target eq 'webgrade') { 1508: $currentstring .= $token->[4]; 1509: } 1510: if ($target eq 'tex') { 1511: # 4 possible alignments: left, right, center, and -missing-. 1512: 1513: my $endstring = ''; 1514: 1515: my $align = lc(&Apache::lonxml::get_param('align', $parstack, 1516: $safeeval, undef, 1)); 1517: if ($align eq 'center') { 1518: $currentstring .= '\begin{center}'; 1519: $endstring = '\end{center}'; 1520: if (&is_inside_of($tagstack, "table")) { 1521: $currentstring = ¢er_correction().$currentstring; 1522: } 1523: } 1524: elsif ($align eq 'right') { 1525: $currentstring .= '\begin{flushright}'; 1526: $endstring .= '\end{flushright}'; 1527: } elsif ($align eq 'left') { 1528: $currentstring .= '\begin{flushleft}'; 1529: $endstring = '\end{flushleft}'; 1530: } else { 1531: 1532: } 1533: $currentstring .= "\n"; # For human readability. 1534: $endstring = "\n$endstring\n"; # For human readability 1535: push(@div_end_stack, $endstring); 1536: } 1537: return $currentstring; 1538: } 1539: 1540: sub end_div { 1541: my ($target,$token) = @_; 1542: my $currentstring = ''; 1543: if ($target eq 'web' || $target eq 'webgrade') { 1544: $currentstring .= $token->[2]; 1545: } 1546: if ($target eq 'tex') { 1547: my $endstring = pop @div_end_stack; 1548: $currentstring .= $endstring; 1549: } 1550: return $currentstring; 1551: } 1552: } 1553: 1554: #-- <a> tag (end tag required) 1555: sub start_a { 1556: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1557: my $currentstring = ''; 1558: if ($target eq 'web' || $target eq 'webgrade') { 1559: my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval, 1560: undef,1); 1561: $currentstring=&Apache::lonenc::encrypt_ref($token,{'href'=>$href}); 1562: } elsif ($target eq 'tex') { 1563: my $a=&Apache::lonxml::get_param('href',$parstack,$safeeval,undef,1); 1564: my $b=&Apache::lonxml::get_param('name',$parstack,$safeeval,undef,1); 1565: if ($a=~/\S/) { 1566: $a=~s/([^\\])%/$1\\\%/g; 1567: $currentstring .= '\ref{URI: '.$a.'}'; 1568: } elsif ($b=~/\S/) { 1569: $currentstring .= '\ref{Anchor: '.$b.'}'; 1570: } else { 1571: $currentstring.=''; 1572: } 1573: } 1574: return $currentstring; 1575: } 1576: 1577: sub end_a { 1578: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1579: my $currentstring = ''; 1580: if ($target eq 'web' || $target eq 'webgrade') { 1581: $currentstring .= $token->[2]; 1582: } 1583: return $currentstring; 1584: } 1585: 1586: #-- <li> tag (end tag optional) 1587: sub start_li { 1588: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1589: my $currentstring = ''; 1590: if ($target eq 'web' || $target eq 'webgrade') { 1591: $currentstring = $token->[4]; 1592: } elsif ($target eq 'tex') { 1593: my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0); 1594: my $value=&Apache::lonxml::get_param('value',$parstack,$safeeval,undef,0); 1595: #FIXME need to support types i and I 1596: if ($type=~/disc/) { 1597: $currentstring .= ' \item[$\bullet$] '; 1598: } elsif ($type=~/circle/) { 1599: $currentstring .= ' \item[$\circ$] '; 1600: } elsif ($type=~/square/) { 1601: $currentstring .= ' \item[$\diamond$] '; 1602: } elsif ($type eq '1') { 1603: $currentstring .= ' \item['.($Apache::londefdef::list_index+1).'.]'; 1604: } elsif ($type eq 'A') { 1605: $currentstring .= ' \item['.('A'..'Z')[$Apache::londefdef::list_index].'.]'; 1606: } elsif ($type eq 'a') { 1607: $currentstring .= ' \item['.('a'..'z')[$Apache::londefdef::list_index].'.]'; 1608: } elsif ($value ne '') { 1609: $currentstring .= ' \item['.$value.'] '; 1610: } else { 1611: $currentstring .= ' \item '; 1612: } 1613: $Apache::londefdef::list_index++; 1614: } 1615: return $currentstring; 1616: } 1617: 1618: sub end_li { 1619: my ($target,$token) = @_; 1620: my $currentstring = &end_p(); # In case there's a <p> in the <li> 1621: if ($target eq 'web' || $target eq 'webgrade') { 1622: $currentstring .= $token->[2]; 1623: } 1624: return $currentstring; 1625: } 1626: 1627: #-- <u> tag (end tag required) 1628: sub start_u { 1629: my ($target,$token) = @_; 1630: my $currentstring = ''; 1631: if ($target eq 'web' || $target eq 'webgrade') { 1632: $currentstring .= $token->[4]; 1633: } elsif ($target eq 'tex') { 1634: &Apache::lonxml::startredirection(); 1635: } 1636: return $currentstring; 1637: } 1638: 1639: sub end_u { 1640: my ($target,$token) = @_; 1641: my $currentstring = ''; 1642: if ($target eq 'web' || $target eq 'webgrade') { 1643: $currentstring .= $token->[2]; 1644: } elsif ($target eq 'tex') { 1645: $currentstring=&Apache::lonxml::endredirection(); 1646: $currentstring=~s/(\S)(\s+)(\S)/$1\}$2\\underline\{$3/g; 1647: $currentstring=~s/^\s*(\S)/\\underline\{$1/; 1648: $currentstring=~s/(\S)\s*$/$1\}/; 1649: } 1650: return $currentstring; 1651: } 1652: 1653: #-- <ul> tag (end tag required) 1654: sub start_ul { 1655: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1656: my $currentstring = &end_p(); # Close off enclosing list. 1657: if ($target eq 'web' || $target eq 'webgrade') { 1658: $currentstring .= $token->[4]; 1659: } elsif ($target eq 'tex') { 1660: my $TeXtype=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0); 1661: $Apache::londefdef::list_index=0; 1662: if ($TeXtype eq 'disc') { 1663: $currentstring .= '\renewcommand{\labelitemi}{$\bullet$}'. 1664: '\renewcommand{\labelitemii}{$\bullet$}'. 1665: '\renewcommand{\labelitemiii}{$\bullet$}'. 1666: '\renewcommand{\labelitemiv}{$\bullet$}'; 1667: } elsif ($TeXtype eq 'circle') { 1668: $currentstring .= '\renewcommand{\labelitemi}{$\circ$}'. 1669: '\renewcommand{\labelitemii}{$\circ$}'. 1670: '\renewcommand{\labelitemiii}{$\circ$}'. 1671: '\renewcommand{\labelitemiv}{$\circ$}'; 1672: } elsif ($TeXtype eq 'square') { 1673: $currentstring .= '\renewcommand{\labelitemi}{$\diamond$}'. 1674: '\renewcommand{\labelitemii}{$\diamond$}'. 1675: '\renewcommand{\labelitemiii}{$\diamond$}'. 1676: '\renewcommand{\labelitemiv}{$\diamond$}'; 1677: } 1678: $currentstring .= '\strut \begin{itemize}'; 1679: } 1680: return $currentstring; 1681: } 1682: 1683: sub end_ul { 1684: my ($target,$token) = @_; 1685: my $currentstring = ''; 1686: if ($target eq 'web' || $target eq 'webgrade') { 1687: $currentstring = $token->[2]; 1688: } elsif ($target eq 'tex') { 1689: $currentstring = '\end{itemize} \renewcommand{\labelitemi}{$\bullet$}'. 1690: '\renewcommand{\labelitemii}{$\bullet$}'. 1691: '\renewcommand{\labelitemiii}{$\bullet$}'. 1692: '\renewcommand{\labelitemiv}{$\bullet$}\strut '; 1693: } 1694: return $currentstring; 1695: } 1696: 1697: #-- <menu> tag (end tag required) 1698: sub start_menu { 1699: my ($target,$token) = @_; 1700: my $currentstring = ''; 1701: if ($target eq 'web' || $target eq 'webgrade') { 1702: $currentstring = $token->[4]; 1703: } elsif ($target eq 'tex') { 1704: $currentstring = " \\begin{itemize} "; 1705: } 1706: return $currentstring; 1707: } 1708: 1709: sub end_menu { 1710: my ($target,$token) = @_; 1711: my $currentstring = ''; 1712: if ($target eq 'web' || $target eq 'webgrade') { 1713: $currentstring = $token->[2]; 1714: } elsif ($target eq 'tex') { 1715: $currentstring = " \\end{itemize}"; 1716: } 1717: return $currentstring; 1718: } 1719: 1720: #-- <dir> tag (end tag required) 1721: sub start_dir { 1722: my ($target,$token) = @_; 1723: my $currentstring = &end_p(); # In case there's a <p> prior to the list. 1724: if ($target eq 'web' || $target eq 'webgrade') { 1725: $currentstring .= $token->[4]; 1726: } elsif ($target eq 'tex') { 1727: $currentstring .= " \\begin{itemize} "; 1728: } 1729: return $currentstring; 1730: } 1731: 1732: sub end_dir { 1733: my ($target,$token) = @_; 1734: my $currentstring = ''; 1735: if ($target eq 'web' || $target eq 'webgrade') { 1736: $currentstring = $token->[2]; 1737: } elsif ($target eq 'tex') { 1738: $currentstring = " \\end{itemize}"; 1739: } 1740: return $currentstring; 1741: } 1742: 1743: #-- <ol> tag (end tag required) 1744: sub start_ol { 1745: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1746: my $currentstring = &end_p(); # In case there's a <p> prior to the list. 1747: if ($target eq 'web' || $target eq 'webgrade') { 1748: $currentstring .= $token->[4]; 1749: } elsif ($target eq 'tex') { 1750: $Apache::londefdef::list_index=0; 1751: my $type=&Apache::lonxml::get_param('type',$parstack,$safeeval,undef,0); 1752: if ($type eq '1') { 1753: $currentstring .= '\renewcommand{\labelenumi}{\arabic{enumi}.}'. 1754: '\renewcommand{\labelenumii}{\arabic{enumii}.}'. 1755: '\renewcommand{\labelenumiii}{\arabic{enumiii}.}'. 1756: '\renewcommand{\labelenumiv}{\arabic{enumiv}.}'; 1757: } elsif ($type eq 'A') { 1758: $currentstring .= '\renewcommand{\labelenumi}{\Alph{enumi}.}'. 1759: '\renewcommand{\labelenumii}{\Alph{enumii}.}'. 1760: '\renewcommand{\labelenumiii}{\Alph{enumiii}.}'. 1761: '\renewcommand{\labelenumiv}{\Alph{enumiv}.}'; 1762: } elsif ($type eq 'a') { 1763: $currentstring .= '\renewcommand{\labelenumi}{\alph{enumi}.}'. 1764: '\renewcommand{\labelenumii}{\alph{enumii}.}'. 1765: '\renewcommand{\labelenumiii}{\alph{enumiii}.}'. 1766: '\renewcommand{\labelenumiv}{\alph{enumiv}.}'; 1767: } elsif ($type eq 'i') { 1768: $currentstring .= '\renewcommand{\labelenumi}{\roman{enumi}.}'. 1769: '\renewcommand{\labelenumii}{\roman{enumii}.}'. 1770: '\renewcommand{\labelenumiii}{\roman{enumiii}.}'. 1771: '\renewcommand{\labelenumiv}{\roman{enumiv}.}'; 1772: } elsif ($type eq 'I') { 1773: $currentstring .= '\renewcommand{\labelenumi}{\Roman{enumi}.}'. 1774: '\renewcommand{\labelenumii}{\Roman{enumii}.}'. 1775: '\renewcommand{\labelenumiii}{\Roman{enumiii}.}'. 1776: '\renewcommand{\labelenumiv}{\Roman{enumiv}.}'; 1777: } 1778: $currentstring .= '\strut \begin{enumerate}'; 1779: } 1780: return $currentstring; 1781: } 1782: 1783: sub end_ol { 1784: my ($target,$token) = @_; 1785: my $currentstring = ''; 1786: if ($target eq 'web' || $target eq 'webgrade') { 1787: $currentstring = $token->[2]; 1788: } elsif ($target eq 'tex') { 1789: $currentstring = '\end{enumerate}\renewcommand{\labelenumi}{\arabic{enumi}.}'. 1790: '\renewcommand{\labelenumii}{\arabic{enumii}.}'. 1791: '\renewcommand{\labelenumiii}{\arabic{enumiii}.}'. 1792: '\renewcommand{\labelenumiv}{\arabic{enumiv}.}\strut '; 1793: } 1794: return $currentstring; 1795: } 1796: 1797: #-- <dl> tag (end tag required) 1798: sub start_dl { 1799: my ($target,$token) = @_; 1800: my $currentstring = &end_p(); # In case there's a <p> unclosed prior to the list. 1801: if ($target eq 'web' || $target eq 'webgrade') { 1802: $currentstring .= $token->[4]; 1803: } elsif ($target eq 'tex') { 1804: $currentstring .= '\begin{description}'; 1805: $Apache::londefdef::DL++; 1806: push(@Apache::londefdef::description,[]); 1807: $Apache::londefdef::DD[$Apache::londefdef::DL]=0; 1808: $Apache::londefdef::DT[$Apache::londefdef::DL]=0; 1809: $Apache::londefdef::seenDT[$Apache::londefdef::DL]=0; 1810: } 1811: return $currentstring; 1812: } 1813: 1814: sub end_dl { 1815: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1816: my $currentstring = ''; 1817: if ($target eq 'web' || $target eq 'webgrade') { 1818: $currentstring = $token->[2]; 1819: } elsif ($target eq 'tex') { 1820: if ($Apache::londefdef::DT[-1]) { &end_dt(@_); } 1821: if ($Apache::londefdef::DD[-1]) { &end_dd(@_); } 1822: foreach my $element (@{$Apache::londefdef::description[-1]}) { 1823: $currentstring.=' '.$element.' '; 1824: } 1825: pop(@Apache::londefdef::description); 1826: $currentstring.='\end{description}'; 1827: delete($Apache::londefdef::DD[$Apache::londefdef::DL]); 1828: delete($Apache::londefdef::DT[$Apache::londefdef::DL]); 1829: delete($Apache::londefdef::seenDT[$Apache::londefdef::DL]); 1830: $Apache::londefdef::DL--; 1831: } 1832: return $currentstring; 1833: } 1834: 1835: #-- <dt> tag (end tag optional) 1836: sub start_dt { 1837: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1838: my $currentstring=''; 1839: if ($target eq 'web' || $target eq 'webgrade') { 1840: $currentstring = $token->[4]; 1841: } elsif ($target eq 'tex') { 1842: if ($Apache::londefdef::DT[-1]) { &end_dt(@_); } 1843: if ($Apache::londefdef::DD[-1]) { &end_dd(@_); } 1844: &Apache::lonxml::startredirection(); 1845: $Apache::londefdef::DT[-1]++; 1846: $Apache::londefdef::seenDT[-1]=1; 1847: } 1848: return $currentstring; 1849: } 1850: 1851: sub end_dt { 1852: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1853: my $currentstring = ''; 1854: if ($target eq 'web' || $target eq 'webgrade') { 1855: $currentstring = $token->[2]; 1856: } elsif ($target eq 'tex') { 1857: if ($Apache::londefdef::DT[-1]) { 1858: my $data=&item_cleanup(); 1859: push(@{$Apache::londefdef::description[-1]},'\item['.$data.'] \strut \vskip 0mm'); 1860: $Apache::londefdef::DT[-1]--; 1861: } 1862: } 1863: return $currentstring; 1864: } 1865: 1866: sub item_cleanup { 1867: my $item=&Apache::lonxml::endredirection(); 1868: $item=~s/\\begin{center}//g; 1869: $item=~s/\\end{center}//g; 1870: return $item; 1871: } 1872: 1873: #-- <dd> tag (end tag optional) 1874: sub start_dd { 1875: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1876: my $currentstring = ''; 1877: if ($target eq 'web' || $target eq 'webgrade') { 1878: $currentstring = $token->[4]; 1879: } elsif ($target eq 'tex') { 1880: if ($Apache::londefdef::DT[-1]) { &end_dt(@_); } 1881: if ($Apache::londefdef::DD[-1]) { &end_dd(@_);} 1882: if (!$Apache::londefdef::seenDT[-1]) { 1883: push(@{$Apache::londefdef::description[-1]},'\item[\strut] \strut \vskip 0mm '); 1884: } 1885: push(@{$Apache::londefdef::description[-1]},''); 1886: $Apache::londefdef::description[-1]->[-1].=' \strut '; 1887: $Apache::londefdef::DD[-1]++; 1888: &Apache::lonxml::startredirection(); 1889: } 1890: return $currentstring; 1891: } 1892: 1893: sub end_dd { 1894: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1895: my $currentstring = ''; 1896: if ($target eq 'web' || $target eq 'webgrade') { 1897: $currentstring = $token->[2]; 1898: } elsif ($target eq 'tex') { 1899: $Apache::londefdef::description[-1]->[-1].= 1900: &Apache::lonxml::endredirection().' \vskip 0mm '; 1901: $Apache::londefdef::DD[-1]--; 1902: } 1903: return $currentstring; 1904: } 1905: 1906: #-- <table> tag (end tag required) 1907: # <table> also ends any prior <p> that is not closed. 1908: # but, unless I allow <p>'s to nest, that's the 1909: # only way I could think of to allow <p> in 1910: # <tr> <th> bodies 1911: # 1912: #list of supported attributes: border,width,TeXwidth 1913: sub start_table { 1914: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 1915: my $textwidth = ''; 1916: my $currentstring = &end_p(); 1917: if ($target eq 'web' || $target eq 'webgrade') { 1918: $currentstring .= $token->[4]; 1919: } elsif ($target eq 'tex') { 1920: push(@Apache::londefdef::table, {}); 1921: $Apache::londefdef::table[-1]{'row_number'} = -1; 1922: #maximum table's width (default coincides with text line length) 1923: if ($#Apache::londefdef::table==0) { 1924: $textwidth=&recalc($env{'form.textwidth'}); #result is always in mm 1925: $textwidth=~/(\d+\.?\d*)/; 1926: $textwidth=0.95*$1; #accounts "internal" LaTeX space for table frame 1927: } else { 1928: if ($Apache::londefdef::table[-2]{'TeXlen'}[$Apache::londefdef::table[-2]{'row_number'}][$Apache::londefdef::table[-2]{'counter_columns'}]=~/\d/) { 1929: #the maximum width of nested table is determined by LATeX width of parent cell 1930: $textwidth=$Apache::londefdef::table[-2]{'TeXlen'}[$Apache::londefdef::table[-2]{'row_number'}][$Apache::londefdef::table[-2]{'counter_columns'}]; 1931: } else { 1932: #try to use all space not used before (minus 5% for LaTeX table internal) - rather silly 1933: $textwidth=$Apache::londefdef::table[-2]{'width'}; 1934: for (my $i=0;$i<$Apache::londefdef::table[-2]{'counter_columns'};$i++) { 1935: $textwidth=$textwidth-$Apache::londefdef::table[-2]{'TeXlen'}[0][$i]; 1936: } 1937: } 1938: } 1939: 1940: # width either comes forced from the TeXwidth or the width parameters. 1941: # in either case it can be a percentage or absolute width. 1942: # in the width case we ignore absolute width 1943: my $TeXwidth = &Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); 1944: if (!defined($TeXwidth)) { 1945: my $htmlwidth = &Apache::lonxml::get_param('width',$parstack, 1946: $safeeval,undef,1); 1947: if ($htmlwidth =~ /%/) { 1948: $TeXwidth = $htmlwidth; 1949: } else { 1950: $TeXwidth = $textwidth; 1951: } 1952: } else { 1953: $Apache::londefdef::table[-1]{'forcedtablewidth'} = 1; 1954: } 1955: if ($TeXwidth=~/%/) { 1956: $Apache::londefdef::table[-1]{'percent'}=1; 1957: $TeXwidth=~/(\d+)/; 1958: $Apache::londefdef::table[-1]{'width'}=$1*$textwidth/100; 1959: } else { 1960: $Apache::londefdef::table[-1]{'width'}=$TeXwidth; 1961: } 1962: # In the end, however the table width cannot be wider than $textwidth... 1963: 1964: if ($Apache::londefdef::table[-1]{'width'} > $textwidth) { 1965: $Apache::londefdef::table[-1]{'width'} = $textwidth; 1966: } 1967: 1968: #table's border 1969: my $border = &Apache::lonxml::get_param('border',$parstack,$safeeval); 1970: my $permission=&Apache::lonxml::get_param('TeXDropEmptyColumns',$parstack,$safeeval,undef,0); 1971: unless (defined $border) { $border = 0; } 1972: if ($border) { 1973: $Apache::londefdef::table[-1]{'hinc'} = '\hline '; 1974: $Apache::londefdef::table[-1]{'vinc'} = '&'; 1975: $Apache::londefdef::table[-1]{'vvinc'} = '|'; 1976: } else { 1977: $Apache::londefdef::table[-1]{'hinc'} = ''; 1978: $Apache::londefdef::table[-1]{'vinc'} = '&'; 1979: $Apache::londefdef::table[-1]{'vvinc'} = ''; 1980: } 1981: if ($#Apache::londefdef::table==0) { 1982: # Note that \newline seems to destroy the alignment envs. 1983: # $Apache::londefdef::table[-1]{'output'}='\strut\newline\strut\setlength{\tabcolsep}{1 mm}'; 1984: $Apache::londefdef::table[-1]{'output'}='\strut'.'\\\\'."\n".'\strut\setlength{\tabcolsep}{1 mm}'; 1985: } 1986: $Apache::londefdef::table[-1]{'output'}.=' \noindent \begin{tabular} '; 1987: $Apache::londefdef::table[-1]{'TeXlen'}=[]; 1988: $Apache::londefdef::table[-1]{'objectlen'}=[]; 1989: $Apache::londefdef::table[-1]{'objectsignal'}=[]; 1990: $Apache::londefdef::table[-1]{'maxlen'}=[]; 1991: $Apache::londefdef::table[-1]{'minlen'}=[]; 1992: $Apache::londefdef::table[-1]{'content'}=[]; 1993: $Apache::londefdef::table[-1]{'align'}=[]; 1994: if (&is_inside_of($tagstack, 'sup')) { 1995: $currentstring .= '}} \\\\ \ensuremath{^{ '; 1996: } 1997: if (&is_inside_of($tagstack, 'sub')) { 1998: $currentstring .= '}} \\\\ \ensuremath{_{ '; 1999: } 2000: $currentstring.=' \keephidden{NEW TABLE ENTRY}'; 2001: 2002: 2003: } 2004: return $currentstring; 2005: } 2006: 2007: sub end_table { 2008: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 2009: my $currentstring = ''; 2010: if ($target eq 'web' || $target eq 'webgrade') { 2011: $currentstring = $token->[2]; 2012: } elsif ($target eq 'tex') { 2013: my $inmemory = ''; 2014: my $output = ''; 2015: my $WARNING=''; 2016: #width of columns from TeXwidth attributes 2017: 2018: for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { 2019: for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { 2020: if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]<$Apache::londefdef::table[-1]{'TeXlen'}[$in][$jn]) { 2021: $Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]=$Apache::londefdef::table[-1]{'TeXlen'}[$in][$jn]; 2022: } 2023: } 2024: } 2025: #free space and number of empty columns 2026: my ($available_space,$empty_columns)=($Apache::londefdef::table[-1]{'width'},0); 2027: if ($#Apache::londefdef::table ne 0) {$available_space=0.9*$available_space;} 2028: for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { 2029: if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]==0) { 2030: $empty_columns++; 2031: } else { 2032: $available_space=$available_space-$Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]; 2033: } 2034: } 2035: #boundaries for contents columns 2036: my @min_len=();#columns can not be narrower 2037: my @max_len=();#maximum length of column 2038: for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { 2039: my ($localmin,$localmax)=(0,0); 2040: for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { 2041: if ($localmin<$Apache::londefdef::table[-1]{'minlen'}[$in][$jn]) { 2042: $localmin=$Apache::londefdef::table[-1]{'minlen'}[$in][$jn]; 2043: } 2044: if ($localmax<$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn]) { 2045: $localmax=$Apache::londefdef::table[-1]{'maxlen'}[$in][$jn]; 2046: } 2047: } 2048: push @min_len, $localmin; 2049: push @max_len, $localmax; 2050: } 2051: for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { 2052: my $localmin=0,; 2053: for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { 2054: if ($localmin<$Apache::londefdef::table[-1]{'objectlen'}[$in][$jn]) { 2055: $localmin=$Apache::londefdef::table[-1]{'objectlen'}[$in][$jn]; 2056: } 2057: } 2058: if ($max_len[$jn]<$localmin) { 2059: $max_len[$jn]=$localmin; 2060: $Apache::londefdef::table[-1]{'objectsignal'}[$jn]=1; 2061: }#object size is bigger 2062: if ($min_len[$jn]<$localmin) { 2063: $min_len[$jn]=$localmin; 2064: $Apache::londefdef::table[-1]{'objectsignal'}[$jn]=1; 2065: }#object size is bigger 2066: if ($Apache::londefdef::table[-1]{'TeXlen'}[0][$jn]!=0) { 2067: $min_len[$jn]=0; 2068: $max_len[$jn]=0; 2069: } 2070: } 2071: #final adjustment of column width 2072: my @fwidth=@{$Apache::londefdef::table[-1]{'TeXlen'}[0]};#final width array 2073: my @adjust=(); 2074: #step 1. adjustment by maximum value 2075: my $space_neeeded=0; 2076: for (my $jn=0;$jn<=$#max_len;$jn++) { 2077: $space_neeeded=$space_neeeded+$max_len[$jn]; 2078: } 2079: if ($space_neeeded<=$available_space) { 2080: for (my $jn=0;$jn<=$#max_len;$jn++) { 2081: if ($fwidth[$jn]==0) { 2082: $fwidth[$jn]=$max_len[$jn]; 2083: } 2084: } 2085: } else { 2086: #step 2. adjustment by minimum value (estimation) 2087: $space_neeeded=0; 2088: for (my $jn=0;$jn<=$#min_len;$jn++) { 2089: $space_neeeded+=$min_len[$jn]; 2090: } 2091: if ($space_neeeded>$available_space) { 2092: $WARNING=' \textbf{NOT ENOUGH SPACE FOR TABLE} '; 2093: for (my $jn=0;$jn<=$#max_len;$jn++) { 2094: if ($fwidth[$jn]==0) { 2095: $fwidth[$jn]=$min_len[$jn]; 2096: } 2097: } 2098: #check if we have objects which can be scaled 2099: my $how_many_to_scale=0; 2100: my @to_scale=(); 2101: for (my $jn=0;$jn<=$#max_len;$jn++) { 2102: if ($Apache::londefdef::table[-1]{'objectsignal'}[$jn] eq '1') { 2103: $how_many_to_scale++; 2104: push @to_scale, $jn; 2105: } 2106: } 2107: if ($how_many_to_scale>0) { 2108: my $space_to_adjust=($space_neeeded-$available_space)/$how_many_to_scale; 2109: foreach my $jn (@to_scale) { 2110: for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { 2111: $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/; 2112: if ($1 ne '') { 2113: my $current_length=&recalc($1); 2114: $current_length=~/(\d+\.?\d*)/; 2115: $current_length=$current_length-$space_to_adjust; 2116: $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/width=$current_length mm/; 2117: } 2118: $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~m/\[(\d+\.?\d*)\s*mm\]/; 2119: if ($1 ne '') { 2120: my $current_length=$1; 2121: $current_length=$current_length-$space_to_adjust; 2122: $Apache::londefdef::table[-1]{'content'}[$in][$jn]=~s/\[(\d+\.?\d*)\s*mm\]/\[$current_length mm\]/; 2123: } 2124: } 2125: $fwidth[$jn]=$fwidth[$jn]-$space_to_adjust; 2126: } 2127: } 2128: } else { 2129: #step 3. adjustment over minimal + corrections 2130: my $enlarge_coef=$available_space/$space_neeeded; 2131: my $acsessive=0; 2132: for (my $jn=0;$jn<=$#min_len;$jn++) { 2133: $adjust[$jn]=$min_len[$jn]*$enlarge_coef; 2134: if ($adjust[$jn]>$max_len[$jn]) { 2135: $fwidth[$jn]=$max_len[$jn]; 2136: $acsessive=$acsessive+$adjust[$jn]-$max_len[$jn]; 2137: $adjust[$jn]=0; 2138: } 2139: } 2140: if ($acsessive>0) { 2141: #we have an excess of space and can redistribute it 2142: my $notempty_columns=0; 2143: for (my $jn=0;$jn<=$#min_len;$jn++) { 2144: if ($adjust[$jn]!=0) { 2145: $notempty_columns++; 2146: } 2147: } 2148: my $per_column=$acsessive/$notempty_columns; 2149: for (my $jn=0;$jn<=$#min_len;$jn++) { 2150: if ($adjust[$jn]!=0) { 2151: $adjust[$jn]+=$per_column; 2152: $fwidth[$jn]=$adjust[$jn]; 2153: } 2154: } 2155: } else { 2156: for (my $jn=0;$jn<=$#min_len;$jn++) { 2157: $fwidth[$jn]=$adjust[$jn]; 2158: } 2159: } 2160: } 2161: } 2162: #use all available width if it is defined in % or as TeXwidth 2163: if (($Apache::londefdef::table[-1]{'percent'}==1) || ($Apache::londefdef::table[-1]{'forcetablewidth'}==1)) { 2164: my $current=0; 2165: for (my $i=0;$i<=$#fwidth;$i++) { 2166: $current+=$fwidth[$i]; 2167: } 2168: my $coef=$Apache::londefdef::table[-1]{'width'}/$current; 2169: for (my $i=0;$i<=$#fwidth;$i++) { 2170: $fwidth[$i]*=$coef; 2171: } 2172: } 2173: #removing of empty columns if allowed 2174: my $permission=&Apache::lonxml::get_param('TeXDropEmptyColumns',$parstack,$safeeval,undef,0); 2175: if ($permission eq 'yes') { 2176: my @cleaned_table=(); 2177: my @cleaned_header=(); 2178: my $colind=0; 2179: for (my $jn=0;$jn<=$Apache::londefdef::table[-1]{'counter_columns'};$jn++) { 2180: if ($fwidth[$jn]!=0) { 2181: #we need to copy column 2182: for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { 2183: $cleaned_table[$in][$colind]=$Apache::londefdef::table[-1]{'content'}[$in][$jn]; 2184: $cleaned_header[$colind]=$fwidth[$jn]; 2185: } 2186: $colind++; 2187: } 2188: } 2189: $Apache::londefdef::table[-1]{'content'}=\@cleaned_table; 2190: @fwidth=@cleaned_header; 2191: } 2192: #construct header of the table 2193: my $header_of_table = '{'.$Apache::londefdef::table[-1]{'vvinc'}; 2194: for (my $in=0;$in<=$#fwidth;$in++) { 2195: $header_of_table.='p{'.$fwidth[$in].' mm}'.$Apache::londefdef::table[-1]{'vvinc'}; 2196: } 2197: $header_of_table .= '}'; 2198: #fill the table 2199: for (my $in=0;$in<=$Apache::londefdef::table[-1]{'row_number'};$in++) { 2200: my $have_rowspan = 0; 2201: for (my $jn=0;$jn<=$#fwidth;$jn++) { 2202: 2203: #----------------------------------------------------------- 2204: # I think this order of doing things will ensure that 2205: # single rowspan, columspan and combined row/colspans will 2206: # work correctly. LaTeX is delicate here. 2207: # RF. 2208: 2209: # Start a rowspan if necessary: 2210: 2211: my $rowspan = $Apache::londefdef::table[-1]{'rowspan'}[$in][$jn]; 2212: my $colspan = $Apache::londefdef::table[-1]{'colspan'}[$in][$jn]; 2213: # 2214: # Do the appropriate magic if this has a colspan 2215: # 2216: 2217: if ($colspan > 1) { 2218: my $spanwidth = 0; 2219: for (my $spancol = $jn; $spancol < $jn + $colspan; $spancol++) { 2220: $spanwidth += $fwidth[$spancol]; 2221: } 2222: $output .= '\multicolumn{'. 2223: $colspan 2224: ."}"; 2225: if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { 2226: $output .= '{|c|}{'; 2227: } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { 2228: $output .= '{|r|}{'; 2229: } 2230: else { 2231: $output .= "{|p{$spanwidth mm}|}{"; 2232: } 2233: 2234: } 2235: 2236: # Rowspan... if colspan is 1, and there's an alignment we'll need 2237: # to kick in a multicolumn in order to get the alignment spec. 2238: # this must precede the multirow or LaTex gets quite upset. 2239: # Naturally if colspan > 1 we've already done that above ^ 2240: # 2241: my $multirow_aligned = 0; 2242: if ($rowspan > 1) { 2243: if ($colspan == 1) { 2244: if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { 2245: $output .= '\multicolumn{1}{|c|}{'; 2246: $multirow_aligned = 1; 2247: } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { 2248: $output .= '\multicolumn{1}{|r|}{'; 2249: $multirow_aligned = 1; 2250: } 2251: } 2252: $have_rowspan++; 2253: $output .= '\multirow{'.$rowspan.'}[0]{*}{'; 2254: # 2255: # If we did not throw in a multicolumn to align, then add 2256: # an extra { 2257: # so we close correctly without having to keep additional state 2258: # around 2259: # 2260: if (!$multirow_aligned) { 2261: $output .= '{'; 2262: } 2263: } 2264: if (($rowspan eq '^') || ($rowspan eq '_')) { 2265: $have_rowspan++; 2266: } 2267: #-------------------------------------------------------------- 2268: 2269: 2270: # For right and center alignment of single cells. 2271: # we are going to use a multicolumn with a span of 1 to specify alignment. 2272: # 2273: if ($colspan == 1 && $rowspan == 1) { 2274: if ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') { 2275: $output .= '\multicolumn{1}{|c|}{'; 2276: } elsif ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r') { 2277: $output .= '\multicolumn{1}{|r|}{'; 2278: } 2279: } 2280: 2281: $output.=$Apache::londefdef::table[-1]{'content'}[$in][$jn]; 2282: 2283: if (($colspan == 1 && $rowspan == 1) && 2284: (($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'c') || 2285: ($Apache::londefdef::table[-1]{'align'}[$in][$jn] eq 'r'))) { 2286: $output .= '}'; 2287: } 2288: 2289: # Close off any open multirow: 2290: 2291: if ($rowspan > 1) { 2292: $output .= '}}'; 2293: } 2294: # Close off the colspan... 2295: # 2296: if ($colspan > 1) { 2297: $output .= '}'; 2298: $jn += $colspan-1; # Adjust for number of rows really left. 2299: } 2300: if ($jn!=$#fwidth) {$output.=' '.$Apache::londefdef::table[-1]{'vinc'};} 2301: } 2302: # If have_rowspan > 0, and borders are on, then 2303: # we need to do more than put an \hline at the bottom of row. 2304: # we need to do the appropriate \cline to ensure that 2305: # the spanned rows don't have \hlines through them. 2306: 2307: if (($Apache::londefdef::table[-1]{'hinc'} =~ /\\hline/) && $have_rowspan) { 2308: $output .= ' \\\\ '; 2309: for (my $jn=0; $jn<=$#fwidth;$jn++) { 2310: my $rowspan = $Apache::londefdef::table[-1]{'rowspan'}[$in][$jn]; 2311: if ($rowspan ne "^") { 2312: if (($rowspan <= 1) || ($rowspan eq '_')) { 2313: my $column = $jn+1; 2314: $output .= '\cline{'.$column.'-'.$column.'} '; 2315: } 2316: } 2317: } 2318: 2319: } else { 2320: $output.=' \\\\ '.$Apache::londefdef::table[-1]{'hinc'}.' '; 2321: } 2322: } 2323: # Note that \newline destroys alignment env's produced by e.g. <div> 2324: # $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut\newline\strut '; 2325: $Apache::londefdef::table[-1]{'output'} .= $header_of_table.$Apache::londefdef::table[-1]{'hinc'}.$output.'\end{tabular}\strut'.'\\\\'."\n".'\strut '; 2326: if ($#Apache::londefdef::table > 0) { 2327: my $inmemory = $Apache::londefdef::table[-1]{'output'}; 2328: # Figure out max/and min width by summing us and then 2329: # apply that to the current column of the table we nest in 2330: # if it's larger than the current width or the current width 2331: # is undefined. 2332: # 2333: my $min_nested_width = 0; 2334: my $max_nested_width = 0; 2335: for (my $col = 0; $col <= $Apache::londefdef::table[-1]{'counter_columns'}; $col++) { 2336: $min_nested_width += $min_len[$col]; 2337: $max_nested_width += $max_len[$col]; 2338: 2339: } 2340: # Fudge in an extra 5 mm for borders etc: 2341: 2342: $min_nested_width += 5; 2343: $max_nested_width += 5; 2344: 2345: my $outer_column = $Apache::londefdef::table[-2]{'counter_columns'}; 2346: my $outer_row = $Apache::londefdef::table[-2]{'row_number'}; 2347: if ($min_nested_width > $Apache::londefdef::table[-2]{'minlen'}[$outer_row][$outer_column]) { 2348: $Apache::londefdef::table[-2]{'minlen'}[$outer_row][$outer_column] = $min_nested_width; 2349: } 2350: if ($max_nested_width > $Apache::londefdef::table[-2]{'maxlen'}[$outer_row][$outer_column]) { 2351: $Apache::londefdef::table[-2]{'maxlen'}[$outer_row][$outer_column] = $max_nested_width; 2352: } 2353: 2354: pop @Apache::londefdef::table; 2355: push @{$Apache::londefdef::table[-1]{'include'}}, $inmemory; 2356: } else { 2357: $currentstring .= $Apache::londefdef::table[-1]{'output'}; 2358: pop @Apache::londefdef::table; 2359: undef @Apache::londefdef::table; 2360: } 2361: } 2362: return $currentstring; 2363: } 2364: 2365: #-- <tr> tag (end tag optional) 2366: sub start_tr { 2367: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 2368: my $currentstring = ''; 2369: if ($target eq 'web' || $target eq 'webgrade') { 2370: $currentstring = $token->[4]; 2371: } elsif ($target eq 'tex') { 2372: $Apache::londefdef::table[-1]{'row_number'}++; 2373: my $alignchar=&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1); 2374: if ($alignchar ne '') { 2375: push @ {$Apache::londefdef::table[-1]{'rows'} },substr($alignchar,0,1); 2376: } else { 2377: push @ {$Apache::londefdef::table[-1]{'rows'} }, 'l'; 2378: } 2379: push ( @{ $Apache::londefdef::table[-1]{'rowdata'} }, $Apache::londefdef::table[-1]{'hinc'}); 2380: # 2381: # Need to save the number of table columns to preserve the max # columns. 2382: # 2383: $Apache::londefdef::table[-1]{'prior_columns'} = $Apache::londefdef::table[-1]{'counter_columns'}; 2384: $Apache::londefdef::table[-1]{'counter_columns'} = -1; 2385: push @ {$Apache::londefdef::table[-1]{'TeXlen'}}, []; 2386: push @ {$Apache::londefdef::table[-1]{'objectlen'}}, []; 2387: push @ {$Apache::londefdef::table[-1]{'minlen'}}, []; 2388: push @ {$Apache::londefdef::table[-1]{'maxlen'}}, []; 2389: push @ {$Apache::londefdef::table[-1]{'content'}}, []; 2390: } 2391: return $currentstring; 2392: } 2393: 2394: sub end_tr { 2395: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 2396: my $currentstring = &end_p(); # Close any pending <p> in the row. 2397: if ($target eq 'web' || $target eq 'webgrade') { 2398: $currentstring .= $token->[2]; 2399: } elsif ($target eq 'tex') { 2400: if ($Apache::londefdef::TD_redirection) { 2401: &end_td_tex($parstack,$parser,$safeeval); 2402: } 2403: # Counter columns must be the maximum number of columns seen 2404: # in the table so far so: 2405: if ($Apache::londefdef::table[-1]{'prior_columns'} > $Apache::londefdef::table[-1]{'counter_columns'}) { 2406: $Apache::londefdef::table[-1]{'counter_columns'} = $Apache::londefdef::table[-1]{'prior_columns'}; 2407: } 2408: 2409: 2410: 2411: } 2412: return $currentstring; 2413: } 2414: 2415: #-- <td> tag (end tag optional) 2416: sub start_td { 2417: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 2418: my $currentstring = ''; 2419: if ($target eq 'web' || $target eq 'webgrade') { 2420: $currentstring = $token->[4]; 2421: } elsif ($target eq 'tex') { 2422: $Apache::londefdef::TD_redirection = 1; 2423: &tag_check('tr','td',$tagstack,$parstack,$parser,$safeeval); 2424: } 2425: return $currentstring; 2426: } 2427: 2428: sub tag_check { 2429: my ($good_tag,$bad_tag,$tagstack,$parstack,$parser,$safeeval) = @_; 2430: my @ar=@$parstack; 2431: for (my $i=$#ar-1;$i>=0;$i--) { 2432: if (lc($$tagstack[$i]) eq $good_tag) { 2433: &start_td_tex($parstack,$parser,$safeeval); 2434: last; 2435: } elsif (lc($$tagstack[$i]) eq $bad_tag) { 2436: splice @ar, $i+1; 2437: &end_td_tex(\@ar,$parser,$safeeval); 2438: &start_td_tex($parstack,$parser,$safeeval); 2439: last; 2440: } 2441: } 2442: return ''; 2443: } 2444: 2445: sub start_td_tex { 2446: my ($parstack,$parser,$safeeval) = @_; 2447: my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1); 2448: if ($alignchar eq '') { 2449: $alignchar = $Apache::londefdef::table[-1]{'rows'}[-1]; 2450: } 2451: push @{ $Apache::londefdef::table[-1]{'align'}[$Apache::londefdef::table[-1]{'row_number'}] }, $alignchar; 2452: $Apache::londefdef::table[-1]{'counter_columns'}++; 2453: my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); 2454: if (defined $TeXwidth) { 2455: my $current_length=&recalc($TeXwidth); 2456: $current_length=~/(\d+\.?\d*)/; 2457: push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1; 2458: } 2459: &Apache::lonxml::startredirection(); 2460: return ''; 2461: } 2462: 2463: sub end_td_tex { 2464: my ($parstack,$parser,$safeeval) = @_; 2465: my $current_row = $Apache::londefdef::table[-1]{'row_number'}; 2466: my $current_column = $Apache::londefdef::table[-1]{'counter_columns'}; 2467: my $data = &Apache::lonxml::endredirection(); 2468: 2469: # The rowspan array of the table indicates which cells are part of a span. 2470: # n indicates the start of a span set of n rows. 2471: # ^ indicates a cell that continues a span set. 2472: # _ indicates the cell is at the bottom of a span set. 2473: # If this and subsequent cells are part of a rowspan, we must 2474: # push along the row until we find one that is not. 2475: 2476: while ((defined $Apache::londefdef::table[-1]{'rowspan'}[$current_row] [$current_column]) 2477: && ($Apache::londefdef::table[-1]{'rowspan'}[$current_row][$current_column] =~ /[\^\_]/)) { 2478: # Part of a span. 2479: push @ {$Apache::londefdef::table[-1]{'content'}[-1]}, ''; 2480: $current_column++; 2481: } 2482: $Apache::londefdef::table[-1]{'counter_columns'} = $current_column; 2483: 2484: 2485: # Get the column and row spans. 2486: # Colspan can be done via \multicolumn if I can figure out the data structs. 2487: 2488: my $colspan = &Apache::lonxml::get_param('colspan', $parstack, $safeeval, undef, 0); 2489: if (!$colspan) { 2490: $colspan = 1; 2491: } 2492: 2493: my $rowspan = &Apache::lonxml::get_param('rowspan', $parstack, $safeeval, undef, 0); 2494: if (!$rowspan) { 2495: $rowspan = 1; 2496: } 2497: 2498: 2499: 2500: for (my $c = 0; $c < $colspan; $c++) { 2501: $Apache::londefdef::table[-1]{'rowspan'}[$current_row][$current_column+$c] = $rowspan; 2502: for (my $i = 1; $i < $rowspan; $i++) { 2503: $Apache::londefdef::table[-1]{'rowspan'}[$current_row+$i][$current_column+$c] = '^'; 2504: if ($i == ($rowspan-1)) { 2505: $Apache::londefdef::table[-1]{'rowspan'}[$current_row+$i][$current_column+$c] = '_'; 2506: } 2507: } 2508: } 2509: 2510: my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); 2511: if (defined $TeXwidth) { 2512: push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2513: push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2514: push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2515: } else { 2516: if (($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) or ($data=~m/\[(\d+\.?\d*)\s*mm\]/)) { 2517: my $garbage_data=$data; 2518: my $fwidth=0; 2519: while ($garbage_data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) { 2520: my $current_length=&recalc($1); 2521: $current_length=~/(\d+\.?\d*)/; 2522: if ($fwidth<$1) {$fwidth=$1;} 2523: $garbage_data=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//; 2524: } 2525: while ($garbage_data=~m/\[(\d+\.?\d*)\s*mm\]/) { 2526: my $current_length=$1; 2527: if ($fwidth<$current_length) {$fwidth=$current_length;} 2528: $garbage_data=~s/\[(\d+\.?\d*)\s*mm\]//; 2529: } 2530: push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2531: push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth; 2532: push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2533: push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2534: } elsif ($data=~/\\parbox\{\s*\d+\.?\d*\s*(mm|cm|in|pc|pt)*\s*\}/ or $data=~/\\epsfxsize\s*=\s*\d+\.?\d*\s*(mm|cm|in|pc|pt)*/) { 2535: my $garbage_data=$data; 2536: my $fwidth=0; 2537: while ($garbage_data=~/\\parbox\{\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)\s*\}/) { 2538: my $current_length=&recalc($1); 2539: $current_length=~/(\d+\.?\d*)/; 2540: if ($fwidth<$1) {$fwidth=$1;} 2541: $garbage_data=~s/\\parbox\{\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//; 2542: } 2543: while ($garbage_data=~/\\epsfxsize\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) { 2544: my $current_length=&recalc($1); 2545: $current_length=~/(\d+\.?\d*)/; 2546: if ($fwidth<$1) {$fwidth=$1;} 2547: $garbage_data=~s/\\epsfxsize\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//; 2548: } 2549: push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2550: push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth; 2551: push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2552: push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2553: $data=~s/\\\\\s*$//; 2554: } else { 2555: $data=~s/^\s+(\S.*)/$1/; 2556: $data=~s/(.*\S)\s+$/$1/; 2557: $data=~s/(\s)+/$1/; 2558: my ($current_length,$min_length)=(0,0); 2559: if ($data=~/\\vskip/) { 2560: my $newdata=$data; 2561: $newdata=~s/\\vskip \d*\.?\d*\s*mm/THISISJUSTTEMPORARYSEPARATOR/g; 2562: my @newdata=split(/THISISJUSTTEMPORARYSEPARATOR/,$newdata); 2563: foreach my $elementdata (@newdata) { 2564: my $lengthnewdata=2.5*&LATEX_length($elementdata); 2565: if ($lengthnewdata>$current_length) {$current_length=$lengthnewdata;} 2566: my @words=split(/ /,$elementdata); 2567: foreach my $word (@words) { 2568: my $lengthword=2.5*&LATEX_length($word); 2569: if ($min_length<$lengthword) {$min_length=$lengthword;} 2570: } 2571: } 2572: } else { 2573: $current_length=2.5*&LATEX_length($data); 2574: my @words=split(/ /,$data); 2575: foreach my $word (@words) { 2576: my $lengthword=2*&LATEX_length($word); 2577: if ($min_length<$lengthword) {$min_length=$lengthword;} 2578: } 2579: } 2580: push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2581: push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2582: push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$current_length; 2583: push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length; 2584: } 2585: } 2586: # Substitute all of the tables nested in this cell in their appropriate places. 2587: 2588: 2589: my $nested_count = $#{$Apache::londefdef::table[-1]{'include'}}; # This one is constant... 2590: for (my $in=0; $in<=$nested_count; $in++) { 2591: my $nested = shift @{$Apache::londefdef::table[-1]{'include'}}; 2592: $nested =~ s/\\end\{tabular\}\\strut\\\\/\\end\{tabular\}/; 2593: # $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/; 2594: $data =~ s/\\keephidden\{NEW TABLE ENTRY\}/$nested/; 2595: 2596: } 2597: # Should be be killing off the 'include' elements as they're used up? 2598: 2599: push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data; 2600: 2601: 2602: 2603: 2604: # the colspan array will indicate how many columns will be spanned by this 2605: # cell..this requires that counter_columns also be adjusted accordingly 2606: # so that the next bunch of text goes in the right cell. Note that since 2607: # counter_columns is incremented in the start_td_tex, we adjust by colspan-1. 2608: # 2609: 2610: $Apache::londefdef::table[-1]{'counter_columns'} += $colspan -1; 2611: for (my $i = 0; $i < ($colspan -1); $i++) { 2612: push @ {$Apache::londefdef::table[-1]{'content'}[-1] },''; 2613: } 2614: for (my $r = 0; $r < $rowspan; $r++) { 2615: $Apache::londefdef::table[-1]{'colspan'}[$current_row+$r][$current_column] = $colspan; 2616: # Put empty text in spanned cols. 2617: 2618: } 2619: 2620: 2621: 2622: return ''; 2623: } 2624: 2625: sub end_td { 2626: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 2627: my $currentstring = ''; 2628: if ($target eq 'web' || $target eq 'webgrade') { 2629: $currentstring = $token->[2]; 2630: } elsif ($target eq 'tex') { 2631: $Apache::londefdef::TD_redirection =0; 2632: &end_td_tex($parstack,$parser,$safeeval); 2633: } 2634: return $currentstring; 2635: } 2636: 2637: #-- <th> tag (end tag optional) 2638: sub start_th { 2639: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 2640: my $currentstring = ''; 2641: if ($target eq 'web' || $target eq 'webgrade') { 2642: $currentstring = $token->[4]; 2643: } elsif ($target eq 'tex') { 2644: $Apache::londefdef::TD_redirection = 1; 2645: &tagg_check('tr','th',$tagstack,$parstack,$parser,$safeeval); 2646: } 2647: return $currentstring; 2648: } 2649: 2650: sub tagg_check { 2651: my ($good_tag,$bad_tag,$tagstack,$parstack,$parser,$safeeval) = @_; 2652: my @ar=@$parstack; 2653: for (my $i=$#ar-1;$i>=0;$i--) { 2654: if (lc($$tagstack[$i]) eq $good_tag) { 2655: &start_th_tex($parstack,$parser,$safeeval); 2656: last; 2657: } elsif (lc($$tagstack[$i]) eq $bad_tag) { 2658: splice @ar, $i+1; 2659: &end_th_tex(\@ar,$parser,$safeeval); 2660: &start_th_tex($parstack,$parser,$safeeval); 2661: last; 2662: } 2663: } 2664: return ''; 2665: } 2666: 2667: sub start_th_tex { 2668: my ($parstack,$parser,$safeeval) = @_; 2669: my $alignchar = substr(&Apache::lonxml::get_param('align',$parstack,$safeeval,undef,1),0,1); 2670: if ($alignchar eq '') { 2671: $alignchar = $Apache::londefdef::table[-1]{'rows'}[-1]; 2672: } 2673: push @{ $Apache::londefdef::table[-1]{'align'}[$Apache::londefdef::table[-1]{'row_number'}] }, $alignchar; 2674: $Apache::londefdef::table[-1]{'counter_columns'}++; 2675: my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); 2676: if (defined $TeXwidth) { 2677: my $current_length=&recalc($TeXwidth); 2678: $current_length=~/(\d+\.?\d*)/; 2679: push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$1; 2680: } 2681: &Apache::lonxml::startredirection(); 2682: return ''; 2683: } 2684: 2685: sub end_th_tex { 2686: my ($parstack,$parser,$safeeval) = @_; 2687: my $current_row = $Apache::londefdef::table[-1]{'row_number'}; 2688: my $data=&Apache::lonxml::endredirection(); 2689: my $TeXwidth=&Apache::lonxml::get_param('TeXwidth',$parstack,$safeeval,undef,0); 2690: if (defined $TeXwidth) { 2691: push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2692: push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2693: push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2694: } else { 2695: if (($data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) or ($data=~m/\[(\d+\.?\d*)\s*mm\]/)) { 2696: my $garbage_data=$data; 2697: my $fwidth=0; 2698: while ($garbage_data=~m/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)/) { 2699: my $current_length=&recalc($1); 2700: $current_length=~/(\d+\.?\d*)/; 2701: if ($fwidth<$1) {$fwidth=$1;} 2702: $garbage_data=~s/width\s*=\s*(\d+\.?\d*\s*(mm|cm|in|pc|pt)*)//; 2703: } 2704: while ($garbage_data=~m/\[(\d+\.?\d*)\s*mm\]/) { 2705: my $current_length=$1; 2706: if ($fwidth<$current_length) {$fwidth=$current_length;} 2707: $garbage_data=~s/\[(\d+\.?\d*)\s*mm\]//; 2708: } 2709: push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2710: push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$fwidth; 2711: push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2712: push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2713: } else { 2714: $data=~s/^\s+(\S.*)/$1/; 2715: $data=~s/(.*\S)\s+$/$1/; 2716: $data=~s/(\s)+/$1/; 2717: my ($current_length,$min_length)=(0,0); 2718: if ($data=~/\\vskip/) { 2719: my $newdata=$data; 2720: $newdata=~s/\\vskip \d*\.?\d*\s*mm/THISISJUSTTEMPORARYSEPARATOR/g; 2721: my @newdata=split(/THISISJUSTTEMPORARYSEPARATOR/,$newdata); 2722: foreach my $elementdata (@newdata) { 2723: my $lengthnewdata=2.5*&LATEX_length($elementdata); 2724: if ($lengthnewdata>$current_length) {$current_length=$lengthnewdata;} 2725: my @words=split(/ /,$elementdata); 2726: foreach my $word (@words) { 2727: my $lengthword=2.5*&LATEX_length($word); 2728: if ($min_length<$lengthword) {$min_length=$lengthword;} 2729: } 2730: } 2731: } else { 2732: $current_length=2.5*&LATEX_length($data); 2733: my @words=split(/ /,$data); 2734: foreach my $word (@words) { 2735: my $lengthword=2*&LATEX_length($word); 2736: if ($min_length<$lengthword) {$min_length=$lengthword;} 2737: } 2738: } 2739: push @ {$Apache::londefdef::table[-1]{'TeXlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2740: push @ {$Apache::londefdef::table[-1]{'objectlen'}[$Apache::londefdef::table[-1]{'row_number'}] },'0'; 2741: push @ {$Apache::londefdef::table[-1]{'maxlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$current_length; 2742: push @ {$Apache::londefdef::table[-1]{'minlen'}[$Apache::londefdef::table[-1]{'row_number'}] },$min_length; 2743: } 2744: } 2745: for (my $in=0; $in<=$#{$Apache::londefdef::table[-1]{'include'}};$in++) { 2746: $data=~s/\\keephidden\{NEW TABLE ENTRY\}/$Apache::londefdef::table[-1]{'include'}[$in]/; 2747: } 2748: #make data bold 2749: $data='\textbf{'.$data.'}'; 2750: push @ {$Apache::londefdef::table[-1]{'content'}[-1] },$data; 2751: return''; 2752: } 2753: 2754: sub end_th { 2755: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 2756: my $currentstring = &end_p(); # Close any open <p> in the row. 2757: if ($target eq 'web' || $target eq 'webgrade') { 2758: $currentstring .= $token->[2]; 2759: } elsif ($target eq 'tex') { 2760: $Apache::londefdef::TD_redirection =0; 2761: &end_th_tex($parstack,$parser,$safeeval); 2762: } 2763: return $currentstring; 2764: } 2765: 2766: #-- <img> tag (end tag forbidden) 2767: # 2768: # Render the <IMG> tag. 2769: # <IMG> has the following attributes (in addition to the 2770: # standard HTML ones: 2771: # TeXwrap - Governs how the tex target will try to wrap text around 2772: # horizontally aligned images. 2773: # TeXwidth - The width of the image when rendered for print (mm). 2774: # TeXheight - The height of the image when rendered for print (mm) 2775: # (Note there seems to also be support for this as a % of page size) 2776: # 2777: sub start_img { 2778: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style) = @_; 2779: my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval, 2780: undef,1); 2781: if (! $src && 2782: ($target eq 'web' || $target eq 'webgrade' || $target eq 'tex') 2783: ) { 2784: my $inside = &Apache::lonxml::get_all_text("/img",$parser,$style); 2785: return ''; 2786: } 2787: &Apache::lonxml::extlink($src); 2788: my $currentstring = ''; 2789: my $scaling = .3; 2790: 2791: # Render unto browsers that which are the browser's... 2792: 2793: if ($target eq 'web' || $target eq 'webgrade') { 2794: if ($env{'browser.imagesuppress'} ne 'on') { 2795: my $enc = ('yes' eq 2796: lc(&Apache::lonxml::get_param('encrypturl',$parstack, 2797: $safeeval))); 2798: $currentstring.=&Apache::lonenc::encrypt_ref($token,{'src'=>$src}, 2799: $enc); 2800: } else { 2801: my $alttag = &Apache::lonxml::get_param('alt',$parstack,$safeeval, 2802: undef,1); 2803: if (!$alttag) { 2804: $alttag = &Apache::lonmeta::alttag($Apache::lonxml::pwd[-1], 2805: $src); 2806: } 2807: $currentstring.='[IMAGE: '.$alttag.']'; 2808: } 2809: 2810: # and render unto TeX that which is LaTeX 2811: 2812: } elsif ($target eq 'tex') { 2813: # 2814: # The alignment will require some superstructure to be put around 2815: # the \includegraphics stuff. At present we can only partially 2816: # simulate the alignments offered by html. 2817: # 2818: # 2819: my $align = lc(&Apache::lonxml::get_param('align', 2820: $parstack, 2821: $safeeval, 2822: undef,1)); 2823: if(!$align) { 2824: $align = "bottom"; # This is html's default so it's ours too. 2825: } 2826: # 2827: &Apache::lonxml::debug("Alignemnt = $align"); 2828: # LaTeX's image/text wrapping is really bad since it wants to 2829: # make figures float. 2830: # The user has the optional parameter (applicable only to l/r 2831: # alignment to use the picins/parpic directive to get wrapped text 2832: # this is also imperfect.. that's why we give them a choice... 2833: # so they can't yell at us for our choice. 2834: # 2835: my $latex_rendering = &Apache::lonxml::get_param('TeXwrap', 2836: $parstack, 2837: $safeeval, 2838: undef,0); 2839: # &Apache::lonxml::debug("LaTeX rendering = $latex_rendering"); 2840: if(!$latex_rendering) { 2841: $latex_rendering = "texwrap"; 2842: } 2843: # using texwrap inside a table does not work. So, if after all of this, 2844: # texwrap is on, we turn it off if we detect we're in a table: 2845: # 2846: if (($latex_rendering eq 'texwrap') && &is_inside_of($tagstack, "table")) { 2847: $latex_rendering = 'parpic'; 2848: } 2849: 2850: # &Apache::lonxml::debug("LaTeX rendering = $latex_rendering image file: $src"); 2851: 2852: #if original gif/jpg/png file exist do following: 2853: my $origsrc=$src; 2854: my ($path,$file) = &get_eps_image($src); 2855: # &Apache::lonnet::logthis("Image source: $src result: $path $file"); 2856: $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src); 2857: &Apache::lonxml::debug("path = $path file = $file src = $src"); 2858: if (-e $src) { 2859: &Apache::lonxml::debug("$src exists"); 2860: my ($height_param,$width_param)= 2861: &image_size($origsrc,0.3,$parstack,$safeeval); 2862: my $size; 2863: if ($width_param) { $size.='width='.$width_param.' mm,'; } 2864: if ($height_param) { $size.='height='.$height_param.' mm]'; } 2865: # Default size if not able to extract that (e.g. eps image). 2866: 2867: # &Apache::lonnet::logthis("Size = $size"); 2868: 2869: $size='['.$size; 2870: $size=~s/,$/]/; 2871: $currentstring .= '\graphicspath{{'.$path.'}}' 2872: .'\includegraphics'.$size.'{'.$file.'} '; 2873: 2874: # If there's an alignment specification we need to honor it here. 2875: # For the horizontal alignments, we will also honor the 2876: # value of the latex specfication. The default is parbox, 2877: # and that's used for illegal values too. 2878: # 2879: # Even though we set a default alignment value, the user 2880: # could have given us an illegal value. In that case we 2881: # just use the default alignment of bottom.. 2882: if ($align eq "top") { 2883: $currentstring = '\raisebox{-'.$height_param.'mm}{'.$currentstring.'}'; 2884: } elsif (($align eq "center") || ($align eq "middle")) { # Being kind 2885: my $offset = $height_param/2; 2886: $currentstring = '\raisebox{-'.$offset.'mm}{'.$currentstring.'}'; 2887: } elsif ($align eq "left") { 2888: if ($latex_rendering eq "parpic") { 2889: $currentstring = '\parpic[l]{'.$currentstring.'}'; 2890: } else { # wrapfig render 2891: $currentstring = '\begin{wrapfigure}{l}{'.$width_param.'mm}' 2892: .'\scalebox{1.0}{'.$currentstring.'}\end{wrapfigure}'; 2893: } 2894: } elsif ($align eq "right") { 2895: if ($latex_rendering eq "parpic") { 2896: $currentstring = '\parpic[r]{'.$currentstring.'}'; 2897: } else { # wrapfig rendering 2898: $currentstring = '\begin{wrapfigure}{r}{'.$width_param.'mm}' 2899: .'\scalebox{1.0}{'.$currentstring.'}\end{wrapfigure}'; 2900: 2901: } 2902: } else { # Bottom is also default. 2903: # $currentstring = '\raisebox{'.$height_param.'mm}{'.$currentstring.'}'; 2904: } 2905: } else { 2906: &Apache::lonxml::debug("$src does not exist"); 2907: #original image file doesn't exist so check the alt attribute 2908: my $alt = 2909: &Apache::lonxml::get_param('alt',$parstack,$safeeval,undef,1); 2910: unless ($alt) { 2911: $alt=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],$src); 2912: } 2913: 2914: if ($alt) { $currentstring .= ' '.$alt.' '; } 2915: } 2916: 2917: # And here's where the semi-quote breaks down: allow the user 2918: # to edit the beast as well by rendering the problem for edit: 2919: } elsif ($target eq 'edit') { 2920: $currentstring .=&Apache::edit::tag_start($target,$token); 2921: $currentstring .=&Apache::edit::text_arg('Image Url:','src',$token,70). 2922: &Apache::edit::browse('src',undef,'alt').' '. 2923: &Apache::edit::search('src',undef,'alt').'<br />'; 2924: $currentstring .=&Apache::edit::text_arg('Description:','alt',$token,70).'<br />'; 2925: $currentstring .=&Apache::edit::text_arg('width (pixel):','width',$token,5); 2926: $currentstring .=&Apache::edit::text_arg('height (pixel):','height',$token,5).'<br />'; 2927: $currentstring .=&Apache::edit::text_arg('TeXwidth (mm):','TeXwidth',$token,5); 2928: $currentstring .=&Apache::edit::text_arg('TeXheight (mm):','TeXheight',$token,5); 2929: $currentstring .=&Apache::edit::select_arg('Alignment:','align', 2930: ['','bottom','middle','top','left','right'],$token,5); 2931: $currentstring .=&Apache::edit::select_arg('TeXwrap:', 'TeXwrap', 2932: ['', 'parbox', 'parpic'], $token, 2); 2933: $currentstring .=&Apache::edit::select_arg('Encrypt URL:','encrypturl', 2934: ['no','yes'], $token, 2); 2935: $currentstring .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); 2936: my $src= &Apache::lonxml::get_param('src',$parstack,$safeeval); 2937: my $alt= &Apache::lonxml::get_param('alt',$parstack,$safeeval); 2938: my $width= &Apache::lonxml::get_param('width',$parstack,$safeeval); 2939: my $height= &Apache::lonxml::get_param('height',$parstack,$safeeval); 2940: 2941: 2942: $currentstring .= '<img src="'.$src.'" alt="'.$alt.'" '; 2943: if ($width) { $currentstring.=' width="'.$width.'" '; } 2944: if ($height) { $currentstring.=' height="'.$height.'" '; } 2945: $currentstring .= ' />'; 2946: } elsif ($target eq 'modified') { 2947: my ($osrc,$owidth,$oheight)= 2948: ($token->[2]{'src'},$token->[2]{'width'},$token->[2]{'height'}); 2949: my $ctag=&Apache::edit::get_new_args($token,$parstack, 2950: $safeeval,'src','alt','align', 2951: 'TeXwidth','TeXheight', 'TeXwrap', 2952: 'width','height','encrypturl'); 2953: my ($nsrc,$nwidth,$nheight)= 2954: ($token->[2]{'src'},$token->[2]{'width'},$token->[2]{'height'}); 2955: my $loc=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$nsrc); 2956: &image_replication($loc); 2957: my ($iwidth,$iheight); 2958: if (-e $loc) { 2959: my $image = Image::Magick->new; 2960: $image->Read($loc); 2961: ($iwidth, $iheight) = ($image->Get('width'), 2962: $image->Get('height')); 2963: } 2964: if ($osrc ne $nsrc || (!$nwidth && !$nheight)) { 2965: # changed image or no size specified, 2966: # if they didn't explicitly change the 2967: # width or height use the ones from the image 2968: if ($iwidth && $iheight) { 2969: if ($owidth == $nwidth || (!$nwidth && !$nheight)) { 2970: $token->[2]{'width'} = $iwidth;$ctag=1; 2971: } 2972: if ($oheight == $nheight || (!$nwidth && !$nheight)) { 2973: $token->[2]{'height'}=$iheight;$ctag=1; 2974: } 2975: } 2976: } 2977: my ($cwidth,$cheight)=($token->[2]{'width'},$token->[2]{'height'}); 2978: # if we don't have a width or height 2979: if ($iwidth && $cwidth && !$cheight) { 2980: $token->[2]{'height'}=int(($cwidth/$iwidth)*$iheight);$ctag=1; 2981: } 2982: if ($iheight && $cheight && !$cwidth) { 2983: $token->[2]{'width'}=int(($cheight/$iheight)*$iwidth);$ctag=1; 2984: } 2985: if ($ctag) {$currentstring=&Apache::edit::rebuild_tag($token);} 2986: } 2987: 2988: return $currentstring; 2989: } 2990: 2991: sub end_img { 2992: my ($target,$token) = @_; 2993: my $currentstring = ''; 2994: if ($target eq 'web' || $target eq 'webgrade') { 2995: $currentstring = $token->[2]; 2996: } elsif ($target eq 'tex') { 2997: $currentstring = ''; 2998: } 2999: return $currentstring; 3000: } 3001: 3002: #-- <applet> tag (end tag required) 3003: sub start_applet { 3004: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3005: 3006: my $code=&Apache::lonxml::get_param('code',$parstack,$safeeval,undef,1); 3007: &Apache::lonxml::extlink($code); 3008: my $archive=&Apache::lonxml::get_param('archive',$parstack,$safeeval, 3009: undef,1); 3010: &Apache::lonxml::extlink($archive); 3011: my $currentstring = ''; 3012: if ($target eq 'web' || $target eq 'webgrade') { 3013: if ($env{'browser.appletsuppress'} ne 'on') { 3014: $currentstring = &Apache::lonenc::encrypt_ref($token, 3015: {'code'=>$code, 3016: 'archive'=>$archive} 3017: ); 3018: } else { 3019: my $alttag= &Apache::lonxml::get_param('alt',$parstack, 3020: $safeeval,undef,1); 3021: unless ($alttag) { 3022: $alttag=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1], 3023: $code); 3024: } 3025: $currentstring='[APPLET: '.$alttag.']'; 3026: } 3027: } elsif ($target eq 'tex') { 3028: my $alttag= &Apache::lonxml::get_param('alt',$parstack, 3029: $safeeval,undef,1); 3030: unless ($alttag) { 3031: my $code=&Apache::lonxml::get_param('code',$parstack,$safeeval, 3032: undef,1); 3033: $alttag=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1], 3034: $code); 3035: } 3036: $currentstring.='\begin{center} \fbox{Java Applet: '.$alttag. 3037: '.}\end{center}'; 3038: } 3039: return $currentstring; 3040: } 3041: 3042: sub end_applet { 3043: my ($target,$token) = @_; 3044: my $currentstring = ''; 3045: if ($target eq 'web' || $target eq 'webgrade') { 3046: $currentstring = $token->[2]; 3047: } elsif ($target eq 'tex') { 3048: } 3049: return $currentstring; 3050: } 3051: 3052: #-- <embed> tag (end tag optional/required) 3053: sub start_embed { 3054: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3055: my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); 3056: &Apache::lonxml::extlink($src); 3057: my $currentstring = ''; 3058: if ($target eq 'web' || $target eq 'webgrade') { 3059: if ($env{'browser.embedsuppress'} ne 'on') { 3060: $currentstring=&Apache::lonenc::encrypt_ref($token,{'src'=>$src}); 3061: } else { 3062: my $alttag=&Apache::lonxml::get_param 3063: ('alt',$parstack,$safeeval,undef,1); 3064: unless ($alttag) { 3065: $alttag=&Apache::lonmeta::alttag($Apache::lonxml::pwd[-1],$src); 3066: } 3067: $currentstring='[EMBED: '.$alttag.']'; 3068: } 3069: } elsif ($target eq 'tex') { 3070: } 3071: return $currentstring; 3072: } 3073: 3074: sub end_embed { 3075: my ($target,$token) = @_; 3076: my $currentstring = ''; 3077: if ($target eq 'web' || $target eq 'webgrade') { 3078: $currentstring = $token->[2]; 3079: } elsif ($target eq 'tex') { 3080: } 3081: return $currentstring; 3082: } 3083: 3084: #-- <param> tag (end tag forbidden) 3085: sub start_param { 3086: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3087: if (&Apache::lonxml::get_param('name',$parstack, 3088: $safeeval,undef,1)=~/^cabbase$/i) { 3089: my $value=&Apache::lonxml::get_param('value',$parstack, 3090: $safeeval,undef,1); 3091: &Apache::lonxml::extlink($value); 3092: } 3093: 3094: my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); 3095: &Apache::lonxml::extlink($src); 3096: my $currentstring = ''; 3097: if ($target eq 'web' || $target eq 'webgrade') { 3098: my %toconvert; 3099: my $src=&Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); 3100: if ($src) { $toconvert{'src'}= $src; } 3101: my $name=&Apache::lonxml::get_param('name',$parstack,$safeeval, 3102: undef,1); 3103: if ($name=~/^cabbase$/i) { 3104: $toconvert{'value'}=&Apache::lonxml::get_param('value',$parstack, 3105: $safeeval,undef,1); 3106: } 3107: $currentstring = &Apache::lonenc::encrypt_ref($token,\%toconvert); 3108: } elsif ($target eq 'tex') { 3109: } 3110: return $currentstring; 3111: } 3112: 3113: sub end_param { 3114: my ($target,$token) = @_; 3115: my $currentstring = ''; 3116: if ($target eq 'web' || $target eq 'webgrade') { 3117: $currentstring = $token->[2]; 3118: } elsif ($target eq 'tex') { 3119: } 3120: return $currentstring; 3121: } 3122: 3123: #-- <allow> tag 3124: sub start_allow { 3125: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3126: my $src = &Apache::lonxml::get_param('src',$parstack,$safeeval,undef,1); 3127: &Apache::lonxml::extlink($src); 3128: 3129: if ($target eq 'tex') { &image_replication($src); } 3130: my $result; 3131: if ($target eq 'edit') { 3132: $result .=&Apache::edit::tag_start($target,$token); 3133: $result .=&Apache::edit::text_arg('File Spec:','src',$token,70); 3134: $result .=&Apache::edit::end_row();#.&Apache::edit::start_spanning_row(); 3135: } elsif ($target eq 'modified') { 3136: my $constructtag=&Apache::edit::get_new_args($token,$parstack, 3137: $safeeval,'src'); 3138: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } 3139: } 3140: return $result; 3141: } 3142: 3143: sub end_allow { 3144: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3145: if ( $target eq 'edit') { return (&Apache::edit::end_table()); } 3146: return ''; 3147: } 3148: 3149: #-- Frames (end tag required) 3150: #-- <frameset> 3151: sub start_frameset { 3152: my ($target,$token) = @_; 3153: my $currentstring = ''; # Close any pending para. 3154: if ($target eq 'web' || $target eq 'webgrade') { 3155: $currentstring = 3156: &Apache::loncommon::start_page($Apache::londefdef::title, 3157: $Apache::londefdef::head, 3158: {'add_entries' => $token->[2], 3159: 'no_title' => 1, 3160: 'force_register' => 1, 3161: 'frameset' => 1,}); 3162: 3163: } 3164: return $currentstring; 3165: } 3166: 3167: sub end_frameset { 3168: my ($target,$token) = @_; 3169: my $currentstring = ''; 3170: if ($target eq 'web' || $target eq 'webgrade') { 3171: $currentstring = $token->[2]; 3172: } 3173: return $currentstring; 3174: } 3175: 3176: #-- <xmp> (end tag required) 3177: sub start_xmp { 3178: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3179: my $currentstring = ''; 3180: if ($target eq 'web' || $target eq 'webgrade') { 3181: $currentstring .= $token->[4]; 3182: } elsif ($target eq 'tex') { 3183: $currentstring .= '\begin{verbatim}'; 3184: } 3185: return $currentstring; 3186: } 3187: 3188: sub end_xmp { 3189: my ($target,$token) = @_; 3190: my $currentstring = ''; 3191: if ($target eq 'web' || $target eq 'webgrade') { 3192: $currentstring .= $token->[2]; 3193: } elsif ($target eq 'tex') { 3194: $currentstring .= '\end{verbatim}'; 3195: } 3196: return $currentstring; 3197: } 3198: 3199: #-- <pre> (end tag required) 3200: sub start_pre { 3201: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3202: my $currentstring = &end_p(); # close off pending <p> 3203: if ($target eq 'web' || $target eq 'webgrade') { 3204: $currentstring .= $token->[4]; 3205: } elsif ($target eq 'tex') { 3206: $currentstring .= '\begin{verbatim}'; 3207: &Apache::lonxml::disable_LaTeX_substitutions(); 3208: } 3209: return $currentstring; 3210: } 3211: 3212: sub end_pre { 3213: my ($target,$token) = @_; 3214: my $currentstring = ''; 3215: if ($target eq 'web' || $target eq 'webgrade') { 3216: $currentstring .= $token->[2]; 3217: } elsif ($target eq 'tex') { 3218: $currentstring .= '\end{verbatim}'; 3219: &Apache::lonxml::enable_LaTeX_substitutions(); 3220: } 3221: return $currentstring; 3222: } 3223: 3224: #-- <insert> 3225: sub start_insert { 3226: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3227: my $currentstring = ''; 3228: if ($target eq 'web' || $target eq 'webgrade') { 3229: my $display = &Apache::lonxml::get_param('display',$parstack,$safeeval,undef,1); 3230: $currentstring .= '<b>'.$display.'</b>';; 3231: } 3232: return $currentstring; 3233: } 3234: 3235: sub end_insert { 3236: my ($target,$token) = @_; 3237: my $currentstring = ''; 3238: if ($target eq 'web' || $target eq 'webgrade') { 3239: $currentstring .= ''; 3240: } 3241: return $currentstring; 3242: } 3243: 3244: #-- <externallink> 3245: sub start_externallink { 3246: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3247: my $currentstring = ''; 3248: if ($target eq 'web' || $target eq 'webgrade') { 3249: my $display = &Apache::lonxml::get_param('display',$parstack,$safeeval,undef,1); 3250: $currentstring .= '<b>'.$display.'</b>';; 3251: } 3252: return $currentstring; 3253: } 3254: 3255: sub end_externallink { 3256: my ($target,$token) = @_; 3257: my $currentstring = ''; 3258: if ($target eq 'web' || $target eq 'webgrade') { 3259: $currentstring .= ''; 3260: } 3261: return $currentstring; 3262: } 3263: 3264: #-- <blankspace heigth=""> 3265: sub start_blankspace { 3266: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3267: my $currentstring = &end_p(); # closes off any unclosed <p> 3268: if ($target eq 'tex') { 3269: my $howmuch = &Apache::lonxml::get_param('heigth',$parstack,$safeeval,undef,1); 3270: $currentstring .= '\vskip '.$howmuch.' '; 3271: } 3272: return $currentstring; 3273: } 3274: 3275: sub end_blankspace { 3276: my ($target,$token) = @_; 3277: my $currentstring = ''; 3278: if ($target eq 'tex') { 3279: $currentstring .= ''; 3280: } 3281: return $currentstring; 3282: } 3283: 3284: #-- <abbr> tag (end tag required) 3285: sub start_abbr { 3286: my ($target,$token) = @_; 3287: my $currentstring = ''; 3288: if ($target eq 'web' || $target eq 'webgrade') { 3289: $currentstring = $token->[4]; 3290: } 3291: return $currentstring; 3292: } 3293: 3294: sub end_abbr { 3295: my ($target,$token) = @_; 3296: my $currentstring = ''; 3297: if ($target eq 'web' || $target eq 'webgrade') { 3298: $currentstring = $token->[2]; 3299: } 3300: return $currentstring; 3301: } 3302: 3303: #-- <acronym> tag (end tag required) 3304: sub start_acronym { 3305: my ($target,$token) = @_; 3306: my $currentstring = ''; 3307: if ($target eq 'web' || $target eq 'webgrade') { 3308: $currentstring = $token->[4]; 3309: } 3310: return $currentstring; 3311: } 3312: 3313: sub end_acronym { 3314: my ($target,$token) = @_; 3315: my $currentstring = ''; 3316: if ($target eq 'web' || $target eq 'webgrade') { 3317: $currentstring = $token->[2]; 3318: } 3319: return $currentstring; 3320: } 3321: 3322: #-- <area> tag (end tag forbidden) 3323: sub start_area { 3324: my ($target,$token) = @_; 3325: my $currentstring = ''; 3326: if ($target eq 'web' || $target eq 'webgrade') { 3327: $currentstring = $token->[4]; 3328: } 3329: return $currentstring; 3330: } 3331: 3332: sub end_area { 3333: my ($target,$token) = @_; 3334: my $currentstring = ''; 3335: if ($target eq 'web' || $target eq 'webgrade') { 3336: $currentstring = $token->[2]; 3337: } 3338: return $currentstring; 3339: } 3340: 3341: #-- <base> tag (end tag forbidden) 3342: sub start_base { 3343: my ($target,$token) = @_; 3344: my $currentstring = ''; 3345: if ($target eq 'web' || $target eq 'webgrade') { 3346: $currentstring = $token->[4]; 3347: } 3348: return $currentstring; 3349: } 3350: 3351: sub end_base { 3352: my ($target,$token) = @_; 3353: my $currentstring = ''; 3354: if ($target eq 'web' || $target eq 'webgrade') { 3355: $currentstring = $token->[2]; 3356: } 3357: return $currentstring; 3358: } 3359: 3360: #-- <bdo> tag (end tag required) 3361: sub start_bdo { 3362: my ($target,$token) = @_; 3363: my $currentstring = ''; 3364: if ($target eq 'web' || $target eq 'webgrade') { 3365: $currentstring = $token->[4]; 3366: } 3367: return $currentstring; 3368: } 3369: 3370: sub end_bdo { 3371: my ($target,$token) = @_; 3372: my $currentstring = ''; 3373: if ($target eq 'web' || $target eq 'webgrade') { 3374: $currentstring = $token->[2]; 3375: } 3376: return $currentstring; 3377: } 3378: 3379: #-- <bgsound> tag (end tag optional) 3380: sub start_bgsound { 3381: my ($target,$token) = @_; 3382: my $currentstring = ''; 3383: if ($target eq 'web' || $target eq 'webgrade') { 3384: $currentstring = $token->[4]; 3385: } 3386: return $currentstring; 3387: } 3388: 3389: sub end_bgsound { 3390: my ($target,$token) = @_; 3391: my $currentstring = ''; 3392: if ($target eq 'web' || $target eq 'webgrade') { 3393: $currentstring = $token->[2]; 3394: } 3395: return $currentstring; 3396: } 3397: 3398: #-- <blink> tag (end tag required) 3399: sub start_blink { 3400: my ($target,$token) = @_; 3401: my $currentstring = ''; 3402: if ($target eq 'web' || $target eq 'webgrade') { 3403: $currentstring = $token->[4]; 3404: } 3405: return $currentstring; 3406: } 3407: 3408: sub end_blink { 3409: my ($target,$token) = @_; 3410: my $currentstring = ''; 3411: if ($target eq 'web' || $target eq 'webgrade') { 3412: $currentstring = $token->[2]; 3413: } 3414: return $currentstring; 3415: } 3416: 3417: #-- <blockquote> tag (end tag required) 3418: sub start_blockquote { 3419: my ($target,$token) = @_; 3420: my $currentstring = &end_p(); # Close any unclosed <p> 3421: if ($target eq 'web' || $target eq 'webgrade') { 3422: $currentstring .= $token->[4]; 3423: } 3424: if ($target eq 'tex') { 3425: $currentstring .= '\begin{quote}'; 3426: } 3427: return $currentstring; 3428: } 3429: 3430: sub end_blockquote { 3431: my ($target,$token) = @_; 3432: my $currentstring = ''; 3433: if ($target eq 'web' || $target eq 'webgrade') { 3434: $currentstring = $token->[2]; 3435: } 3436: if ($target eq 'tex') { 3437: $currentstring = '\end{quote}'; 3438: } 3439: return $currentstring; 3440: } 3441: 3442: #-- <button> tag (end tag required) 3443: sub start_button { 3444: my ($target,$token) = @_; 3445: my $currentstring = ''; 3446: if ($target eq 'web' || $target eq 'webgrade') { 3447: $currentstring = $token->[4]; 3448: } 3449: return $currentstring; 3450: } 3451: 3452: sub end_button { 3453: my ($target,$token) = @_; 3454: my $currentstring = ''; 3455: if ($target eq 'web' || $target eq 'webgrade') { 3456: $currentstring = $token->[2]; 3457: } 3458: return $currentstring; 3459: } 3460: 3461: #-- <caption> tag (end tag required) 3462: sub start_caption { 3463: my ($target,$token) = @_; 3464: my $currentstring = ''; 3465: if ($target eq 'web' || $target eq 'webgrade') { 3466: $currentstring = $token->[4]; 3467: } 3468: return $currentstring; 3469: } 3470: 3471: sub end_caption { 3472: my ($target,$token) = @_; 3473: my $currentstring = ''; 3474: if ($target eq 'web' || $target eq 'webgrade') { 3475: $currentstring = $token->[2]; 3476: } 3477: return $currentstring; 3478: } 3479: 3480: #-- <col> tag (end tag forbdden) 3481: sub start_col { 3482: my ($target,$token) = @_; 3483: my $currentstring = ''; 3484: if ($target eq 'web' || $target eq 'webgrade') { 3485: $currentstring = $token->[4]; 3486: } 3487: return $currentstring; 3488: } 3489: 3490: sub end_col { 3491: my ($target,$token) = @_; 3492: my $currentstring = ''; 3493: if ($target eq 'web' || $target eq 'webgrade') { 3494: $currentstring = $token->[2]; 3495: } 3496: return $currentstring; 3497: } 3498: 3499: #-- <colgroup> tag (end tag optional) 3500: sub start_colgroup { 3501: my ($target,$token) = @_; 3502: my $currentstring = ''; 3503: if ($target eq 'web' || $target eq 'webgrade') { 3504: $currentstring = $token->[4]; 3505: } 3506: return $currentstring; 3507: } 3508: 3509: sub end_colgroup { 3510: my ($target,$token) = @_; 3511: my $currentstring = ''; 3512: if ($target eq 'web' || $target eq 'webgrade') { 3513: $currentstring = $token->[2]; 3514: } 3515: return $currentstring; 3516: } 3517: 3518: #-- <del> tag (end tag required) 3519: sub start_del { 3520: my ($target,$token) = @_; 3521: my $currentstring = ''; 3522: if ($target eq 'web' || $target eq 'webgrade') { 3523: $currentstring = $token->[4]; 3524: } 3525: return $currentstring; 3526: } 3527: 3528: sub end_del { 3529: my ($target,$token) = @_; 3530: my $currentstring = ''; 3531: if ($target eq 'web' || $target eq 'webgrade') { 3532: $currentstring = $token->[2]; 3533: } 3534: return $currentstring; 3535: } 3536: 3537: #-- <fieldset> tag (end tag required) 3538: sub start_fieldset { 3539: my ($target,$token) = @_; 3540: my $currentstring = ''; 3541: if ($target eq 'web' || $target eq 'webgrade') { 3542: $currentstring = $token->[4]; 3543: } 3544: return $currentstring; 3545: } 3546: 3547: sub end_fieldset { 3548: my ($target,$token) = @_; 3549: my $currentstring = ''; 3550: if ($target eq 'web' || $target eq 'webgrade') { 3551: $currentstring = $token->[2]; 3552: } 3553: return $currentstring; 3554: } 3555: 3556: #-- <frame> tag (end tag forbidden) 3557: sub start_frame { 3558: my ($target,$token) = @_; 3559: my $currentstring = ''; 3560: if ($target eq 'web' || $target eq 'webgrade') { 3561: $currentstring = $token->[4]; 3562: } 3563: return $currentstring; 3564: } 3565: 3566: sub end_frame { 3567: my ($target,$token) = @_; 3568: my $currentstring = ''; 3569: if ($target eq 'web' || $target eq 'webgrade') { 3570: $currentstring = $token->[2]; 3571: } 3572: return $currentstring; 3573: } 3574: 3575: #-- <iframe> tag (end tag required) 3576: sub start_iframe { 3577: my ($target,$token) = @_; 3578: my $currentstring = ''; 3579: if ($target eq 'web' || $target eq 'webgrade') { 3580: $currentstring = $token->[4]; 3581: } 3582: return $currentstring; 3583: } 3584: 3585: sub end_iframe { 3586: my ($target,$token) = @_; 3587: my $currentstring = ''; 3588: if ($target eq 'web' || $target eq 'webgrade') { 3589: $currentstring = $token->[2]; 3590: } 3591: return $currentstring; 3592: } 3593: 3594: #-- <ins> tag (end tag required) 3595: sub start_ins { 3596: my ($target,$token) = @_; 3597: my $currentstring = ''; 3598: if ($target eq 'web' || $target eq 'webgrade') { 3599: $currentstring = $token->[4]; 3600: } 3601: return $currentstring; 3602: } 3603: 3604: sub end_ins { 3605: my ($target,$token) = @_; 3606: my $currentstring = ''; 3607: if ($target eq 'web' || $target eq 'webgrade') { 3608: $currentstring = $token->[2]; 3609: } 3610: return $currentstring; 3611: } 3612: 3613: #-- <isindex> tag (end tag forbidden) 3614: sub start_isindex { 3615: my ($target,$token) = @_; 3616: my $currentstring = ''; 3617: if ($target eq 'web' || $target eq 'webgrade') { 3618: $currentstring = $token->[4]; 3619: } 3620: return $currentstring; 3621: } 3622: 3623: sub end_isindex { 3624: my ($target,$token) = @_; 3625: my $currentstring = ''; 3626: if ($target eq 'web' || $target eq 'webgrade') { 3627: $currentstring = $token->[2]; 3628: } 3629: return $currentstring; 3630: } 3631: 3632: #-- <keygen> tag (end tag forbidden) 3633: sub start_keygen { 3634: my ($target,$token) = @_; 3635: my $currentstring = ''; 3636: if ($target eq 'web' || $target eq 'webgrade') { 3637: $currentstring = $token->[4]; 3638: } 3639: return $currentstring; 3640: } 3641: 3642: sub end_keygen { 3643: my ($target,$token) = @_; 3644: my $currentstring = ''; 3645: if ($target eq 'web' || $target eq 'webgrade') { 3646: $currentstring = $token->[2]; 3647: } 3648: return $currentstring; 3649: } 3650: 3651: #-- <label> tag 3652: sub start_label { 3653: my ($target,$token) = @_; 3654: my $currentstring = ''; 3655: if ($target eq 'web' || $target eq 'webgrade') { 3656: $currentstring = $token->[4]; 3657: } 3658: return $currentstring; 3659: } 3660: 3661: sub end_label { 3662: my ($target,$token) = @_; 3663: my $currentstring = ''; 3664: if ($target eq 'web' || $target eq 'webgrade') { 3665: $currentstring = $token->[2]; 3666: } 3667: return $currentstring; 3668: } 3669: 3670: #-- <layer> tag (end tag required) 3671: sub start_layer { 3672: my ($target,$token) = @_; 3673: my $currentstring = ''; 3674: if ($target eq 'web' || $target eq 'webgrade') { 3675: $currentstring = $token->[4]; 3676: } 3677: return $currentstring; 3678: } 3679: 3680: sub end_layer { 3681: my ($target,$token) = @_; 3682: my $currentstring = ''; 3683: if ($target eq 'web' || $target eq 'webgrade') { 3684: $currentstring = $token->[2]; 3685: } 3686: return $currentstring; 3687: } 3688: 3689: #-- <legend> tag (end tag required) 3690: sub start_legend { 3691: my ($target,$token) = @_; 3692: my $currentstring = ''; 3693: if ($target eq 'web' || $target eq 'webgrade') { 3694: $currentstring = $token->[4]; 3695: } 3696: return $currentstring; 3697: } 3698: 3699: sub end_legend { 3700: my ($target,$token) = @_; 3701: my $currentstring = ''; 3702: if ($target eq 'web' || $target eq 'webgrade') { 3703: $currentstring = $token->[2]; 3704: } 3705: return $currentstring; 3706: } 3707: 3708: #-- <link> tag (end tag forbidden) 3709: sub start_link { 3710: my ($target,$token,$tagstack,$parstack,$parser,$safeeval) = @_; 3711: my $currentstring = ''; 3712: if ($target eq 'web' || $target eq 'webgrade') { 3713: my $href=&Apache::lonxml::get_param('href',$parstack,$safeeval, 3714: undef,1); 3715: &Apache::lonxml::extlink($href); 3716: $currentstring = $token->[4]; 3717: } 3718: return $currentstring; 3719: } 3720: 3721: sub end_link { 3722: my ($target,$token) = @_; 3723: my $currentstring = ''; 3724: if ($target eq 'web' || $target eq 'webgrade') { 3725: $currentstring = $token->[2]; 3726: } 3727: return $currentstring; 3728: } 3729: 3730: #-- <marquee> tag (end tag optional) 3731: sub start_marquee { 3732: my ($target,$token) = @_; 3733: my $currentstring = ''; 3734: if ($target eq 'web' || $target eq 'webgrade') { 3735: $currentstring = $token->[4]; 3736: } 3737: return $currentstring; 3738: } 3739: 3740: sub end_marquee { 3741: my ($target,$token) = @_; 3742: my $currentstring = ''; 3743: if ($target eq 'web' || $target eq 'webgrade') { 3744: $currentstring = $token->[2]; 3745: } 3746: return $currentstring; 3747: } 3748: 3749: #-- <multicol> tag (end tag required) 3750: sub start_multicol { 3751: my ($target,$token) = @_; 3752: my $currentstring = &end_p(); # Close any pending <p> 3753: if ($target eq 'web' || $target eq 'webgrade') { 3754: $currentstring .= $token->[4]; 3755: } 3756: return $currentstring; 3757: } 3758: 3759: sub end_multicol { 3760: my ($target,$token) = @_; 3761: my $currentstring = ''; 3762: if ($target eq 'web' || $target eq 'webgrade') { 3763: $currentstring = $token->[2]; 3764: } 3765: return $currentstring; 3766: } 3767: 3768: #-- <nobr> tag (end tag required) 3769: sub start_nobr { 3770: my ($target,$token) = @_; 3771: my $currentstring = ''; 3772: if ($target eq 'web' || $target eq 'webgrade') { 3773: $currentstring = $token->[4]; 3774: } elsif ($target eq 'tex') { 3775: $currentstring='\mbox{'; 3776: } 3777: return $currentstring; 3778: } 3779: 3780: sub end_nobr { 3781: my ($target,$token) = @_; 3782: my $currentstring = ''; 3783: if ($target eq 'web' || $target eq 'webgrade') { 3784: $currentstring = $token->[2]; 3785: } elsif ($target eq 'tex') { 3786: $currentstring='}'; 3787: } 3788: return $currentstring; 3789: } 3790: 3791: #-- <noembed> tag (end tag required) 3792: sub start_noembed { 3793: my ($target,$token) = @_; 3794: my $currentstring = ''; 3795: if ($target eq 'web' || $target eq 'webgrade') { 3796: $currentstring = $token->[4]; 3797: } 3798: return $currentstring; 3799: } 3800: 3801: sub end_noembed { 3802: my ($target,$token) = @_; 3803: my $currentstring = ''; 3804: if ($target eq 'web' || $target eq 'webgrade') { 3805: $currentstring = $token->[2]; 3806: } 3807: return $currentstring; 3808: } 3809: 3810: #-- <noframes> tag (end tag required) 3811: sub start_noframes { 3812: my ($target,$token) = @_; 3813: my $currentstring = ''; 3814: if ($target eq 'web' || $target eq 'webgrade') { 3815: $currentstring = $token->[4]; 3816: } 3817: return $currentstring; 3818: } 3819: 3820: sub end_noframes { 3821: my ($target,$token) = @_; 3822: my $currentstring = ''; 3823: if ($target eq 'web' || $target eq 'webgrade') { 3824: $currentstring = $token->[2]; 3825: } 3826: return $currentstring; 3827: } 3828: 3829: #-- <nolayer> tag (end tag required) 3830: sub start_nolayer { 3831: my ($target,$token) = @_; 3832: my $currentstring = ''; 3833: if ($target eq 'web' || $target eq 'webgrade') { 3834: $currentstring = $token->[4]; 3835: } 3836: return $currentstring; 3837: } 3838: 3839: sub end_nolayer { 3840: my ($target,$token) = @_; 3841: my $currentstring = ''; 3842: if ($target eq 'web' || $target eq 'webgrade') { 3843: $currentstring = $token->[2]; 3844: } 3845: return $currentstring; 3846: } 3847: 3848: #-- <noscript> tag (end tag required) 3849: sub start_noscript { 3850: my ($target,$token) = @_; 3851: my $currentstring = ''; 3852: if ($target eq 'web' || $target eq 'webgrade') { 3853: $currentstring = $token->[4]; 3854: } 3855: return $currentstring; 3856: } 3857: 3858: sub end_noscript { 3859: my ($target,$token) = @_; 3860: my $currentstring = ''; 3861: if ($target eq 'web' || $target eq 'webgrade') { 3862: $currentstring = $token->[2]; 3863: } 3864: return $currentstring; 3865: } 3866: 3867: #-- <object> tag (end tag required) 3868: sub start_object { 3869: my ($target,$token) = @_; 3870: my $currentstring = ''; 3871: if ($target eq 'web' || $target eq 'webgrade') { 3872: $currentstring = $token->[4]; 3873: } 3874: return $currentstring; 3875: } 3876: 3877: sub end_object { 3878: my ($target,$token) = @_; 3879: my $currentstring = ''; 3880: if ($target eq 'web' || $target eq 'webgrade') { 3881: $currentstring = $token->[2]; 3882: } 3883: return $currentstring; 3884: } 3885: 3886: #-- <optgroup> tag (end tag required) 3887: sub start_optgroup { 3888: my ($target,$token) = @_; 3889: my $currentstring = ''; 3890: if ($target eq 'web' || $target eq 'webgrade') { 3891: $currentstring = $token->[4]; 3892: } 3893: return $currentstring; 3894: } 3895: 3896: sub end_optgroup { 3897: my ($target,$token) = @_; 3898: my $currentstring = ''; 3899: if ($target eq 'web' || $target eq 'webgrade') { 3900: $currentstring = $token->[2]; 3901: } 3902: return $currentstring; 3903: } 3904: 3905: #-- <samp> tag (end tag required) 3906: sub start_samp { 3907: my ($target,$token) = @_; 3908: my $currentstring = ''; 3909: if ($target eq 'web' || $target eq 'webgrade') { 3910: $currentstring = $token->[4]; 3911: } elsif ($target eq 'tex') { 3912: $currentstring='\texttt{'; 3913: } 3914: return $currentstring; 3915: } 3916: 3917: sub end_samp { 3918: my ($target,$token) = @_; 3919: my $currentstring = ''; 3920: if ($target eq 'web' || $target eq 'webgrade') { 3921: $currentstring = $token->[2]; 3922: } elsif ($target eq 'tex') { 3923: $currentstring='}'; 3924: } 3925: return $currentstring; 3926: } 3927: 3928: #-- <server> tag 3929: sub start_server { 3930: my ($target,$token) = @_; 3931: my $currentstring = ''; 3932: if ($target eq 'web' || $target eq 'webgrade') { 3933: $currentstring = $token->[4]; 3934: } 3935: return $currentstring; 3936: } 3937: 3938: sub end_server { 3939: my ($target,$token) = @_; 3940: my $currentstring = ''; 3941: if ($target eq 'web' || $target eq 'webgrade') { 3942: $currentstring = $token->[2]; 3943: } 3944: return $currentstring; 3945: } 3946: 3947: #-- <spacer> tag (end tag forbidden) 3948: sub start_spacer { 3949: my ($target,$token) = @_; 3950: my $currentstring = &end_p(); # Close off any open <p> tag. 3951: if ($target eq 'web' || $target eq 'webgrade') { 3952: $currentstring .= $token->[4]; 3953: } 3954: return $currentstring; 3955: } 3956: 3957: sub end_spacer { 3958: my ($target,$token) = @_; 3959: my $currentstring = ''; 3960: if ($target eq 'web' || $target eq 'webgrade') { 3961: $currentstring = $token->[2]; 3962: } 3963: return $currentstring; 3964: } 3965: 3966: #-- <span> tag (end tag required) 3967: sub start_span { 3968: my ($target,$token) = @_; 3969: my $currentstring = ''; 3970: if ($target eq 'web' || $target eq 'webgrade') { 3971: $currentstring = $token->[4]; 3972: } 3973: return $currentstring; 3974: } 3975: 3976: sub end_span { 3977: my ($target,$token) = @_; 3978: my $currentstring = ''; 3979: if ($target eq 'web' || $target eq 'webgrade') { 3980: $currentstring = $token->[2]; 3981: } 3982: return $currentstring; 3983: } 3984: 3985: #-- <tbody> tag (end tag optional) 3986: sub start_tbody { 3987: my ($target,$token) = @_; 3988: my $currentstring = ''; 3989: if ($target eq 'web' || $target eq 'webgrade') { 3990: $currentstring = $token->[4]; 3991: } 3992: return $currentstring; 3993: } 3994: 3995: sub end_tbody { 3996: my ($target,$token) = @_; 3997: my $currentstring = ''; 3998: if ($target eq 'web' || $target eq 'webgrade') { 3999: $currentstring = $token->[2]; 4000: } 4001: return $currentstring; 4002: } 4003: 4004: #-- <tfoot> tag (end tag optional) 4005: sub start_tfoot { 4006: my ($target,$token) = @_; 4007: my $currentstring = ''; 4008: if ($target eq 'web' || $target eq 'webgrade') { 4009: $currentstring = $token->[4]; 4010: } 4011: return $currentstring; 4012: } 4013: 4014: sub end_tfoot { 4015: my ($target,$token) = @_; 4016: my $currentstring = ''; 4017: if ($target eq 'web' || $target eq 'webgrade') { 4018: $currentstring = $token->[2]; 4019: } 4020: return $currentstring; 4021: } 4022: 4023: #-- <thead> tag (end tag optional) 4024: sub start_thead { 4025: my ($target,$token) = @_; 4026: my $currentstring = ''; 4027: if ($target eq 'web' || $target eq 'webgrade') { 4028: $currentstring = $token->[4]; 4029: } 4030: return $currentstring; 4031: } 4032: 4033: sub end_thead { 4034: my ($target,$token) = @_; 4035: my $currentstring = ''; 4036: if ($target eq 'web' || $target eq 'webgrade') { 4037: $currentstring = $token->[2]; 4038: } 4039: return $currentstring; 4040: } 4041: 4042: #-- <var> tag 4043: sub start_var { 4044: my ($target,$token) = @_; 4045: my $currentstring = ''; 4046: if ($target eq 'web' || $target eq 'webgrade') { 4047: $currentstring = $token->[4]; 4048: } elsif ($target eq 'tex') { 4049: $currentstring = '\textit{'; 4050: } 4051: return $currentstring; 4052: } 4053: 4054: sub end_var { 4055: my ($target,$token) = @_; 4056: my $currentstring = ''; 4057: if ($target eq 'web' || $target eq 'webgrade') { 4058: $currentstring = $token->[2]; 4059: } elsif ($target eq 'tex') { 4060: $currentstring = '}'; 4061: } 4062: return $currentstring; 4063: } 4064: 4065: #-- <wbr> tag (end tag forbidden) 4066: sub start_wbr { 4067: my ($target,$token) = @_; 4068: my $currentstring = ''; 4069: if ($target eq 'web' || $target eq 'webgrade') { 4070: $currentstring = $token->[4]; 4071: } 4072: return $currentstring; 4073: } 4074: 4075: sub end_wbr { 4076: my ($target,$token) = @_; 4077: my $currentstring = ''; 4078: if ($target eq 'web' || $target eq 'webgrade') { 4079: $currentstring = $token->[2]; 4080: } 4081: return $currentstring; 4082: } 4083: 4084: #-- <hideweboutput> tag 4085: sub start_hideweboutput { 4086: my ($target,$token) = @_; 4087: if ($target eq 'web' || $target eq 'webgrade') { 4088: &Apache::lonxml::startredirection(); 4089: } 4090: return ''; 4091: } 4092: 4093: sub end_hideweboutput { 4094: my ($target,$token) = @_; 4095: my $currentstring = ''; 4096: if ($target eq 'web' || $target eq 'webgrade') { 4097: $currentstring = &Apache::lonxml::endredirection(); 4098: } 4099: return ''; 4100: } 4101: 4102: 4103: sub image_replication { 4104: my $src = shift; 4105: if (not -e $src) { &Apache::lonnet::repcopy($src); } 4106: #replicates eps or ps 4107: my $epssrc = my $pssrc = $src; 4108: $epssrc =~ s/\.(gif|jpg|jpeg|png)$/.eps/i; 4109: $pssrc =~ s/\.(gif|jpg|jpeg|png)$/.ps/i; 4110: if (not -e $epssrc && not -e $pssrc) { 4111: my $result=&Apache::lonnet::repcopy($epssrc); 4112: if ($result ne 'ok') { &Apache::lonnet::repcopy($pssrc); } 4113: } 4114: return ''; 4115: } 4116: # 4117: # Get correct sizing parameter for an image given 4118: # it's initial ht. and wid. This allows sizing of 4119: # images that are generated on-the-fly (e.g. gnuplot) 4120: # as well as serving as a utility for image_size. 4121: # 4122: # Parameter: 4123: # height_param 4124: # width_param - Initial picture dimensions. 4125: # scaling - A scale factor. 4126: # parstack, - the current stack of tag attributes 4127: # from the xml parser 4128: # safeeval, - pointer to the safespace 4129: # depth, - from what level in the stack to look for attributes 4130: # (assumes -1 if unspecified) 4131: # cis - look for attrubutes case insensitively 4132: # (assumes false) 4133: # 4134: # Returns: 4135: # height, width - new dimensions. 4136: # 4137: sub resize_image { 4138: my ($height_param, $width_param, $scaling, 4139: $parstack, $safeeval, $depth, $cis) = @_; 4140: 4141: # First apply the scaling... 4142: 4143: $height_param = $height_param * $scaling; 4144: $width_param = $width_param * $scaling; 4145: 4146: #do we have any specified LaTeX size of the picture? 4147: my $toget='TeXwidth'; 4148: if ($cis) { 4149: $toget=lc($toget); 4150: } 4151: my $TeXwidth = &Apache::lonxml::get_param($toget,$parstack, 4152: $safeeval,$depth,$cis); 4153: $toget='TeXheight'; if ($cis) { $toget=lc($toget); } 4154: my $TeXheight = &Apache::lonxml::get_param($toget,$parstack, 4155: $safeeval,$depth,$cis); 4156: #do we have any specified web size of the picture? 4157: my $width = &Apache::lonxml::get_param('width',$parstack,$safeeval, 4158: $depth,1); 4159: if ($TeXwidth) { 4160: my $old_width_param=$width_param; 4161: if ($TeXwidth=~/(\d+)\s*\%/) { 4162: $width_param = $1*$env{'form.textwidth'}/100; 4163: } else { 4164: $width_param = $TeXwidth; 4165: } 4166: if ($TeXheight) { 4167: $height_param = $TeXheight; 4168: } elsif ($old_width_param) { 4169: $height_param=$TeXwidth/$old_width_param*$height_param; 4170: } 4171: } elsif ($TeXheight) { 4172: $height_param = $TeXheight; 4173: if ($height_param) { 4174: $width_param = $TeXheight/$height_param*$width_param; 4175: } 4176: } elsif ($width) { 4177: my $old_width_param=$width_param; 4178: $width_param = $width*$scaling; 4179: if ($old_width_param) { 4180: $height_param=$width_param/$old_width_param*$height_param; 4181: } 4182: } 4183: if ($width_param > $env{'form.textwidth'}) { 4184: my $old_width_param=$width_param; 4185: $width_param =0.95*$env{'form.textwidth'}; 4186: if ($old_width_param) { 4187: $height_param=$width_param/$old_width_param*$height_param; 4188: } 4189: } 4190: 4191: return ($height_param, $width_param); 4192: } 4193: 4194: sub image_size { 4195: my ($src,$scaling,$parstack,$safeeval,$depth,$cis)=@_; 4196: 4197: #size of image from gif/jpg/jpeg/png 4198: my $ressrc=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src); 4199: if (-e $ressrc) { 4200: $src = $ressrc; 4201: } 4202: my $image = Image::Magick->new; 4203: my $current_figure = $image->Read($src); 4204: my $width_param = $image->Get('width'); 4205: my $height_param = $image->Get('height'); 4206: &Apache::lonxml::debug("Image magick says: $src : Height = $height_param width = $width_param"); 4207: undef($image); 4208: 4209: ($height_param, $width_param) = &resize_image($height_param, $width_param, 4210: $scaling, $parstack, $safeeval, 4211: $depth, $cis); 4212: 4213: return ($height_param, $width_param); 4214: } 4215: 4216: sub image_width { 4217: my ($height, $width) = &image_size(@_); 4218: return $width; 4219: } 4220: # Not yet 100% sure this is correct in all circumstances.. 4221: # due to my uncertainty about mods to image_size. 4222: # 4223: sub image_height { 4224: my ($height, $width) = &image_size(@_); 4225: return $height; 4226: } 4227: 4228: sub get_eps_image { 4229: my ($src)=@_; 4230: my $orig_src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1], $src); 4231: 4232: # In order to prevent the substitution of the alt text, we need to 4233: # be sure the orig_src file is on system now so: 4234: 4235: if (! -e $orig_src) { 4236: &Apache::lonnet::repcopy($orig_src); # Failure is not completely fatal. 4237: } 4238: &Apache::lonxml::debug("get_eps_image: Original image: $orig_src"); 4239: my ($spath, $sname, $sext) = &fileparse($src, qr/\.(gif|png|jpg|jpeg)/i); 4240: $src=~s/\.(gif|png|jpg|jpeg)$/\.eps/i; 4241: $src=&Apache::lonnet::filelocation($Apache::lonxml::pwd[-1],$src); 4242: &Apache::lonxml::debug("Filelocation gives: $src"); 4243: if (! -e $src) { 4244: &Apache::lonxml::debug("$src does not exist"); 4245: if (&Apache::lonnet::repcopy($src) ne 'ok' ) { 4246: &Apache::lonxml::debug("Repcopy of $src failed (1)"); 4247: #if replication failed try to find ps file 4248: $src=~s/\.eps$/\.ps/; 4249: &Apache::lonxml::debug("Now looking for $src"); 4250: #if no ps file try to replicate it. 4251: my $didrepcopy = &Apache::lonnet::repcopy($src); 4252: &Apache::lonxml::debug("repcopy of $src ... $didrepcopy"); 4253: if ( (not -e $src) || 4254: ($didrepcopy ne 'ok')) { 4255: &Apache::lonxml::debug("Failed to find or replicate $src"); 4256: 4257: #if replication failed try to produce eps file dynamically 4258: $src=~s/\.ps$/\.eps/; 4259: my $temp_file; 4260: open(FILE,">>/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat"); 4261: my $newsrc=$orig_src; 4262: $newsrc =~ s|(.*)/res/|/home/httpd/html/res/|; 4263: &Apache::lonxml::debug("queueing $newsrc for dynamic eps production."); 4264: print FILE ("$newsrc\n"); 4265: close(FILE); 4266: $src=~s|/home/httpd/html/res|/home/httpd/prtspool|; 4267: $src=~s|/home/([^/]*)/public_html/|/home/httpd/prtspool/$1/|; 4268: if ($sext ne "") { # Put the ext. back in to uniquify. 4269: $src =~ s/\.eps$/$sext.eps/; 4270: } 4271: 4272: } 4273: 4274: } 4275: } else { 4276: # If the postscript file has spaces in its name, 4277: # LaTeX will gratuitiously vomit. Therefore 4278: # queue such files for copy with " " replaced by "_". 4279: # printout.pm will know them by their .ps or .eps extensions. 4280: my $newsrc = $orig_src; 4281: $newsrc =~ s|(.*)/res/|/home/httpd/html/res/|; 4282: open(FILE,">>/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat"); 4283: print FILE "$src\n"; 4284: close FILE; 4285: $src=~s|/home/httpd/html/res|/home/httpd/prtspool|; 4286: $src=~s|/home/([^/]*)/public_html/|/home/httpd/prtspool/$1/|; 4287: } 4288: my ($path,$file)=($src=~m|(.*)/([^/]*)$|); 4289: $path =~ s/ /\_/g; 4290: $file =~ s/ /\_/g; 4291: &Apache::lonxml::debug("get_eps_image returning: $path / $file<BR />"); 4292: return ($path.'/',$file); 4293: } 4294: 4295: sub eps_generation { 4296: my ($src,$file,$width_param) = @_; 4297: my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat"; 4298: my $temp_file = Apache::File->new('>>'.$filename); 4299: print $temp_file "$src\n"; 4300: my $newsrc = $src; 4301: $newsrc =~ s/(\.gif|\.jpg|\.jpeg)$/\.eps/i; 4302: $newsrc=~s{/home/httpd/html/res}{}; 4303: $newsrc=~s{/home/($LONCAPA::username_re)/public_html/}{/$1/}; 4304: $newsrc=~s{/\./}{/}; 4305: $newsrc=~s{/([^/]+)\.(ps|eps)}{/}; 4306: if ($newsrc=~m{/home/httpd/lonUsers/}) { 4307: $newsrc=~s{/home/httpd/lonUsers}{}; 4308: $newsrc=~s{/($LONCAPA::domain_re)/./././}{/$1/}; 4309: } 4310: if ($newsrc=~m{/userfiles/}) { 4311: return ' \graphicspath{{'.$newsrc.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} '; 4312: } else { 4313: return ' \graphicspath{{/home/httpd/prtspool'.$newsrc.'}}\includegraphics[width='.$width_param.' mm]{'.$file.'} '; 4314: } 4315: } 4316: 4317: sub file_path { 4318: my $src=shift; 4319: my ($file,$path); 4320: if ($src =~ m!(.*)/([^/]*)$!) { 4321: $file = $2; 4322: $path = $1.'/'; 4323: } 4324: return $file,$path; 4325: } 4326: # Converts a measurement in to mm from any of 4327: # the other valid LaTeX units of measure. 4328: # If the units of measure are missing from the 4329: # parameter, it is assumed to be in and returned 4330: # with mm units of measure 4331: sub recalc { 4332: my $argument = shift; 4333: if (not $argument=~/(mm|cm|in|pc|pt)/) {return $argument.' mm';} 4334: $argument=~/\s*(\d+\.?\d*)\s*(mm|cm|in|pc|pt)/; 4335: my $value=$1; 4336: my $units=$2; 4337: if ($units eq 'cm') { 4338: $value*=10; 4339: } elsif ($units eq 'in') { 4340: $value*=25.4; 4341: } elsif ($units eq 'pc') { 4342: $value*=(25.4*12/72.27); 4343: } elsif ($units eq 'pt') { 4344: $value*=(25.4/72.27); 4345: } 4346: return $value.' mm'; 4347: } 4348: 4349: sub LATEX_length { 4350: my $garbage=shift; 4351: $garbage=~s/^\s+$//; 4352: $garbage=~s/^\s+(\S.*)/$1/;#space before 4353: $garbage=~s/(.*\S)\s+$/$1/;#space after 4354: $garbage=~s/(\s)+/$1/;#only one space 4355: $garbage=~s/(\\begin{([^\}]+)}|\\end{([^\}]+)})//g;#remove LaTeX \begin{...} and \end{...} 4356: $garbage=~s/(\$\_\{|\$\_|\$\^{|\$\^|\}\$)//g;#remove $_{,$_,$^{,$^,}$ 4357: $garbage=~s/([^\\])\$/$1/g;#$ 4358: $garbage=~s/(\\ensuremath\{\_\{|\\ensuremath\{\_|\\ensuremath\{\^{|\\ensuremath\{\^|\})//g;#remove \ensuremath{...} 4359: $garbage=~s/(\\alpha|\\beta|\\gamma|\\delta|\\epsilon|\\verepsilon|\\zeta|\\eta|\\theta|\\vartheta|\\iota|\\kappa|\\lambda|\\mu|\\nu|\\xi|\\pi|\\varpi|\\rho|\\varrho|\\sigma|\\varsigma|\\tau|\\upsilon|\\phi|\\varphi|\\chi|\\psi|\\omega|\\Gamma|\\Delta|\\Theta|\\Lambda|\\Xi|\\Pi|\\Sigma|\\Upsilon|\\Phi|\\Psi|\\Omega)/1/g; 4360: $garbage=~s/(\\pm|\\mp|\\times|\\div|\\cdot|\\ast|\\star|\\dagger|\\ddagger|\\amalg|\\cap|\\cup|\\uplus|\\sqcap|\\sqcup|\\vee|\\wedge|\\oplus|\\ominus|\\otimes|\\circ|\\bullet|\\diamond|\\lhd|\\rhd|\\unlhd|\\unrhd|\\oslash|\\odot|\\bigcirc|\\Box|\\Diamond|\\bigtriangleup|\\bigtriangledown|\\triangleleft|\\triangleright|\\setminus|\\wr)/1/g; 4361: $garbage=~s/(\\le|\\ll|\\leq|\\ge|\\geq|\\gg|\\neq|\\doreq|\\sim|\\simeq|\\subset|\\subseteq|\\sqsubset|\\sqsubseteq|\\in|\\vdash|\\models|\\supset|\\supseteq|\\sqsupset|\\sqsupseteq|\\ni|\\dash|\\perp|\\approx|\\cong|\\equiv|\\propto|\\prec|\\preceq|\\parallel|\\asymp|\\smile|\\frown|\\bowtie|\\succ|\\succeq|\\mid)/1/g; 4362: $garbage=~s/(\\not<|\\\\not\\le|\\not\\prec|\\not\\preceq|\\not\\subset|\\not\\subseteq|\\not\\sqsubseteq|\\not\\in|\\not>|\\not\\ge|\\not\\succ|\\notsucceq|\\not\\supset|\\notsupseteq|\\not\\sqsupseteq|\\notin|\\not=|\\not\\equiv|\\not\\sim|\\not\\simeq|\\not\\approx|\\not\\cong|\\not\\asymp)/1/g; 4363: $garbage=~s/(\\leftarrow|\\gets|\\Leftarrow|\\rightarrow|\\to|\\Rightarrow|\\leftrightarrow|\\Leftrightarrow|\\mapsto|\\hookleftarrow|\\leftharpoonup|\\leftkarpoondown|\\rightleftharpoons|\\longleftarrow|\\Longleftarrow|\\longrightarrow|\\Longrightarrow|\\longleftrightarrow|\\Longleftrightarrow|\\longmapsto|\\hookrightarrow|\\rightharpoonup|\\rightharpoondown|\\uparrow|\\Uparrow|\\downarrow|\\Downarrow|\\updownarrow|\\Updownarrow|\\nearrow|\\searrow|\\swarrow|\\nwarrow)/11/g; 4364: $garbage=~s/(\\aleph|\\hbar|\\imath|\\jmath|\\ell|\\wp|\\Re|\\Im|\\mho|\\prime|\\emptyset|\\nabla|\\surd|\\partial|\\top|\\bot|\\vdash|\\dashv|\\forall|\\exists|\\neg|\\flat|\\natural|\\sharp|\\\||\\angle|\\backslash|\\Box|\\Diamond|\\triangle|\\clubsuit|\\diamondsuit|\\heartsuit|\\spadesuit|\\Join|\\infty)/11/g; 4365: $garbage=~s/(\\hat{([^}]+)}|\\check{([^}]+)}|\\dot{([^}]+)}|\\breve{([^}]+)}|\\acute{([^}]+)}|\\ddot{([^}]+)}|\\grave{([^}]+)}|\\tilde{([^}]+)}|\\mathring{([^}]+)}|\\bar{([^}]+)}|\\vec{([^}]+)})/$1/g; 4366: #remove some other LaTeX command 4367: $garbage=~s|\\(\w+)\\|\\|g; 4368: $garbage=~s|\\(\w+)(\s*)|$2|g; 4369: $garbage=~s|\+|11|g; 4370: my $value=length($garbage); 4371: return $value; 4372: } 4373: 4374: 4375: # is_inside_of $tagstack $tag 4376: # This sub returns true if the current state of Xml processing 4377: # is inside of the tag. 4378: # Parameters: 4379: # tagstack - The tagstack from the parser. 4380: # tag - The tag (without the <>'s.). 4381: # Sample usage: 4382: # if (is_inside_of($tagstack "table")) { 4383: # # I'm in a table.... 4384: # } 4385: sub is_inside_of { 4386: my ($tagstack, $tag) = @_; 4387: my @stack = @$tagstack; 4388: for (my $i = ($#stack - 1); $i >= 0; $i--) { 4389: if ($stack[$i] eq $tag) { 4390: return 1; 4391: } 4392: } 4393: return 0; 4394: } 4395: 4396: 4397: 1; 4398: __END__