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