1: #!/usr/local/bin/perl5.00403 -w
  2: BEGIN { # try to get to legacy perl support files
  3: my @tmp = @INC;
  4: use lib qw( /usr/local/lib/perl5 /usr/local/lib/perl5/site_perl
  5:             /data1/opt2/perl/vendor/lib/vendor_perl/5.6.0/. );
  6: use lib @INC; # these should replace trailing paths

  8: }

 10: my $version_marker = ' $Id: htmltrans,v 1.45 2001/09/20 11:35:07 rbraddoc Exp xethair $ ';

 12: use lib ("/usr/app/home/rbraddoc/SGML/Transform");
 13: use lib (".");
 14: use SGMLHandler;
 15: use Carp;
 16: use Data::Locations::Shell;
 17: use strict;
 18: require "sgmlhelp.pl";

 20: my $doctype_html = '<!doctype html PUBLIC "-//W3C//DTD HTML 4.0//EN">';
 21: my $handbookdir = "/usr/app/home/rbraddoc/Handbook";
 22: my $htmldir = $handbookdir . "/conversion/html";

 24: require "$handbookdir/conversion/general.pl";
 25: require "$handbookdir/general/common.pl";
 26: require "$htmldir/grutils.pl";

 28: my $debug = 0; # does very little


 31: #constants
 32: my $dirpath = ".";
 33: my $topleveldir = $handbookdir . "/conversion/html";
 34: my $topleveldirtype = 'volume';

 36: #flags
 37: my $do_purge_before = 0; #delete all files before article processing
 38: my $do_section_split = 1; #whether to produce multi page documents
 39: my $do_manuscript = 0; #whether to produce manuscript review format
 40: my $do_comments = 0; #whether to include debugging info in comments
 41: my $do_stylesheet = 1; #include code to call stylesheet
 42: my $do_full_toc = 0; #include runin sects in toc
 43: my $do_subfile_toc = 0; #include toc in section files
 44: my $do_accurate_table_borders = 0;
 45: my %do_external_images =  ('color'=>0,'halftone'=>0,'lineart'=>0); #include links to full size separate images
 46: my $with_graphics_at = 'absolute'; #use relative links to graphics hierarchy
 47: my $show_borders = 0; #show borders on formatting tables

 49: #globals
 50: my $exitcode = 0;
 51: my $sgml = new SGMLHandler();
 52: my $out = '[no location created here!]';
 53: my $null = '[no location created here!]';
 54: my ($volnum,$divnum,$artnum,$footnote_count,$end_notes,$targetfile,
 55:     $stylesheetloc,$stylesheet);
 56: my (@simplecontentelements,@calloutsections,@runinsections);
 57: my (%Label,%Label_Sub,%Label_Prime,%simple_element_map, #%map_section_heading,
 58:     %entity_map,%entity_map_tex,%entity_map_html,%ID_File,%ID_Content);

 60: $stylesheet = $htmldir . "/section.css";
 61:     
 62: my @filelist = ReadArgs(@ARGV);

 64: %simple_element_map = ('ITALIC' => 'em',
 65:                        'BOLD' => 'strong',
 66:                        'PARA' => 'p',
 67:                        #'SUB' => 'sub',
 68:                        #'SUP' => 'sup',
 69:                        #'BREAK' => 'br',
 70:                        );

 72: my %map_element_default_title = 
 73:     (
 74:      'SELECT.SECT' => "Selected References",
 75:      'INTRO' => "Introduction",
 76:      'APPENDIX' => "Appendix",
 77:      'TOPIC.OVERVIEW' => "Overview"
 78:      );

 80: @simplecontentelements = ('INTRO','RUNIN.SECT',
 81:                           'FIG.SECT');
 82: @calloutsections = ('CALLOUT.SECT','FIG.SECT','SELECT.SECT','REF.SECT',
 83:                     'ACKNOWLEDGE','INTRO','APPENDIX','TOPIC.OVERVIEW');
 84: @runinsections   = ('RUNIN.SECT','EXAMPLE');

 86: my %section_type = ((map { ($_,'callout') } @calloutsections),
 87:                     (map { ($_,'runin') } @runinsections));
 88:                     


 91: %entity_map = %entity_map_tex = %entity_map_html = ();
 92: ReadEntityMapping("$handbookdir/conversion/html/entity.map",\%entity_map_html);
 93: ReadEntityMapping("$handbookdir/conversion/tex/entity.map",\%entity_map_tex);

 95: # zero-th is repeated for out of range notes
 96: my @footnote_marker = (0,'*','**',Entity('dagger'),Entity('Dagger'));
 97: $a = 0;
 98: my %footnote_map = 
 99:     map { ($_, ++$a) } @footnote_marker[1..$#footnote_marker];

101: my $layout_table_attr = ''; #valign="top" cellpadding=0
102: if ($show_borders) {
103:     $layout_table_attr .= ' border=0';
104: } else {
105:     $layout_table_attr .= ' border=0';
106: }

108: #############################################################################
109: ## Handler Functions
110: $sgml->handler_mode('DEFAULT');
111: # Default handlers
112: $sgml->element('',sub {
113:     my ($sgml,$element) = @_;
114:     warn "WARN:Unhandled Element:".$sgml->get_context."\n";
115:     print $out "<!--IGNORE:[".$element->name."]-->" if $do_comments;
116:     print $out &check_for_id($sgml,$element);
117:     my $save = $out;
118:     $out = new Data::Locations::Shell("/dev/null");
119:     $sgml->process_content;
120:     $out = $save;
121:     #print $out "<!--INGORE:CLOSE[".$element->name."]-->" if $do_comments;
122: });
123: $sgml->cdata('',sub {
124:     my ($sgml,$data) = @_;
125:     if (ref($out)) {
126:         print $out $data;
127:     } else {
128:         warn "WARNING:CDATA:Output Location is invalid:".$sgml->get_context."\n";
129:     }
130: });
131: $sgml->sdata('',sub {
132:     my ($sgml,$data) = @_;
133:     #$data->data =~ /^\\s*(\w+)\s*$/ || warn "Bad SData: '$data'\n";
134:     my $adata = $data->name;
135:     my $cont = Entity($adata);
136:     print $out $cont;
137: });
138: $sgml->pi('',sub {
139:     my ($sgml,$data) = @_;
140:     print $out "<!--IGNORE:PI:".$$data."-->" if $do_comments;
141: });
142: $sgml->comment('',sub {
143:     my ($sgml,$comment) = @_;
144:     my @temp = $comment->comments();
145:     print $out "<!--COMMENT:[".join('--',@temp)."]-->" if $do_comments;
146: });
147: $sgml->re('',sub {
148:     my ($sgml,$data) = @_;
149:     print $out "\n";
150: });

152: $sgml->element('ARTICLE',sub {
153:     my ($sgml,$element) = @_;
154:     my ($savedout,$dir,$curdir,$toc,$tocloc,$cref,$artloc,%counts,
155:         @sectionlist,@sectargs,@divlist,%texcache,$tmp,$sectpathloc,
156:         $titleloc,$headingloc,@cleanup_tasks,$year);

158:     my $id = $element->attr('ID');
159:     $id = uc $id->value if defined $id;
160:     ($volnum,$divnum,$artnum,$year) =
161:       Handbook::General::ReadAccessNumber($element->attr('ACCESS.NO')->value);
162:     if (!defined $volnum) {
163:         warn "WARNING: article '$id' omitted (access number error)\n";
164:         $sgml->suppress_content;
165:         return;
166:     } else {
167:         my @ctrldata = 
168:             (Handbook::General::Get_Article_Info($id))[2,3,4,5];
169:         $year = $ctrldata[3] unless $year;
170:         my @sgmldata = ($volnum,$divnum,$artnum,$year);
171:         for (my $i=0; $i<4; $i+=1) {
172:             my $c = $ctrldata[$i];
173:             my $s = $sgmldata[$i];
174:             next unless defined($c) || defined($s);
175:             my $err = 1;
176:             TEST: {
177:                 last TEST if (!defined($c) || !defined($s));
178:                 if ($c =~ /\D/) {
179:                     last TEST unless ($c eq $s);
180:                 } else {
181:                     last TEST unless ($c == $s);
182:                 }
183:                 $err = 0;
184:             }

186:             if ($err) {
187:                 warn "WARNING: SGML access number does not match Control Data".
188:                     ": " . ('volume','division','article','year')[$i] .
189:                         " S:'".$s."'  C:'".$c."'\n";
190:                 if (defined $c) {
191:                     if ($i == 0) {
192:                         $volnum = $c;
193:                     } elsif ($i == 1) {
194:                         $divnum = $c;
195:                     } elsif ($i == 2) {
196:                         $artnum = $c;
197:                     }
198:                 }
199:                 #last;
200:             }
201:         }

203:         $volnum = '0'.(0+$volnum) unless $volnum =~ /\D/ || $volnum > 9;
204:         $divnum = '0'.(0+$divnum) unless $divnum =~ /\D/ || $divnum > 9;
205:         $artnum = '0'.(0+$artnum) unless $artnum =~ /\D/ || $artnum > 9;
206:         $year = 0 unless $year;
207:     }
208:     $dirpath = $topleveldir;
209:     if ($topleveldirtype eq 'volume') {
210:         if ($volnum =~ /\D/) {
211:             $tmp = "/".$volnum;
212:         } else {
213:             $tmp = "/V".$volnum;
214:         }
215:         foreach $dir ($tmp, "Y".$year, "/D".$divnum, "/A".$artnum) {
216:             $dirpath .= $dir;
217:             if (! -d $dirpath) {
218:                 mkdir $dirpath,0755 || die "Failed to make destination directory";
219:             }
220:         }
221:     } elsif ($topleveldirtype eq 'article') {
222:         foreach $dir ("/A".$artnum) {
223:             $dirpath .= $dir;
224:             if (! -d $dirpath) {
225:                 mkdir $dirpath,0755 || die "Failed to make destination directory";
226:             }
227:         }
228:     } elsif ($topleveldirtype eq 'id') {
229:         foreach $dir ("/".$id) {
230:             $dirpath .= $dir;
231:             if (! -d $dirpath) {
232:                 mkdir $dirpath,0755 || die "Failed to make destination directory";
233:             }
234:         }
235:     } elsif ($topleveldirtype eq 'content') {
236:         if (! -d $dirpath) {
237:             mkdir $dirpath,0755 || die "Failed to make destination directory";
238:         }
239:     } elsif ($topleveldirtype eq 'division') {
240:         foreach $dir ("/D".$divnum,"/A".$artnum) {
241:             $dirpath .= $dir;
242:             if (! -d $dirpath) {
243:                 mkdir $dirpath,0755 || die "Failed to make destination directory";
244:             }
245:         }
246:     }

248:     if ($do_purge_before) {
249:         system 'rm','-rf',$dirpath;
250:         mkdir($dirpath,0755) || die "Failed to make destination directory";
251:     }

253:     if ($with_graphics_at eq 'local') {
254:         mkdir($dirpath.'/detail',0755) ||
255:             die "Failed to make detail images directory";
256:     } elsif ($with_graphics_at eq 'division') {
257:         foreach $dir ('','/inline','/entities','/detail') {
258:             if (! -d $dirpath.'/../graphics'.$dir) {
259:                 mkdir($dirpath.'/../graphics'.$dir,0755) ||
260:                     die "Failed to make ".$dir." images directory\n";
261:             }
262:         }
263:     }

265:     $sgml->global('footnote count',0);
266:     %ID_Content = ();
267:     %ID_File = ();
268:     foreach my $name ('table','inline.table','fig','ref.item','equation',
269:                       'example') {
270:         $Label_Prime{$name} = 0;
271:     }
272:     
273:     $titleloc = new Data::Locations::Shell("/dev/null");
274:     $headingloc = new Data::Locations::Shell("/dev/null");
275:     $tocloc = new Data::Locations::Shell("/dev/null");
276:     $sectpathloc = new Data::Locations::Shell("/dev/null");
277:     %texcache = @sectionlist = @divlist = ();
278:     #note some of these are initialization for open_section_file
279:     $sgml->stack_new('math numbering' => 1,'destination path' => $dirpath,
280:                      'TeX rendered hash' => \%texcache,
281:                      'Article ID' => $id,
282:                      'Article Heading' => $headingloc,
283:                      'Section Path' => $sectpathloc,
284:                      'Article Title' => $titleloc,
285:                      'Article Section Location List' => \@sectionlist,
286:                      'div list reference' => \@divlist,
287:                      'Section Type' => 'article',
288:                      'Volume' => $volnum,
289:                      'end of article cleanup' => \@cleanup_tasks);

291:     chomp ($curdir = `pwd`);
292:     chdir($dirpath) || die "Failed to change directory to $dirpath: $!\n";
293:     warn "INFO:Writing to ".$dirpath."/\n";
294:     unlink "index.html"; # TODO remove these lines after symlinks gone
295:     unlink "$id.html";
296:     #symlink "$id.html","index.html";
297:     $savedout = $out;
298:     #dont do start_section($sgml,$element,'article');
299:     ($out,$toc) = open_section_file($sgml,$element,'article');

301:     $sgml->handler_mode_push('ARTICLE','DEFAULT');
302:     print $out "<div class=\"article-sect\">";
303:     $sgml->process_content_filt('Article Top-level Location'=>$out);
304:     print $out "<div>";
305:     $sgml->handler_mode_pop('ARTICLE','DEFAULT');
306:     
307:     #if ($sgml->global('footnote count') > 0) {
308:     #    print $out "<div class=\"FOOTNOTES\">";
309:     #    print $out "<!--Footnotes-->" if $do_comments;
310:     #    print $out "<h3 class='sect-title'>Notes</h3>\n<ol>\n";
311:     #    print $out $sgml->global('article notes');
312:     #    print $out "</ol>\n</div>\n";
313:     #}

315:     $titleloc->reset;
316:     if (!defined $titleloc->read) {
317:         print $titleloc $element->attr('ACCESS.NO')->value;
318:     }

320:     close_section_file($sgml,$element);
321:     #finish_section($sgml,$element);

323:     foreach my $task (@cleanup_tasks) {
324:         if (ref($task) eq 'ARRAY') {
325:             my $proc = shift @$task;
326:             &$proc(@$task);
327:         } elsif (ref($task) eq 'CODEREF') {
328:             &$task();
329:         } else {
330:             warn "WARNING:cleanup:unexpected task type ".ref($task)."\n";
331:         }
332:     }

334:     #all included locations should be filled by now
335:     foreach $tmp (@sectionlist) {
336:         $tmp->dump;
337:         #$tmp->delete; #not recursive - maybe try traverse & delete?
338:     }
339:     
340:     chdir $curdir;
341:     $out = $savedout;
342: });

344: $sgml->element(['HDBKEDIT','DIV'],'process');

346: $sgml->element('DIV.INFO','suppress');

348: #################################################################
349: ## Article content handlers
350: $sgml->handler_mode('ARTICLE');

352: foreach my $el (keys %simple_element_map) {
353:     $sgml->element($el,'',\&simple_mapped_element);
354: }

356: $sgml->element(['ARTICLE.REAR','ARTICLE.BODY'],'process');

358: $sgml->element('BREAK',sub {
359:     my ($sgml,$element) = @_;
360:     print $out "<br>";
361:     $sgml->process_content;
362: });

364: $sgml->element('TRADENAME','process');

366: #override the simple_mapped_elements
367: $sgml->element('PARA',sub {
368:     my ($sgml,$element) = @_;
369:     Count_Increment($sgml,'paragraph');
370:     $sgml->stack('seen content',1);
371:     if ($sgml->global("Suppress Next Open Para")) {
372:         $sgml->global("Suppress Next Open Para",0);
373:     } else {
374:         print $out "<" . $simple_element_map{'PARA'} . ">";
375:     }
376:     $sgml->process_content;
377:     print $out "</" . $simple_element_map{'PARA'} . ">\n";
378: });
379: #override the para default case
380: $sgml->element('PARA','.*/((FOOTNOTE)|(ENTRY)|(ITEM)|(REF\.ITEM))/[^/]+',
381:                'process');

383: $sgml->element(\@simplecontentelements,\&SimpleContentElement);

385: $sgml->element('CALLOUT.SECT',\&Element_CalloutSection);

387: $sgml->element('BYLINE.DISPLAY','.*/(CALLOUT)|(PROPERTY).SECT/[^/]*', sub {
388:     my ($sgml,$element) = @_;
389:     my $savedout = $out;
390:     $out = $sgml->stack('section byline');
391:     $sgml->process_content;
392:     $out = $savedout;
393: });

395: $sgml->element('COPYRIGHT','suppress');

397: $sgml->element('PAGE.NO','suppress');
398: $sgml->element('SOURCE.INFO','suppress');

400: #these are assumed duplicated by footnotes
401: $sgml->element('PERMISSION','suppress');

403: $sgml->element('ARTICLE.INFO','.*/ARTICLE/[^/]+', sub {
404:     my ($sgml,$element) = @_;
405:     my ($head,$title,$titlestr,$tmploc,$series,$volnum,
406:         $divtitle,$voltitle,$byline,$vol,$permission);
407:     #print $out &check_for_id($sgml,$element);
408:     
409:     $tmploc = new Data::Locations::Shell('/dev/null');
410:     foreach (\$title,\$series,\$volnum,\$divnum,\$divtitle,\$voltitle,
411:                   \$byline,\$permission) {
412:         $$_ = $tmploc->new;
413:     }
414:     $sgml->stack_new('series'=>$series,'vol.no'=>$volnum,'title'=>$title,
415:                      'div.title'=>$divtitle,'div.chair.display'=>$tmploc,
416:                      'byline.display'=>$byline,'permission'=>$permission);

418:     $sgml->process_content;

420:     #print $head "<table width=100% border=0>\n<tr><td>\n<table width=100% border=0>\n<tr><td>";
421:     #$sgml->stack('series',$head->new);
422:     #print $head ", Volume&nbsp;";
423:     #$sgml->stack('vol.no',$head->new);
424:     #print $head "</td></tr>\n<tr><td>";
425:     #$sgml->stack('div.title',$head->new);
426:     #print $head "</td></tr>\n<tr><td><br>\n";
427:     #$sgml->stack('div.chair.display',$head->new);
428:     #print $head "</td></tr></table>\n</td><td>\n<h1 align=center>";
429:     #$titleloc = $head->new;
430:     #$sgml->stack('title',$titleloc);
431:     #print $head "</h1>\n<h4 align=right>";
432:     #$sgml->stack('byline.display',$head->new);
433:     #print $head "</h4>\n</td></tr></table>\n";

435:     #make stripped title
436:     $head = $sgml->stack('Article Title');
437:     $title->reset;
438:     $titlestr = join '',($title->read);
439:     $titlestr =~ s/<\/?[^>]+>//g;
440:     print $head $titlestr;

442:     #get vol title
443:     $vol = $sgml->stack('Volume');
444:     #$voltitle = join '',($volnum->read);
445:     #$voltitle =~ s/<\/?[^>]+>//g;
446:     $voltitle = Handbook::General::Get_Volume_Info($vol);
447:     $voltitle = '[VOLUME]' unless defined $voltitle;

449:     #set up section path
450:     $head = $sgml->stack('Section Path');
451:     if ($vol =~ /\D/) {
452:         #desk edition
453:         print $head ("<a href='../../../index.html'>ASM Desk Editions",
454:                      "</a> --> <a href='../../index.html'>",$voltitle,
455:                      "</a> --> <a href='../index.html'>Division: ",
456:                      $divtitle,"</a> --> <a href='index.html'>Article: ",$title,"</a>");
457:     } else {
458:         #handbook
459:         print $head ("<a href='../../../index.html'>",$series,
460:                      "</a> --> <a href='../../index.html'>Volume ",(0+$vol),", ",
461:                      $voltitle,"</a> --> <a href='../index.html'>Division: ",
462:                      $divtitle,"</a> --> <a href='index.html'>Article: ",$title,"</a>");
463:     }
464:     #set up article heading
465:     $head = $sgml->stack('Article Heading');
466:     print $head "
467: <h1 class='article-title'>",$title,"</h1>
468: <p class='byline'>",$byline,"</p>
469: ";
470:     if (defined $permission->read) {
471:         print $head "<p class='permission'>",$permission,"</p>\n";
472:     }
473:     print $head "
474: <hr>
475: ";
476: #<table border=0 width='100%'>
477: #<tr><td>From:</td><td><it>",$series,"</it>, Volume ",$volnum,", ",$voltitle,"</td></tr>
478: #<tr><td>Division:</td><td><it>",$divtitle,"</it></td></tr>
479: #</table>
480: #<hr>
481: #";

483: });
484:       
485: $sgml->element('TITLE',sub {
486:     my ($sgml,$element) = @_;
487:     my (@prefix,@suffix,$savedout,$sect,$parent,$secttype);

489:     print $out &check_for_id($sgml,$element);
490:     #fig.section causes this to choke without the defined test
491:     #if (defined($$element[5]->attr('EXTRALEVEL')) && ! $$element[5]->attr('EXTRALEVEL')->is_implied && $$element[5]->attr('EXTRALEVEL')->value != 0 ) { #NOTE INTERNAL INTERFACE
492:     $secttype = $sgml->stack('Section Type');
493:     if (Parent($element,@calloutsections,@runinsections)) {
494:         $sect = 1;
495:         @prefix = ();
496:         @suffix = ();
497:         if ($secttype eq 'runin') {
498:             $sgml->global("Suppress Next Open Para",1);
499:         }
500:     } else {
501:         $sect = 0;
502:         @prefix = ($sgml->stack('title style start'));
503:         @suffix = ($sgml->stack('title style end'));
504:     }
505:     
506:     print $out @prefix;
507:    
508:     if ($sect) {
509:         $savedout = $out;
510:         $out = $sgml->stack('toc title');
511:         #print $savedout $out;
512:         $sgml->stack('section title')->print($out);
513:     }

515:     $sgml->process_content;

517:     if ($sect) {
518:         $out = $savedout;
519:     }

521:     print $out @suffix;
522: });
523:          
524: $sgml->element(['TITLE.TOC','TITLE.HEAD','TITLE.SEARCH','TABCT','BYLINE',
525:                 'COMMITTEE.BYLINE','FIGCT','CREATE.DATE','REVISE.DATE',
526:                 'WORK.HISTORY','INDX.ALL','TEXTPAGES.CT','DIV.CHAIR',
527:                 'PROCESS.NOTES'], sub {
528:                     my ($sgml,$element) = @_;
529:                     print $out "<!--SKIP:OPEN[".$element->name."]-->" if $do_comments;
530:                     $sgml->suppress_content;
531:                 });

533: $sgml->element('TOPIC.OVERVIEW',sub {
534:     my ($sgml,$element) = @_;
535:     
536:     start_section($sgml,$element,'toplevel'=>1,'notoc'=>1);
537:     print $out "<hr>\n";
538:     $sgml->process_content;
539:     print $out "<hr>\n";
540:     finish_section($sgml,$element);
541: });

543: $sgml->element('APPENDIX',sub {
544:     my ($sgml,$element) = @_;

546:     start_section($sgml,$element);
547:     $sgml->process_content;
548:     finish_section($sgml,$element);
549: });

551: $sgml->element('ARTICLE.INFO','.*/APPENDIX/[^/]+',sub {
552:     my ($sgml,$element) = @_ ;
553:     my ($byline,$title,$permission,$dummy);
554:     print $out "<h3 class='sect-title'>";
555:     $title = $out->new;
556:     print $out "</h3>\n<p class='byline'>";
557:     $byline = $out->new;
558:     print $out "</p>\n";
559:     $permission = $out->new;
560:     $dummy = new Data::Locations::Shell('/dev/null');
561:     $sgml->process_content_filt('byline.display'=>$byline,'title'=>$title,
562:                                 'series'=>$dummy,'vol.no'=>$dummy,
563:                                 'div.title'=>$dummy,'permission'=>$permission,
564:                                 'div.chair.display'=>$dummy);
565:     $dummy->delete;
566:     if (defined $permission->read) {
567:         print $byline "<p class='permission'>";
568:         print $permission "</p>\n";
569:     }
570: });


573: $sgml->element(['DEF.LIST','GLOSS.LIST'],sub {
574:     my ($sgml,$element) = @_;
575:     my ($title);
576:     print $out &check_for_id($sgml,$element);
577:     $sgml->stack('seen content',1);
578:     print $out "<ul class='term-list'>\n";
579:     $title = $out->new;
580:     $sgml->process_content_filt('title location',$title);
581:     print $out "</ul>\n";
582: });

584: $sgml->element(['DEF.BLOCK','GLOSS.BLOCK'],sub {
585:     my ($sgml,$element) = @_;
586:     my ($title);
587:     print $out "<ul class='term-list'>\n";
588:     print $out &check_for_id($sgml,$element);
589:     $title = $out->new;
590:     $sgml->process_content_filt('title location',$title);
591:     print $out "</ul>\n";
592: });

594: $sgml->element('TITLE','.*/(DEF|GLOSS)\.(BLOCK|LIST)/[^/]+',sub {
595:     my ($sgml,$element) = @_;
596:     my $savedout = $out;
597:     $out = $sgml->stack('title location');
598:     print $out "<li class=\"title\">";
599:     $sgml->process_content;
600:     print $out "</li>\n";
601:     $out = $savedout;
602: });
603:        
604: $sgml->element(['DEF.ENTRY','GLOSS.ENTRY'],sub {
605:     my ($sgml,$element) = @_;
606:     my ($def,$term);
607:     print $out "<li class='term'>";
608:     print $out &check_for_id($sgml,$element);
609:     $term = $out->new;
610:     print $out "</li><li class='def'>";
611:     $def = $out->new;
612:     print $out "</li>\n";

614:     $sgml->process_content_filt('deflist term location',$term,
615:                                 'deflist definition location',$def);
616: });

618: $sgml->element('TERM',sub {
619:     my ($sgml,$element) = @_;
620:     my $savedout = $out;
621:     $out = $sgml->stack('deflist term location');
622:     print $out &check_for_id($sgml,$element);
623:     $sgml->process_content;
624:     $out = $savedout;
625: });

627: $sgml->element('DEF',sub {
628:     my ($sgml,$element) = @_;
629:     my $savedout = $out;
630:     $out = $sgml->stack('deflist definition location');
631:     print $out &check_for_id($sgml,$element);
632:     $sgml->process_content;
633:     $out = $savedout;
634: });


637: $sgml->element('LIST',sub {
638:     my ($sgml,$element) = @_;
639:     my ($style,$head,$tail,$title,$pretitle,$outertype);
640:     Count_Increment($sgml,'list');
641:     $sgml->stack('seen content',1);
642:     if ($sgml->stack_exists('list style')) {
643:         $outertype = $sgml->stack('list style');
644:     } else {
645:         $outertype = '';
646:     }
647:     $sgml->stack_new('list style' => '');
648:     $style = lc $element->attr('LIST.STYLE')->value;
649:     if ($style eq 'bulleted') {
650:         #$sgml->stack('list style','');
651:         $head = "<ul class='$style'>";
652:         $tail = "</ul>\n";
653:     } elsif ($style eq 'numbered') {
654:         if ($outertype eq 'number-1') {
655:             $sgml->stack('list style','number-a');
656:             #$head = "<ol type='a' class='$style'>";
657:             $head = "<ol class='$style'>";
658:             $tail = "</ol>\n";
659:         } else { #default or ($outertype eq 'number-a')
660:             $sgml->stack('list style','number-1');
661:             #$head = "<ol type='1' class='$style'>";
662:             $head = "<ol class='$style'>";
663:             $tail = "</ol>\n";
664:         }
665:     } elsif ($style eq 'simple') {
666:         #$sgml->stack('list style','');
667:         $head = "<ul class='$style'>";
668:         $tail = "</ul>\n";
669:     } else {
670:         if ($do_comments) {
671:             $head = "<!--ERROR:LIST:OPEN:UNKNOWN STYLE [$style]-->";
672:             $tail = "<!--ERROR:LIST:CLOSE:UNKNOWN STYLE [$style]-->";
673:         } else {
674:             $head = $tail = '';
675:         }
676:     }

678:     print $out "<table $layout_table_attr width='100%' class='list'><tr><td>";
679:     print $out &check_for_id($sgml,$element);
680:     $pretitle = $out->new;
681:     $title = $out->new;
682:     print $out $head;

684:     $sgml->process_content_filt('title location' => $title,
685:                                 'list block start' => $head, 
686:                                 'list block end' => $tail);
687:     print $out $tail;
688:     print $out "</td></tr></table>";

690:     if (defined $title->read) {
691:         print $pretitle "<span class=\"title\">";
692:         print $title "</span>";
693:     }
694: });

696: $sgml->element('BLOCK',".*/LIST/[^/]+",sub {
697:     my ($sgml,$element) = @_;
698:     my ($title,$pretitle);
699:     print $out $sgml->stack('list block end');
700:     print $out "</td></tr><tr><td>";
701:     $pretitle = $out->new;
702:     $title = $out->new;
703:     print $out $sgml->stack('list block start');
704:     print $out &check_for_id($sgml,$element);

706:     $sgml->process_content_filt('title location',$title);

708:     if (defined $title->read) {
709:         print $pretitle "<span class=\"title\">";
710:         print $title "</span>";
711:     }
712: });

714: $sgml->element('TITLE','.*/LIST(/BLOCK)?/[^/]+',\&Title_Loc);

716: $sgml->element('ITEM',".*/LIST(/BLOCK)?/[^/]+",sub {
717:     my ($sgml,$element) = @_;

719:     print $out "<li>";
720:     print $out &check_for_id($sgml,$element);
721:     $sgml->process_content;
722:     print $out "</li>\n";
723: });
724:  

726: $sgml->element('TABLE',\&Table);
727: $sgml->element('INLINE.TABLE',\&Table);

729: $sgml->element('EXT.XREF',sub {
730:     my ($sgml,$element) = @_;
731:     my ($pointer,$targetvol,$targetdiv,$targetart,$tmp,$numvol);
732:     Count_Increment($sgml,'crossref');
733:     $pointer = $element->attr('POINTER')->value;

735:     my @info = Handbook::General::Get_Article_Info($pointer);
736:     if (@info < 1 || !defined $info[4]) {
737:         warn "WARNING:ext.ref:no data found for article $pointer\n";
738:         print $out "<A HREF=\"\">";
739:         print $out "<!--ERROR:FAILED TO LOOKUP $pointer-->" if $do_comments;
740:     } else {
741:         my ($title,$id,$v,$d,$a,$p) = @info;
742:         $targetdiv = $d;
743:         $targetdiv = '0' . (0+$targetdiv) if $targetdiv < 10;
744:         $targetart = $a;
745:         $targetart = '0' . (0+$targetart) if $targetart < 10;
746:         $targetvol = $v;
747:         if ($targetvol !~ /\D/) {
748:             $targetvol = '0' . (0+$targetvol) if $targetvol < 10;
749:             $numvol = 0;
750:         } else {
751:             $numvol = 1;
752:         }

754:         print $out "<A HREF=\"";
755:         if (($numvol && $volnum !~ /\D/ && $targetvol == $volnum) || 
756:             ($targetvol eq $volnum)) {
757:             if ($targetdiv == $divnum) {
758:                 print $out "../A$targetart/";
759:             } else {
760:                 print $out "../../D$targetdiv/A$targetart/";
761:             }
762:         } else {
763:             $tmp = '';
764:             $tmp = 'V' unless $numvol;
765:             print $out "../../../$tmp$targetvol/D$targetdiv/A$targetart/";
766:         }
767:         print $out "index.html\">";
768:     }

770:     $sgml->process_content;

772:     print $out "</A>";
773: });

775: $sgml->element(['XREF','REFERENCE','FNREF'],\&Reference);

777: $sgml->element('FOOTNOTE',sub {
778:     my ($sgml,$element) = @_;
779:     my ($tabnotes,$notebody,$referencetext,$saved,$notecount,$label,$marker);

781:     #warn "checking footnote type\n";
782:     if (Ancestor($element,'TABLE','INLINE.TABLE')) {
783:         #warn "processing table footnote\n";
784:         $tabnotes = $sgml->globalrefs('table footnote count');
785:         if ($$tabnotes == 0) {
786:             $notebody = new Data::Locations::Shell();
787:             $sgml->global('table notes',$notebody);
788:         } else {
789:             $notebody = $sgml->global('table notes');
790:         }
791:         $$tabnotes += 1;
792:         $label = '('.lc(NumToTableNoteLetter($$tabnotes)).')';
793:         set_gen_numbering($element->attr('ID')->value,$label);
794:         print $notebody '<tr><td  valign="top" class="label">'.$label.'</td><td valign="top" class="body">';
795:         print $notebody &check_for_id($sgml,$element);
796:         $saved = $out;
797:         $out = $notebody;
798:         $sgml->process_content;
799:         $out = $saved;
800:         print $notebody "</td></tr>\n";
801:     } else {
802:         #warn "processing footnote\n";
803:         $notecount = $sgml->globalrefs('footnote count');
804:         if ($$notecount == 0) {
805:             $notebody = new Data::Locations::Shell();
806:             $sgml->global('article notes',$notebody);
807:         } else {
808:             $notebody = $sgml->global('article notes');
809:         }
810:         $notebody = $notebody->new;
811:         set_ID_content($element->attr('ID')->value,$notebody);
812:         $$notecount += 1;

814:         #assert($$notecount > 0);
815:         if ($$notecount > $#footnote_marker) {
816:             warn "WARN:Footnote count exceeds number of available symbols\n";
817:             if ($footnote_marker[0] eq '0') {
818:                 $marker = $$notecount;
819:             } else {
820:                 $marker = $footnote_marker[0] x $$notecount;
821:             }
822:         } else {
823:             $marker = $footnote_marker[$$notecount];
824:         }
825:         set_gen_numbering($element->attr('ID')->value,$marker);
826:         #$ref = $sgml->stack('Section References List');
827:         #$$ref{lc $idref} = 1;
828:         print $notebody "<tr><td valign='top' class='label'>".$marker.
829:             "</td><td valign='top' class='body'>";
830:         print $notebody &check_for_id($sgml,$element);
831:         $saved = $out;
832:         $out = $notebody;
833:         $sgml->process_content;
834:         $out = $saved;
835:         print $notebody "</td></tr>\n";
836:     }
837: });

839: $sgml->element(['TITLE','DIV.CHAIR.DISPLAY','BYLINE.DISPLAY','DIV.TITLE',
840:                 'SERIES','VOL.NO'],
841:                '.*/ARTICLE\.INFO(/.*)?',\&proc_artinfosub);

843: $sgml->element('REF.SECT',sub {
844:     my ($sgml,$element) = @_;
845:     my ($title);
846:     
847:     start_section($sgml,$element);
848:     $sgml->stack('_Section Refs Location', #no need for separate refs list
849:                  new Data::Locations::Shell('/dev/null'));

851:     $title = $sgml->stack('toc title');
852:     print $title 'Reference';
853:     print $title 's' if $element->attr('PLURAL')->value == 1;
854:     
855:     print $out '<h3 class="sect-title">';
856:     print $out $title;
857:     print $out '</h3>';

859:     $sgml->process_content;

861:     finish_section($sgml,$element);
862: });

864: $sgml->element('SELECT.SECT',sub {
865:     my ($sgml,$element) = @_;
866:     my ($title);

868:     start_section($sgml,$element);

870:     $title = $sgml->stack('toc title');
871:     print $title 'Selected References';

873:     print $out '<h3 class="sect-title">';
874:     print $out $title;
875:     print $out '</h3>';

877:     $sgml->process_content;

879:     finish_section($sgml,$element);
880: });

882: $sgml->element('REF.LIST', sub { #can have title and ref.block content
883:     my ($sgml,$element) = @_;
884:     $sgml->stack('seen content',1);
885:     my $type = 'numbered';
886:     $type = 'selected' if (Ancestor($element,'SELECT.SECT'));

888:     print $out "<table $layout_table_attr class='$type-refs-list'>";
889:     $sgml->stack_new('title location',$out->new);
890:     $sgml->process_content;
891:     print $out "</table>\n";
892: });

894: $sgml->element('REF.BLOCK', sub { #can have title
895:     my ($sgml,$element) = @_;
896:     my $type = 'numbered';
897:     $type = 'selected' if (Ancestor($element,'SELECT.SECT'));

899:     print $out "<tr><td></td><td><table $layout_table_attr class='$type-refs-block'>";
900:     $sgml->stack_new('title location',$out->new);

902:     $sgml->process_content;
903:     print $out "</table></td></tr>\n";
904: });

906: $sgml->element('TITLE','.*/REF\.(LIST|BLOCK)/[^/]+',sub {
907:     my ($sgml,$element) = @_;
908:     my $savedout = $out;
909:     $out = $sgml->stack('title location');
910:     print $out "<tr><td colspan=2><h3 class=\"sect-title\">";  #list-title?
911:     $sgml->process_content;
912:     print $out "</h3></td></tr>\n";
913:     $out = $savedout;
914: });

916: $sgml->element('REF.ITEM', sub {
917:     my ($sgml,$element) = @_;
918:     my ($savedout);
919:     $savedout = $out;
920:     $out = $out->new; #location for just this reference
921:     my $type = 'numbered';
922:     $type = 'selected' if (Ancestor($element,'SELECT.SECT'));

924:     #these explicit valign attrs were necessary 20001023
925:     print $out "<tr><td class='label' valign='top'>";
926:     print $out &check_for_id($sgml,$element);
927:     if (!Ancestor($element,'SELECT.SECT')) {
928:         gen_numbering_simple($element);
929:         Count_Increment($sgml,'numbered reference');
930:         set_ID_content($element->attr('ID')->value,$out);
931:         print $out &read_gen_numbering($element->attr('ID')->value),'.';
932:     } else {
933:         Count_Increment($sgml,'unnumbered reference');
934:         set_ID_content($element->attr('ID')->value,$out);
935:         # can't print saved numbering here, because it might be in the note 
936:         # body already (data not marked up for this)
937:         print $out &Entity('bull');
938:     } 
939:     print $out "</td><td valign='top' class='body'>";
940:     $sgml->process_content;
941:     print $out "</td></tr>\n";
942:     $out = $savedout;
943: });

945: $sgml->element('CAUTION',sub {
946:     my ($sgml,$element) = @_;
947:     print $out "<span class='caution'>Caution: ";
948:     $sgml->process_content;
949:     print $out "</span>"
950: });

952: $sgml->element('BLOCK.QUOTE',sub {
953:     my ($sgml,$element) = @_;
954:     $sgml->stack('seen content',1);
955:     print $out "<table width='100%' $layout_table_attr><tr><td width='10%'></td><td>";
956:     $sgml->process_content;
957:     print $out "</td><td width='10%'></td></tr></table>"
958: });

960: $sgml->element('SIG.BLOCK',sub {
961:     my ($sgml,$element) = @_;
962:     $sgml->stack('seen content',1);
963:     print $out "<table width='100%' $layout_table_attr><td width='20%'></td><tr><td class='sig-block'>";
964:     $sgml->process_content;
965:     print $out "</td></tr></table>"
966: });

968: $sgml->element('ACKNOWLEDGE',sub {
969:     my ($sgml,$element) = @_;
970:     my ($title);

972:     start_section($sgml,$element,'nosplit'=>1,'notoc'=>1);

974:     $title = $sgml->stack('toc title');
975:     print $title 'Acknowledgement';
976:     print $title 's' if $element->attr('PLURAL')->value == 1;
977:     print $out '<h3 class="sect-title">';
978:     print $out $title;
979:     print $out '</h3>';

981:     $sgml->process_content;
982:     finish_section($sgml,$element);
983: });

985: $sgml->element('TITLE','.*/EXAMPLE/[^/]+',\&Title_Loc);

987: $sgml->element('EXAMPLE',sub {
988:     my ($sgml,$element) = @_;
989:     my ($id,$toc,$titleloc,$titlesub,$titleprefix);
990:     Count_Increment($sgml,'example');
991:     gen_numbering_dual($element);

993:     start_section($sgml,$element);

995:     $id = $element->attr('ID');
996:     $id = $id->value if defined $id;

998:     print $out '<h3 class="sect-title">';
999:     $titleloc = $out->new;
1000:     if ($element->attr('NUMBERED')->value != 0) {
1001:         print $titleloc "Example ",&read_gen_numbering($id);
1002:     } else {
1003:         print $titleloc "Example";
1004:     }
1005:     $titleprefix = $titleloc->new;
1006:     $titlesub = $titleloc->new;
1007:     print $out "</h3>\n";

1009:     $toc = $sgml->stack('toc title');
1010:     print $toc $titleloc;

1012:     $sgml->process_content_filt('title location',$titlesub);

1014:     if ($element->attr('NUMBERED')->value != 0 || defined $titlesub->read) {
1015:         print $titleprefix ": ";
1016:     }
1017:     finish_section($sgml,$element);
1018: });

1020: $sgml->element('EQUATION', sub {
1021:     my ($sgml,$element) = @_;
1022:     Count_Increment($sgml,'equation');
1023:     $sgml->stack('seen content',1);
1024:     gen_numbering_dual($element);
1025:     $sgml->stack_new('title style start' => "<h5 class=\"title\">",
1026:                      'title style end' => "</h5>",
1027:                      'image caption position',"right");
1028:     
1029:     print $out &check_for_id($sgml,$element);
1030:     print $out '<table border=0 width="100%"><tr><td align=center>';
1031:     print $out '<!--'.$element->name.'-->' if $do_comments;
1032:     print $out '<table border=0><tr><td align=left>';
1033:     $sgml->process_content;
1034:     print $out '</td></tr></table>';
1035:     print $out '</td>';
1036:     if ($element->attr('NUMBERED')->value != 0) {
1037:         print $out "<td align=right><strong>(Eq ";
1038:         print $out &read_gen_numbering($element->attr('ID')->value);
1039:         print $out ")</strong></td>";
1040:     }
1041:     print $out  "</tr>\n";
1042:     print $out "<!--".$element->name."-->" if $do_comments;
1043:     print $out "</table>\n";
1044: });

1046: $sgml->element('FIG.GRP',sub {
1047:     my ($sgml,$element) = @_;
1048:     my ($pretitle,$title,$body,$precaption,$caption,$savedout);
1049:     print $out &check_for_id($sgml,$element);
1050:     #gen_numbering_dual($element); #numbering is based on name but this isnt FIG

1052:     print $out "<table border=1 width='100%' class='figure-group'><tr><td><table $layout_table_attr width='100%'>";
1053:     print $out "<!--".$element->name."-->" if $do_comments;
1054:     $pretitle = $out->new;
1055:     $title = $out->new;
1056:     print $out "<tr><td>";
1057:     $body = $out->new;
1058:     print $out "</td></tr>";
1059:     $precaption = $out->new;
1060:     $caption = $out->new;
1061:     print $out "</table></td></tr></table>\n";

1063:     ($savedout,$out) = ($out,$body);
1064:     $sgml->process_content_filt('figure caption' => $caption,
1065:                                 'title location' => $title);
1066:     $out = $savedout;

1068:     if (defined $title->read()) {
1069:         print $pretitle "<tr><td><h3 class='title'>";
1070:         print $title "</h3></td></tr>\n";
1071:     }
1072:     if (defined $caption->read()) {
1073:         print $precaption "<tr><td>";
1074:         print $caption "</td></tr>\n";
1075:     }
1076: });

1078: $sgml->element('TITLE','.*/FIG\.GRP/[^/]+',\&Title_Loc);

1080: $sgml->element('CAPTION','.*/FIG(.GRP)?/[^/]+',sub {
1081:     my ($sgml,$element) = @_;
1082:     my $savedout = $out;
1083:     $out = $sgml->stack('figure caption');
1084:     $sgml->process_content;
1085:     $out = $savedout;
1086: });

1088: $sgml->element('FIG',sub {
1089:     my ($sgml,$element) = @_;
1090:     my ($precaption,$caption,$pos,$savedout);

1092:     gen_numbering_dual($element);
1093:     Count_Increment($sgml,'figure');
1094:     $sgml->stack('seen content',1);

1096:     #print $out "<tr><td>" if (Parent($element,'FIG.GRP'));
1097:     print $out "<table $layout_table_attr class=\"figure\">";
1098:     print $out "<!--".$element->name."-->" if $do_comments;
1099:     print $out "<tr><td>";
1100:     print $out &check_for_id($sgml,$element);
1101:     $savedout = $out->new;
1102:     print $out "</td>";
1103:     $precaption = $out->new;
1104:     print $out "<td valign=top class=\"caption\">";
1105:     if ($element->attr('NUMBERED')->value != 0) {
1106:         print $out "<strong>Fig. ";
1107:         print $out &read_gen_numbering($element->attr('ID')->value);
1108:         print $out "</strong> ";
1109:     }
1110:     $caption = $out->new;
1111:     print $out "</td>";
1112:     print $out "</tr>";
1113:     print $out "<!--".$element->name."-->" if $do_comments;
1114:     print $out "</table>\n";
1115:     #print $out "</td></tr>" if (Parent($element,'FIG.GRP'));

1117:     ($out,$savedout) = ($savedout,$out);
1118:     ($caption,$pos) = $sgml->process_content_filt('figure caption'=> $caption,'image caption position','right','title style start' => "<tr><td colspan=2><h3 class=\"title\">",'title style end'=> "</h3></td></tr>");
1119:     ($out,$savedout) = ($savedout,$out);

1121:     #if (Parent($element,'FIG.GRP') || $pos ne 'right') {
1122:     print $precaption "</tr>\n<tr>";
1123:     #}
1124: });

1126: $sgml->element('IMAGE',sub {
1127:     use integer;
1128:     my ($sgml,$element) = @_;
1129:     my ($class,$id,$width,$height,$type,$urltofull,$urltoinline);
1130:     $id = $element->attr('ID')->value;
1131:     $type = lc $element->attr('IMAGE.TYPE')->value;
1132:     $class = lc $element->attr('IMAGE.CLASS')->value;

1134:     Count_Increment($sgml,$class) if ($class eq 'lineart' || $class eq 'halftone' || $class eq 'color');

1136:     if (defined($id) && $id =~ /^([LIQ])((\d)(\d)(\d)(\d)(\d)(\d)(\d))$/) {
1137:         #$class = $1;
1138:         #$id = $class.$2;
1139:         
1140:         ($urltofull,$urltoinline,$width,$height) =
1141:             LookupGraphic($id,$class,$type);
1142:         #if ($width > 480 || (3*$width) > (4*$height)) {
1143:         #    $sgml->stack('image caption position','bottom');
1144:         #}
1145:         
1146:         print $out "<A href=\"$urltofull\">" if ($do_external_images{$class});
1147:         print $out "ID:$id<br>" if ($do_manuscript);
1148:         print $out "<IMG src=\"$urltoinline\" alt=\"$class:$id\" width=$width height=$height border=0>";
1149:         print $out "</A>" if ($do_external_images{$class});
1150:         print $out "\n";
1151:     } else {
1152:         warn "WARN: Image id is invalid: '$id'\n";
1153:         print $out "<!--FLAG:IMAGE:invalid id [$id]-->" if $do_comments;
1154:     }
1155:     
1156:     $sgml->suppress_content;
1157: });

1159: $sgml->element('IMAGE','.*/(FIG|EQUATION|TABLE|INLINE\.TABLE)/[^/]+',sub {
1160:     use integer;
1161:     my ($sgml,$element) = @_;
1162:     my ($class,$id,$width,$height,$type,$urltofull,$urltoinline);
1163:     $id = $element->attr('ID')->value;
1164:     $type = lc $element->attr('IMAGE.TYPE')->value;
1165:     $class = lc $element->attr('IMAGE.CLASS')->value;

1167:     Count_Increment($sgml,$class) if ($class eq 'lineart' || $class eq 'halftone' || $class eq 'color');

1169:     if (defined($id) && $id =~ /^([LIQ])((\d)(\d)(\d)(\d)(\d)(\d)(\d))$/) {
1170:         #$class = $1;
1171:         #$id = $class.$2;
1172:         
1173:         ($urltofull,$urltoinline,$width,$height) =
1174:             LookupGraphic($id,$class,$type);
1175:         if ($width > 480 || (3*$width) > (4*$height)) {
1176:             $sgml->stack('image caption position','bottom');
1177:         }
1178:         
1179:         print $out "<A href=\"$urltofull\">" if ($do_external_images{$class});
1180:         print $out "ID:$id<br>" if ($do_manuscript);
1181:         print $out "<IMG src=\"$urltoinline\" alt=\"$class:$id\" width=$width height=$height border=0>";
1182:         print $out "</A>" if ($do_external_images{$class});
1183:         print $out "\n";
1184:     } else {
1185:         warn "WARN: Image id is invalid: '$id'\n";
1186:         print $out "<!--FLAG:IMAGE:invalid id [$id]-->" if $do_comments;
1187:     }
1188:     
1189:     $sgml->suppress_content;
1190: });

1192: $sgml->element('TITLE','.*/(INLINE\.)?TABLE/[^/]*',\&Title_Loc);

1194: $sgml->element('TGROUP', sub {
1195:     my ($sgml,$element) = @_;
1196:     my ($thead,$tfoot,%args,$rowsep,$colsep,$frame,$tagstart);

1198:     $sgml->stack_new('table span specification' => { },
1199:                      'table column specification' => { },
1200:                      'tgroup has colsep' => 0,
1201:                      'tgroup has rowsep' => 0,
1202:                      'table header location' => $thead=new Data::Locations::Shell(),
1203:                      'table footer location' => $tfoot=new Data::Locations::Shell());

1205:     #location for table start tag, deferred to wait for col/row sep uses
1206:     $tagstart = $out->new;

1208:     print $out '<!--'.$element->name.'-->' if $do_comments;
1209:     print $out $thead;
1210:     %args = ();
1211:     if (!$element->attr('TGROUPSTYLE')->is_implied) {
1212:         $args{'table style name'} = $element->attr('TGROUPSTYLE')->value;
1213:     }
1214:     if (!$element->attr('COLSEP')->is_implied) {
1215:         $args{'table column separator'} = $element->attr('COLSEP')->value;
1216:     }
1217:     if (!$element->attr('ROWSEP')->is_implied) {
1218:         $args{'table row separator'} = $element->attr('ROWSEP')->value;
1219:     }
1220:     if (!$element->attr('ALIGN')->is_implied) {
1221:         $args{'table horizontal alignment'} = $element->attr('ALIGN')->value;
1222:     }
1223:     if (!$element->attr('CHAROFF')->is_implied) {
1224:         $args{'table character offset'} = $element->attr('CHAROFF')->value;
1225:     }
1226:     if (!$element->attr('CHAR')->is_implied) { #NOTE:UNUSED
1227:         $args{'table alignment character'} = join("",$element->attr('CHAR')->value);
1228:     }
1229:     $sgml->process_content_filt(%args);
1230:     print $out $tfoot;
1231:     print $out  "\n";
1232:     print $out "<!--".$element->name."-->" if $do_comments;
1233:     print $out "</table>\n";

1235:     $frame = $sgml->stack('table frame');
1236:     $frame = lc $frame;
1237:     ($rowsep,$colsep) = $sgml->stackvals('tgroup has rowsep',
1238:                                          'tgroup has colsep');
1239:     if ($rowsep || $colsep || $frame ne 'none') {
1240:         print $tagstart "<table border=1 class='body' ";
1241:         if ($do_accurate_table_borders) {
1242:             if ($rowsep && $colsep) {
1243:                 print $tagstart "rules=all ";
1244:             } elsif ($rowsep) {
1245:                 print $tagstart "rules=rows ";
1246:             } elsif ($colsep) {
1247:                 print $tagstart "rules=cols ";
1248:             } else {
1249:                 print $tagstart "rules=none ";
1250:             }
1251:             if ($frame eq "all") {
1252:                 print $tagstart "frame=box";
1253:             } elsif ($frame eq "sides") {
1254:                 print $tagstart "frame=vsides";
1255:             } elsif ($frame eq "topbot") {
1256:                 print $tagstart "frame=hsides";
1257:             } elsif ($frame eq "top") {
1258:                 print $tagstart "frame=above";
1259:             } elsif ($frame eq "bottom") {
1260:                 print $tagstart "frame=below";
1261:             } else {
1262:                 print $tagstart "frame=void";
1263:             }
1264:         }
1265:         print $tagstart ">";
1266:     } else {
1267:         print $tagstart "<table border=0 class='body'>";
1268:     }
1269: });

1271: $sgml->element('THEAD', sub {
1272:     my ($sgml,$element) = @_;
1273:     my ($saved,$valign);
1274:     $saved = $out;
1275:     $out = $sgml->stack('table header location');
1276:     print $out "<!--".$element->name."-open-->" if $do_comments;
1277:     if ($element->attr('VALIGN')->is_implied) {
1278:         $valign = 'BOTTOM';
1279:     } else {
1280:         $valign = $element->attr('VALIGN')->value;
1281:     }
1282:     $sgml->process_content_filt('table vertical alignment',$valign,
1283:                                 'table section','HEAD');
1284:     print $out "<!--".$element->name."-close-->\n" if $do_comments;
1285:     $out = $saved;
1286: });

1288: $sgml->element('TFOOT', sub {
1289:     my ($sgml,$element) = @_;
1290:     my ($saved,$valign);
1291:     $saved = $out;
1292:     $out = $sgml->stack('table footer location');
1293:     print $out "<!--".$element->name."-open-->" if $do_comments;
1294:     if ($element->attr('VALIGN')->is_implied) {
1295:         $valign = 'TOP';
1296:     } else {
1297:         $valign = $element->attr('VALIGN')->value;
1298:     }
1299:     $sgml->process_content_filt('table vertical alignment',$valign,
1300:                                 'table section','FOOT');
1301:     print $out "<!--".$element->name."-close-->\n" if $do_comments;
1302:     $out = $saved;
1303: });

1305: $sgml->element('TBODY', sub {
1306:     my ($sgml,$element) = @_;
1307:     my ($valign);
1308:     print $out "<!--".$element->name."-open-->" if $do_comments;
1309:     if ($element->attr('VALIGN')->is_implied) {
1310:         $valign = 'TOP';
1311:     } else {
1312:         $valign = $element->attr('VALIGN')->value;
1313:     }
1314:     $sgml->process_content_filt('table vertical alignment',$valign,
1315:                                 'table section','BODY');
1316:     print $out "<!--".$element->name."-close-->\n" if $do_comments;
1317: });

1319: $sgml->element('TDESC', sub {
1320:     my ($sgml,$element) = @_;
1321:     my $savedout = $out;
1322:     $out = $sgml->stack('table description');
1323:     print $out "<!--".$element->name."-open-->" if $do_comments;
1324:     $sgml->process_content;
1325:     print $out "<!--".$element->name."-close-->\n" if $do_comments;
1326:     $out = $savedout
1327: });

1329: $sgml->element('ROW', sub {
1330:     my ($sgml,$element) = @_;
1331:     my ($valign,$rowsep,%args);
1332:     Count_Increment($sgml,'row');
1333:     print $out "<tr>";
1334:     %args = ();
1335:     if (!$element->attr('VALIGN')->is_implied) {
1336:         $args{'table vertical alignment'} = $element->attr('VALIGN')->value;
1337:     }
1338:     if (!$element->attr('ROWSEP')->is_implied) {
1339:         $args{'table row separator'} = $element->attr('ROWSEP')->value;
1340:     }
1341:     $sgml->process_content_filt(%args);
1342:     print $out "</tr>\n";
1343: });

1345: $sgml->element('SPANSPEC','.*/TGROUP/[^/]*', sub {
1346:     my ($sgml,$element) = @_;
1347:     my ($hash,$name,$start,$end,$align,$charoff,$char,$colsep,$rowsep);
1348:     $hash = $sgml->stack('table span specification');
1349:     $name  = lc $element->attr('SPANNAME')->value;
1350:     $start = $element->attr('NAMEST')->value;
1351:     $end   = $element->attr('NAMEEND')->value;
1352:     $align = $element->attr('ALIGN');
1353:     if ($align->is_implied) {
1354:         $align = undef;
1355:     } else {
1356:         $align = $align->value;
1357:     }
1358:     $charoff = $element->attr('CHAROFF');
1359:     if ($charoff->is_implied) {
1360:         $charoff = undef;
1361:     } else {
1362:         $charoff = $charoff->value;
1363:     }
1364:     $char = $element->attr('CHAR');
1365:     if ($char->is_implied) {
1366:         $char = undef;
1367:     } else {
1368:         $char = join("",$char->value); #NOTE:UNUSED
1369:     }
1370:     $colsep = $element->attr('COLSEP');
1371:     if ($colsep->is_implied) {
1372:         $colsep = undef;
1373:     } else {
1374:         $colsep = $colsep->value;
1375:     }
1376:     $rowsep = $element->attr('ROWSEP');
1377:     if ($rowsep->is_implied) {
1378:         $rowsep = undef;
1379:     } else {
1380:         $rowsep = $rowsep->value;
1381:     }

1383:     $$hash{$name} = [ $start, $end, $align, $char, $charoff, $colsep, $rowsep ];
1384:     $sgml->process_content;
1385: });

1387: $sgml->element('COLSPEC','.*/TGROUP/[^/]*', sub {
1388:     my ($sgml,$element) = @_;
1389:     my ($hash,$name,$num,$width,$align,$charoff,$char,$colsep,$rowsep);
1390:     $hash = $sgml->stack('table column specification');
1391:     $num   = join("",$element->attr('COLNUM')->value);
1392:     $name  = $element->attr('COLNAME');
1393:     if ($name->is_implied) {
1394:         $name = "c" . (0+$num);
1395:     } else {
1396:         $name = lc($name->value);
1397:     }
1398:     $width = $element->attr('COLWIDTH');
1399:     if ($width->is_implied) {
1400:         $width = undef;
1401:     } else {
1402:         $width = $width->value;
1403:     }
1404:     $align = $element->attr('ALIGN');
1405:     if ($align->is_implied) {
1406:         $align = undef;
1407:     } else {
1408:         $align = $align->value;
1409:     }
1410:     $charoff = $element->attr('CHAROFF');
1411:     if ($charoff->is_implied) {
1412:         $charoff = undef;
1413:     } else {
1414:         $charoff = $charoff->value;
1415:     }
1416:     $char = $element->attr('CHAR');
1417:     if ($char->is_implied) {
1418:         $char = undef;
1419:     } else {
1420:         $char = join("",$char->value); #NOTE:UNUSED
1421:     }
1422:     $colsep = $element->attr('COLSEP');
1423:     if ($colsep->is_implied) {
1424:         $colsep = undef;
1425:     } else {
1426:         $colsep = $colsep->value;
1427:     }
1428:     $rowsep = $element->attr('ROWSEP');
1429:     if ($rowsep->is_implied) {
1430:         $rowsep = undef;
1431:     } else {
1432:         $rowsep = $rowsep->value;
1433:     }

1435:     $$hash{$name} = [ $num, $width, $align, $char, $charoff, $colsep, $rowsep ];
1436:     $sgml->process_content;
1437: });

1439: #NOTE: This makes the asumption that ALL ENTRIES ARE SPECIFIED AND IN ORDER
1440: #      Proper handling would generate a table showing where each entry
1441: #      goes and print in order at the end
1442: #      (actually, this was done in the TeX conversion--need to re do this based
1443: #      on that now)
1444: $sgml->element('ENTRY', sub {
1445:     my ($sgml,$element) = @_;
1446:     my ($col,$span,$spec,$colnum,$colwidth,$colstart,$colend,$halign,$char,
1447:         $charoff,$colsep,$rowsep,$att,$rotate,$valign,$colspan,$rowspan,
1448:         $in_thead,$savedout);
1449:     Count_Increment($sgml,'entry');

1451:     $in_thead = 'HEAD' eq $sgml->stack('table section');

1453:     $colsep  = $sgml->stack('table column separator');
1454:     $rowsep  = $sgml->stack('table row separator');
1455:     $valign  = $sgml->stack('table vertical alignment');
1456:     $halign  = $sgml->stack('table horizontal alignment');
1457:     $charoff = $sgml->stack('table character offset');
1458:     $char    = $sgml->stack('table alignment character');

1460:     #check for a span name and fill in span info
1461:     $span = $element->attr('SPANNAME');
1462:     if (!$span->is_implied) {
1463:         $span = lc $span->value;
1464:         $spec = $sgml->stack('table span specification');
1465:         $spec = $$spec{$span};
1466:         #($colstart,$colend,$halign,$char,$charoff,$colsep,$rowsep) = @$spec;
1467:         $colstart  = $$spec[0]; #required
1468:         $colend    = $$spec[1]; #required
1469:         $halign    = $$spec[2] if defined $$spec[2];
1470:         $char      = $$spec[3] if defined $$spec[3];
1471:         $charoff   = $$spec[4] if defined $$spec[4];
1472:         $colsep    = $$spec[5] if defined $$spec[5];
1473:         $colsep    = $$spec[6] if defined $$spec[6];
1474:     }
1475:     #check for a column name and fill in column details
1476:     if (!$element->attr('COLNAME')->is_implied) {
1477:         $col = lc $element->attr('COLNAME')->value;
1478:     } elsif  (!$element->attr('NAMEST')->is_implied) {
1479:         $col = lc $element->attr('NAMEST')->value;
1480:     } elsif  (!$span->is_implied) {
1481:         $col = lc $colstart;
1482:     } else {
1483:         warn "WARN:Table entry has no column specification: ".Ancestor($element,'TABLE','INLINE.TABLE')->attr('ID')->value."\n";
1484:         $col = undef;
1485:     }
1486:     if (defined $col) {
1487:         $spec = $sgml->stack('table column specification');
1488:         $spec = $$spec{$col};
1489:         $colnum    = $$spec[0] if defined $$spec[0];
1490:         $colwidth = $$spec[1] if defined $$spec[1];
1491:         $halign   = $$spec[2] if defined $$spec[2];
1492:         $char     = $$spec[3] if defined $$spec[3];
1493:         $charoff  = $$spec[4] if defined $$spec[4];
1494:         $colsep   = $$spec[5] if defined $$spec[5];
1495:         $rowsep   = $$spec[6] if defined $$spec[6];
1496:         $colstart = $col unless defined $colstart;
1497:     }
1498:     #fill in any specified values
1499:     $att = $element->attr('NAMEST');
1500:     $colstart = $att->value unless ($att->is_implied);
1501:     $att = $element->attr('NAMEEND');
1502:     $colend   = $att->value unless ($att->is_implied);
1503:     $att = $element->attr('COLSEP');
1504:     $colsep   = $att->value unless ($att->is_implied);
1505:     $att = $element->attr('ROWSEP');
1506:     $rowsep   = $att->value unless ($att->is_implied);
1507:     $att = $element->attr('ROTATE');
1508:     $rotate   = $att->value unless ($att->is_implied);
1509:     $att = $element->attr('VALIGN');
1510:     $valign   = $att->value unless ($att->is_implied);
1511:     $att = $element->attr('ALIGN');
1512:     $halign   = $att->value unless ($att->is_implied);
1513:     $att = $element->attr('CHAROFF');
1514:     $charoff  = $att->value unless ($att->is_implied);
1515:     $att = $element->attr('CHAR');
1516:     $char     = join("",$att->value) unless ($att->is_implied); #NOTE:UNUSED

1518:     if (defined $colstart && $colstart ne '') {
1519:         warn "WARN:Column start name is invalid [$colstart]\n" unless $colstart =~ /[Cc](\d+)/;
1520:         $colstart = $1;
1521:         if (defined $colend && $colend ne '') {
1522:             warn "WARN:Column end name is invalid [$colend]\n" unless $colend =~ /[Cc](\d+)/;
1523:             $colend = $1;
1524:         } else {
1525:             $colend = $colstart;
1526:         }
1527:     } else {
1528:         warn "WARN:Column start name is unspecified\n";
1529:         print $out "<!--ERROR:Unspecified Columt start-->" if $do_comments;
1530:         $colstart = $colend = 0;
1531:     }
1532:     
1533:     $colspan = $colend - $colstart + 1;
1534:     $rowspan = $element->attr('MOREROWS')->value + 1;
1535:     $halign = lc $halign;
1536:     $valign = lc $valign;
1537:     if ($halign eq 'char') {
1538:         $halign = 'center';
1539:     } elsif ($halign eq 'justify') {
1540:         $halign = 'left';
1541:     }
1542:     if (!defined $halign || $halign eq '') {
1543:         warn "WARN:Horizontal alignment undefined: ".Ancestor($element,'TABLE','INLINE.TABLE')->attr('ID')->value."\n";
1544:         $halign = 'left';
1545:     }
1546:     if (!defined $valign || $valign eq '') {
1547:         warn "WARN:Vertical alignment undefined: ".Ancestor($element,'TABLE','INLINE.TABLE')->attr('ID')->value."\n";
1548:         $valign = 'baseline';
1549:     }
1550:     
1551:     $sgml->stack('tgroup has colsep',1) if ($colsep);
1552:     $sgml->stack('tgroup has rowsep',1) if ($rowsep);
1553:         

1555:     print $out "<td";
1556:     print $out " rowspan=$rowspan" unless $rowspan == 1;
1557:     print $out " colspan=$colspan" unless $colspan == 1;
1558:     print $out " align=$halign" unless $halign eq 'left';
1559:     print $out " valign=$valign" unless $valign eq 'baseline';
1560:     print $out ">";
1561:     print $out "<strong>" if $in_thead;
1562:     print $out &check_for_id($sgml,$element);

1564:     $savedout = $out;
1565:     $out = $out->new;
1566:     $sgml->process_content;
1567:     $out->reset;
1568:     if (join('',$out->read) =~ /\A\s*\Z/s) {
1569:         print $savedout &Entity('nbsp');  # makes empty cell non-"empty"
1570:     }
1571:     $out = $savedout;

1573:     print $out "</strong>" if $in_thead;
1574:     print $out " </td>"; # add space for borders on empty cells
1575: });

1577: $sgml->element('PROPERTY.SECT',sub {
1578:     my ($sgml,$element) = @_;
1579:     start_section($sgml,$element,'type'=>'callout');
1580:     $sgml->process_content;
1581:     finish_section($sgml,$element);
1582: });

1584: $sgml->element('PROPERTY.SECT','.*/PROPERTY.SECT/(.*/)?PROPERTY.SECT/[^/]+',sub {
1585:     my ($sgml,$element) = @_;
1586:     start_section($sgml,$element,'type'=>'runin');
1587:     $sgml->process_content;
1588:     finish_section($sgml,$element);
1589: });

1591: $sgml->element('PROPERTY.HEAD','.*/PROPERTY.SECT/[^/]+',\&Section_Title);

1593: ####################################
1594: ## Math Handlers
1595: $sgml->element(['OVERDOT','OVERBAR','OVERLINE','UNDRLINE','SUBFORM','FRACTION',
1596:                 'SUP','SUB','INF','DDOT','HAT','EQUALS','DEG','TILDE',
1597:                 'OVERRIGHTARROW','UNDERRIGHTARROW'],sub {
1598:     my ($sgml,$element) = @_;
1599:     $sgml->stack_new('math-pseudo',1);
1600:     print $out "<!--MATH:IMPLICIT:OPEN-->" if $do_comments;
1601:     $sgml->reprocess_pseudo_element('MATH');
1602:     print $out "<!--MATH:IMPLICIT:CLOSE-->" if $do_comments;
1603: });

1605: $sgml->element(['MATH','MATH.ISO'],sub {
1606:     my ($sgml,$element) = @_;
1607:     my ($tex,$simple,$content,$savedout,$complete,$real_math);
1608:     print $out "<!--MATH:INLINE:OPEN-->" if $do_comments;

1610:     $real_math = $sgml->stack_exists('math-pseudo');
1611:     if ($real_math && $sgml->stack('math-pseudo')) {
1612:         $real_math = 0;
1613:     } else {
1614:         $real_math = 1;
1615:     }
1616:     my %constructs = ();
1617:     my @styles = ();
1618:     if (Parent($element,"ITALIC")) {
1619:         push @styles, 'italic';
1620:     } else {
1621:         push @styles, 'roman'; # if (@styles == 0);
1622:     }
1623:     push @styles, 'bold' if (Parent($element,"BOLD"));

1625:     $tex = new Data::Locations::Shell;
1626:     $simple = $out->new;
1627:     $savedout = $out;
1628:     $out = $tex;
1629:     print $tex "\$";
1630:     $sgml->handler_mode_push('MATH','DEFAULT'); #keep default for PI
1631:     ($content,$complete) = 
1632:         $sgml->process_content_filt('math content','empty',
1633:                                     'complete math handling','complete',
1634:                                     'math element open',$real_math,
1635:                                     'math constructs',\%constructs,
1636:                                     'normal output',$savedout,
1637:                                     'simple output',$simple,
1638:                                     'math formatting','inline',
1639:                                     'math text style',\@styles,
1640:                                     'math pre-script open',0);
1641:     $sgml->handler_mode_pop('MATH','DEFAULT');
1642:     print $tex "\$";
1643:     $out = $savedout;

1645:     if ($complete ne 'complete') {
1646:         print $out "<!--FLAG:TEX:incomplete:",$tex,"-->" if $do_comments;
1647:         print $out "<strong><code>MATH OMITTED</code></strong>";
1648:         warn "WARNING:Math composition failed (search for 'MATH OMITTED')\n";
1649:     } else {
1650:         #constructs(symbol,fraction,compactscript,spanner,multilevelscript) {
1651:         #was the simple version good enough?
1652:         if ($content eq 'complex') {
1653:             #nope, render with TeX
1654:             $simple->delete;
1655:             print $out "<!--TEX:",$tex,"-->" if $do_comments;

1657:             my ($path,$w,$h,$b,$number,$texhash,$textmp);
1658:             #get the data from the location
1659:             $textmp = $tex;
1660:             $textmp->reset;
1661:             $tex = join '',$textmp->read;
1662:             #see if this TeX string was rendered already
1663:             $texhash = $sgml->stack('TeX rendered hash');
1664:             if (defined ($path = $$texhash{$tex})) {
1665:                 ($path,$w,$h,$b) = @$path;
1666:                 print $out "<img src=\"$path\" border=0 height=$h width=$w";
1667:                 if (defined($b) && $b) {
1668:                     print $out " style='vertical-align: $b".'%'."'";
1669:                 }
1670:                 print $out ">";
1671:             } else {
1672:                 $path = $sgml->stack('destination path');
1673:                 $number = $sgml->stack('math numbering');
1674:                 $sgml->stack('math numbering',$number + 1);
1675:                 ($w,$h,$b) = TeXtoImage("$path/math$number.png",$tex);
1676:                 if (defined $w) {
1677:                     $$texhash{$tex} = [ "math$number.png",$w,$h,$b ];
1678:                     print $out "<img src=\"math$number.png\" border=0".
1679:                         " width=$w height=$h";
1680:                     if (defined($b) && $b) {
1681:                         print $out " style='vertical-align: $b".'%'."'";
1682:                     }
1683:                     print $out ">";
1684:                 } else {
1685:                     #TeXtoImage should have printed a message for us
1686:                     print $out "<!--FLAG:TEX:rendering failed-->"
1687:                         if $do_comments;
1688:                     print $out "<strong><code>MATH OMITTED</code></strong>";
1689:                 }
1690:             }
1691:         }
1692:     }
1693:     print $out "<!--MATH:INLINE:CLOSE-->" if $do_comments;
1694: });

1696: $sgml->handler_mode('MATH');

1698: #This is here to cancel any non math specific handlers
1699: $sgml->element('',sub {
1700:     my ($sgml,$element) = @_;
1701:     my $save = $out;
1702:     $sgml->stack('complete math handling','failed');
1703:     $sgml->stack('math constructs')->{'unknown'} = 1;
1704:     $out = $sgml->stack('normal output');
1705:     warn "WARN:Unhandled Element in MATH:".$sgml->get_context."\n";
1706:     print $out "<!--MATH:IGNORE:[".$element->name."]-->" if $do_comments;
1707:     print $out &check_for_id($sgml,$element);
1708:     $sgml->suppress_content;
1709:     $out = $save;
1710:     #print $out "<!--MATH:INGORE:CLOSE[".$element->name."]-->" if $do_comments;
1711: });

1713: #for math inside implicit math elements
1714: $sgml->element('MATH', sub {
1715:     my ($sgml,$element) = @_;
1716:     $sgml->process_content_filt('math element open',1);
1717: });


1720: $sgml->element('ITALIC',sub {
1721:     my ($sgml,$element) = @_;
1722:     #$sgml->stack('complete math handling','failed');
1723:     $sgml->stack('math constructs')->{'style'} = 1;
1724:     my $simple = $sgml->stack('simple output');
1725:     my $styles = $sgml->stack('math text style');
1726:     print $simple '<em>';
1727:     push @$styles,'italic';
1728:     $sgml->process_content;
1729:     print $out "\\/"; #end italic spacer
1730:     pop @$styles;
1731:     print $simple '</em>';
1732: });
1733: $sgml->element('BOLD',sub {
1734:     my ($sgml,$element) = @_;
1735:     my $save = $out;
1736:     #$sgml->stack('complete math handling','failed');
1737:     $sgml->stack('math constructs')->{'style'} = 1;
1738:     #print $out "<!--MATH:IGNORE:[".$element->name."]-->" if $do_comments;
1739:     my $simple = $sgml->stack('simple output');
1740:     my $styles = $sgml->stack('math text style');
1741:     print $simple '<strong>';
1742:     push @$styles,'bold';
1743:     $sgml->process_content;
1744:     pop @$styles;
1745:     print $simple '</strong>';
1746: });

1748: sub texStyle {
1749:     my $listref = shift;
1750:     my %styles = ('roman'=>0,'italic'=>0,'bold'=>0,
1751:                   map { ($_ => 1) } @$listref);
1752:     my $pre = '';
1753:     my $post = '';
1754:     #no explicit italic, or tex will complain about subscripts
1755:     if (! $styles{'italic'} && $styles{'roman'}) {
1756:         $pre .= "{\\rm ";
1757:         $post .= '}';
1758:     }
1759:     if ($styles{'bold'}) {
1760:         $pre .= "{\\bf ";
1761:         $post .= '}';
1762:     }

1764:     #foreach my $s (@$listref) {
1765:     #    if ($s  eq 'italic') {
1766:     #        $pre .= "{\\it ";
1767:     #    } elsif ($s eq 'bold') {
1768:     #        $pre .= "{\\bf ";
1769:     #    } elsif ($s eq 'roman') {
1770:     #        $pre .= "{\\rm ";
1771:     #    } else {
1772:     #        warn "WARN:MATH:Ignoring text style [$s]\n";
1773:     #        $pre .= '{';
1774:     #    }
1775:     #}
1776:     return ($pre,$post); #''.('}' x $post));
1777: }

1779: $sgml->sdata('',sub {
1780:     my ($sgml,$data) = @_;
1781:     my ($name,$tex,$cont);
1782:     $name = $data->name;

1784:     $cont = '';
1785:     #look for html definition
1786:     if (defined $entity_map_html{$name}) {
1787:         $cont = '<!--ENTITY:HTML:'.$name.'-->' if ($do_comments);
1788:         $cont .= $entity_map_html{$name};
1789:         #if ($cont =~ m/\<img src=/) {
1790:         #    $cont = '';
1791:         #}
1792:     }
1793:     if ($cont ne '') {
1794:         my $simple = $sgml->stack('simple output');
1795:         print $simple $cont;
1796:     } else {
1797:         #will have to use TeX version
1798:         $sgml->stack('math content',"complex");
1799:         $sgml->stack('math constructs')->{'symbol'} = 1;
1800:     }
1801:     my ($pre,$suf) = texStyle($sgml->stack('math text style'));
1802:     if (defined ($tex = $entity_map_tex{$name})) {
1803:         if ($tex =~ /^\$(.*)\$$/) {
1804:             $tex = $1;
1805:         } else {
1806:             $tex = '\hbox{'.$tex.'}';
1807:         }
1808:         print $out $pre.$tex.$suf;
1809:     } else {
1810:         warn "WARN:Entity $name has no TeX conversion\n";
1811:         $sgml->stack('complete math handling','failed');
1812:     }
1813: });

1815: $sgml->cdata('',sub {
1816:     my ($sgml,$data) = @_;
1817:     my $simple = $sgml->stack('simple output');
1818:     print $simple $data;
1819:     #escape for TeX
1820:     $data =~ s/\s+/ /sg;
1821:     $data =~ s/\\/\\backslash/g;
1822:     $data =~ s/([\{\}\$\#\_\%])/\\$1/g; #';
1823:     $data =~ s/\^/\\hat{\\hbox{\\ }}/g;
1824:     $data =~ s/~/\\tilde{\\hbox{\\ }}/g;
1825:     $data =~ s'"'``'g;  #';
1826:     #$data =~ s'([%&\{}_~|<>#$"^])'\\$1'g;  #'; # translate TeX special chars
1827:     if ($data =~ /\S/) {
1828:         my ($pre,$suf) = texStyle($sgml->stack('math text style'));
1829:         print $out $pre.$data.$suf; #note: need concat here for unknown reason
1830:         #warn $pre.$data.$suf."\n"; #maybe Locations using "unlikely" char string?
1831:     } else {
1832:         print $out $data;
1833:     }
1834: });

1836: $sgml->element('FRACTION',sub {
1837:     my ($sgml,$element) = @_;
1838:     my ($num,$den,$format,$tmpout,$type);
1839:     #attributes:
1840:     # shape (built|case)   <implied>
1841:     # align (left|center|right)
1842:     # style lots of types, do 'single' and 'none' first, insert comments
1843:     $sgml->stack('math constructs')->{'fraction'} = 1;
1844:     $sgml->stack('math content',"complex");

1846:     print $out "{{";
1847:     $num = $out->new;
1848:     print $out "}\\over{";
1849:     $den = $out->new;
1850:     print $out "}}";

1852:     ($type) = $sgml->process_content_filt('fraction type','simple',
1853:                                           'numerator location',$num,
1854:                                           'denominator location',$den);

1856:     #$format = $sgml->stack('math formatting');
1857:     #if ($sgml->stack('math content') eq 'empty' &&
1858:     #    $format eq 'inline' && $type eq 'simple') {
1859:     #    $sgml->stack('math content',"simple fraction");
1860:     #    $tmpout = $sgml->stack('simple output');
1861:     #    print $tmpout "<sup>",$num,"</sup>/<sub>",$den,"</sub>";
1862:     #} else {
1863:     #    $sgml->stack('math content',"complex");
1864:     #}
1865: });

1867: $sgml->element('NUM',sub {
1868:     my ($sgml,$element) = @_;
1869:     my ($savedout,$content);
1870:     $savedout = $out;
1871:     $out = $sgml->stack('numerator location');
1872:     $sgml->process_content;
1873:     if (defined ($content = $out->read) && !defined $out->read) {
1874:         if ($content !~ /^\d+$/) {
1875:             $sgml->stack('fraction type',"complex");
1876:         }
1877:     } else {
1878:         $sgml->stack('fraction type',"complex");
1879:     }
1880:     $out = $savedout;
1881: });

1883: $sgml->element('DEN',sub {
1884:     my ($sgml,$element) = @_;
1885:     my ($savedout,$content);
1886:     $savedout = $out;
1887:     $out = $sgml->stack('denominator location');
1888:     $sgml->process_content;
1889:     if (defined ($content = $out->read) && !defined $out->read) {
1890:         if ($content !~ /^\d+$/) {
1891:             $sgml->stack('fraction type',"complex");
1892:         }
1893:     } else {
1894:         $sgml->stack('fraction type',"complex");
1895:     }
1896:     $out = $savedout;
1897: });

1899: sub scriptPlacement {
1900:     my ($element,$in_math) = @_;
1901:     my $precedes = 0;
1902:     my $stagger = 1; #non-math default: stagger

1904:     if ($in_math) {
1905:         #math default: compact
1906:         $stagger = $element->attr('ARRANGE');
1907:         $stagger = $stagger->value if defined $stagger;
1908:         if (defined $stagger) {
1909:             $stagger = (lc($stagger) ne 'compact');
1910:         } else {
1911:             $stagger = 0;
1912:         }
1913:         my $loc = $element->attr('LOCATION');
1914:         $loc = $loc->value if defined $loc;
1915:         if (defined $loc && lc($loc) eq 'pre') {
1916:             $precedes = 1;
1917:             #$sgml->stack('complete math handling','failed');
1918:             #warn "WARN:MATH contains SUP/INF with 'PRE' placement\n";
1919:         }
1920:     }
1921:     return ($stagger,$precedes);
1922: }

1924: sub mathScript {
1925:     my ($sgml,$element,$type) = @_;
1926:     my ($stagger,$precedes,$simple,$savedout);
1927:     if (Ancestor($element,'SUP','INF','SUB')) {
1928:         $sgml->stack('math content',"complex");
1929:     }

1931:     ($stagger,$precedes) = scriptPlacement($element,
1932:                                            $sgml->stack('math element open'));

1934:     if ($stagger) {
1935:         $sgml->stack('math constructs')->{'script'} = 1;
1936:         print $out '{}';
1937:         $simple = $sgml->stack('simple output');
1938:         print $simple "<$type>";
1939:     } else {
1940:         $sgml->stack('math constructs')->{'compactscript'} = 1;
1941:         $sgml->stack('math content',"complex");
1942:         if ($precedes) {
1943:             if (! $sgml->stack('math pre-script open')) {
1944:                 $sgml->stack('math pre-script open',1);
1945:                 print $out ' {}';
1946:             }
1947:         }
1948:     }
1949:     $sgml->stack('math pre-script open',0) unless $precedes;

1951:     if ($type eq 'sup') {
1952:         print $out '^{';
1953:     } else {
1954:         print $out '_{';
1955:     }
1956:     $sgml->process_content;
1957:     print $out '}';
1958:     if ($stagger) {
1959:         print $simple "</$type>";
1960:     }
1961: }

1963: #these have attributes: location(pre|post) and arrange(compact|stagger)
1964: $sgml->element('SUP', sub { mathScript($_[0],$_[1],'sup'); });
1965: $sgml->element(['INF','SUB'], sub { mathScript($_[0],$_[1],'sub'); });

1967: $sgml->element('SUBFORM',sub {
1968:     my ($sgml,$element) = @_;
1969:     #$sgml->stack('math content',"complex");
1970:     $sgml->stack('math pre-script open',0);
1971:     $sgml->stack('math constructs')->{'subform'} = 1;
1972:     print $out '{';
1973:     $sgml->process_content;
1974:     print $out '}';
1975: });

1977: $sgml->element('OVERBAR',sub {
1978:     my ($sgml,$element) = @_;
1979:     $sgml->stack('math content',"complex");
1980:     $sgml->stack('math constructs')->{'spanner'} = 1;
1981:     print $out '\overline{'; #used to use \bar here
1982:     $sgml->process_content;
1983:     print $out '}';
1984: });

1986: $sgml->element('OVERLINE',sub {
1987:     my ($sgml,$element) = @_;
1988:     $sgml->stack('math content',"complex");
1989:     $sgml->stack('math constructs')->{'spanner'} = 1;
1990:     print $out '\overline{';
1991:     $sgml->process_content;
1992:     print $out '}';
1993: });

1995: $sgml->element('UNDRLINE',sub {
1996:     my ($sgml,$element) = @_;
1997:     $sgml->stack('math content',"complex");
1998:     $sgml->stack('math constructs')->{'spanner'} = 1;
1999:     print $out '{\underline';
2000:     $sgml->process_content;
2001:     print $out '}';
2002: });

2004: $sgml->element('OVERDOT',sub {
2005:     my ($sgml,$element) = @_;
2006:     $sgml->stack('math content',"complex");
2007:     $sgml->stack('math constructs')->{'spanner'} = 1;
2008:     print $out '\dot{';
2009:     $sgml->process_content;
2010:     print $out '}';
2011: });

2013: $sgml->element('DDOT',sub {
2014:     my ($sgml,$element) = @_;
2015:     $sgml->stack('math content',"complex");
2016:     $sgml->stack('math constructs')->{'spanner'} = 1;
2017:     print $out '\ddot{';
2018:     $sgml->process_content;
2019:     print $out '}';
2020: });

2022: $sgml->element('TILDE',sub {
2023:     my ($sgml,$element) = @_;
2024:     $sgml->stack('math content',"complex");
2025:     $sgml->stack('math constructs')->{'spanner'} = 1;
2026:     print $out '\tilde{';
2027:     $sgml->process_content;
2028:     print $out '}';
2029: });

2031: $sgml->element('HAT',sub {
2032:     my ($sgml,$element) = @_;
2033:     $sgml->stack('math content',"complex");
2034:     $sgml->stack('math constructs')->{'spanner'} = 1;
2035:     print $out '\hat{';
2036:     $sgml->process_content;
2037:     print $out '}';
2038: });

2040: $sgml->element('DEG',sub {
2041:     my ($sgml,$element) = @_;
2042:     $sgml->stack('math content',"complex");
2043:     $sgml->stack('math constructs')->{'spanner'} = 1;
2044:     print $out '\hbox{\setbox0=\hbox{h}\dimen0=\ht0 \advance\dimen0 by -1ex\rlap{\raise.67\dimen0\hbox{\char'."'".'27}}\hbox{';
2045:     $sgml->process_content;
2046:     print $out '}}';
2047: });

2049: $sgml->element('EQUALS',sub {
2050:     my ($sgml,$element) = @_;
2051:     $sgml->stack('math content',"complex");
2052:     $sgml->stack('math constructs')->{'spanner'} = 1;
2053:     print $out '\overline{\overline{';
2054:     $sgml->process_content;
2055:     print $out '}}';
2056: });

2058: $sgml->element('OVERRIGHTARROW',sub {
2059:     my ($sgml,$element) = @_;
2060:     $sgml->stack('math content',"complex");
2061:     $sgml->stack('math constructs')->{'spanner'} = 1;
2062:     print $out '\hbox{\vbox{\ialign{#\crcr\rightarrowfill\crcr\noalign{\kern-1pt\nointerlineskip\vskip1.5pt}\hfil {';
2063:     $sgml->process_content;
2064:     print $out '}\hfil\crcr}}}';
2065: });

2067: $sgml->element('UNDERRIGHTARROW',sub {
2068:     my ($sgml,$element) = @_;
2069:     $sgml->stack('math content',"complex");
2070:     $sgml->stack('math constructs')->{'spanner'} = 1;
2071:     print $out '\hbox{\vbox{\ialign{#\crcr\hfil {';
2072:     $sgml->process_content;
2073:     print $out '}\hfil\crcr\noalign{\kern-1pt\nointerlineskip\vskip3pt}\rightarrowfill\crcr}}}';
2074: });

2076: $sgml->element('RADICAL',sub {
2077:     my ($sgml,$element) = @_;
2078:     $sgml->stack('math content',"complex");
2079:     $sgml->stack('math constructs')->{'spanner'} = 1;
2080:     my ($radicand,$radix) = 
2081:         $sgml->process_content_filt('radicand',new Data::Locations::Shell,
2082:                                     'radix',new Data::Locations::Shell);
2083:     if (defined $radix->read) {
2084:         print $out '{\root {',$radix,'} \of {',$radicand,'}}';
2085:     } else {
2086:         print $out '\sqrt{',$radicand,'}';
2087:     }
2088: });

2090: $sgml->element('RADICAND',sub {
2091:     my ($sgml,$element) = @_;
2092:     my $savedout = $out;
2093:     $out = $sgml->stack('radicand');
2094:     $sgml->process_content;
2095:     $out = $savedout;
2096: });

2098: $sgml->element('RADIX',sub {
2099:     my ($sgml,$element) = @_;
2100:     my $savedout = $out;
2101:     $out = $sgml->stack('radix');
2102:     $sgml->process_content;
2103:     $out = $savedout;
2104: });

2106: ## End of Handler Definitions
2107: #########################################################

2109: #last minute sanity checks
2110: if ($with_graphics_at eq 'division') {
2111:     die "cannot use division level graphics links with article level destination\n"
2112:         if ($topleveldirtype eq 'article' || $topleveldirtype eq 'id' ||
2113:             $topleveldirtype eq 'content');
2114: } elsif ($with_graphics_at ne 'local' && $with_graphics_at ne 'division' &&
2115:          $with_graphics_at ne 'absolute') {
2116:     die "graphics links must be 'local' 'division' or 'absolute'\n";
2117: }

2119: delete $ENV{'DISPLAY'}; #imagemagick inexplicably opens windows on occasion

2121: foreach $targetfile (@filelist) {
2122:     my ($res,$tocloc);
2123:     #initialize globals
2124:     $sgml->global("Suppress Next Open Para",0);
2125:     $tocloc = $out = new Data::Locations::Shell("/dev/null");
2126:     $sgml->stack_new('Link to Up Loc' => '',
2127:                      'Link to Next Loc' => '',
2128:                      'Link to Previous Loc' => '',
2129:                      'seen content' => 0,
2130:                      'Table of Contents' => $tocloc,
2131:                      'Section Type' => 'File');
2132:     $stylesheetloc = new Data::Locations::Shell("/dev/null");
2133:     if ($do_stylesheet) {
2134:         #print $stylesheetloc "<STYLE>\n<!--\n";
2135:         #open STYLEF,"<$stylesheet";
2136:         #while (<STYLEF>) { print $stylesheetloc $_; }
2137:         #close STYLEF;
2138:         #print $stylesheetloc "\n-->\n</STYLE>\n";
2139:         print $stylesheetloc '<META http-equiv="Content-Style-Type" content="text/css"><LINK href="'.$stylesheet.'" rel=stylesheet type="text/css">'
2140:     }
2141:     
2142:     #process the input
2143:     $sgml->handler_mode('DEFAULT');
2144:     $res = $sgml->process_sgml_sysid($targetfile);
2145:     if (!defined $res) {
2146:         warn "WARNING: SGML Errors processing file $targetfile\n";
2147:         $exitcode = 1;
2148:     }
2149:     #clean up Locations
2150:     #$out->dump(); #this should only dump to /dev/null
2151:     Data::Locations->delete;
2152: }

2154: exit $exitcode;

2156: #############################################################################
2157: ## Handler Functions for multiple elements


2160: sub Entity {
2161:     my ($name,$data) = @_;
2162:     return $entity_map{$name} if defined $entity_map{$name};

2164:     my ($cont,$h,$w,$b,$file);
2165:     $data = '['.$name.']' unless defined $data;
2166:     $cont = '';

2168:     if (defined $entity_map_html{$name}) {
2169:         $cont = '<!--ENTITY:HTML:'.$name.'-->' if ($do_comments);
2170:         $cont .= $entity_map_html{$name};
2171:         #if ($do_relative_graphics && $cont =~ m/\<img src=/) {
2172:         #    $cont =~ s|(src=['""'])(/graphics/)|$1../../..$2|g;
2173:         #}
2174:     } elsif (defined $entity_map_tex{$name}) {
2175:         $file = $name.'.png';
2176:         $file = 'u-'.lc($file) if $file =~ /[A-Z]/;
2177:         ($w,$h,$b) = TeXtoImage("/data1/httpd/root/graphics/entities/$file",
2178:                              $entity_map_tex{$name});
2179:         if (defined $w) {
2180:             $cont = "<!--ENTITY:TEX:".$name."-->" if $do_comments;
2181:             if ($with_graphics_at eq 'local') {
2182:                 $cont .= "<img src='$file'";
2183:                 symlink("/data1/httpd/root/graphics/entities/".$file,
2184:                         $file);
2185:             } elsif ($with_graphics_at eq 'division') {
2186:                 $cont .= "<img src='../graphics/entities/$file'";
2187:                 symlink("/data1/httpd/root/graphics/entities/".$file,
2188:                         "../graphics/entities/".$file);
2189:             } else {
2190:                 $cont .= "<img src=\"/graphics/entities/$file\"";
2191:             }
2192:             $cont .= " border='0' width='$w' height='$h' alt='$name'";
2193:             $cont .= " style='vertical-align: ".$b.'%'."'" if defined($b) && $b != 0;
2194:             $cont .= ">";
2195:         } else {
2196:             $cont = "<!--ENTITY:FAILED:TEX:".$name."-->" if $do_comments;
2197:             $cont .= $data;
2198:             warn "WARN:Failed to generate image for entity $name\n";
2199:         }
2200:     } else {
2201:         $cont = "<!--ENTITY:FAILED:".$name."-->" if $do_comments;
2202:         $cont .= $data;
2203:         warn "WARN:Failed to find replacement for entity $name\n";
2204:     }

2206:     $entity_map{$name} = $cont; #cache this result
2207:     return $cont;
2208: }

2210: sub Title_Loc {
2211:     my ($sgml,$element) = @_;
2212:     my $savedout = $out;
2213:     $out = $sgml->stack('title location');
2214:     $sgml->process_content;
2215:     $out = $savedout;
2216: }

2218: sub Section_Title {
2219:     my ($sgml,$element) = @_;
2220:     my $savedout = $out;
2221:     my $secttype = $sgml->stack('Section Type');

2223:     $out = $sgml->stack('toc title');
2224:     $sgml->stack('section title')->print($out);

2226:     $sgml->process_content;

2228:     $out = $savedout;
2229:     if ($secttype eq 'runin') {
2230:         $sgml->global("Suppress Next Open Para",1);
2231:     }
2232: }

2234: sub Element_CalloutSection {
2235:     my ($sgml,$element) = @_;

2237:     start_section($sgml,$element);
2238:     $sgml->process_content;
2239:     finish_section($sgml,$element);
2240: }

2242: sub SimpleContentElement {
2243:     my ($sgml,$element) = @_;
2244:     my ($id,$toc,$toctitle,$cref,$tocdata,$secttype,$temp,$tocbyline);
2245:     if ($do_comments) {
2246:         $sgml->stack_new('title style start' => "<!--ERROR:Unexpected Title--><h3 class=\"sect-title\">",
2247:                          'title style end' => "</h3>");
2248:     } else {
2249:         $sgml->stack_new('title style start' => "<h3 class=\"sect-title\">",
2250:                          'title style end' => "</h3>");
2251:     }

2253:     if ($element->name eq 'INTRO') {
2254:         start_section($sgml,$element,'notoc'=>1,'toplevel'=>1);
2255:     } else {
2256:         start_section($sgml,$element);
2257:     }

2259:     $id = $element->attr('ID');
2260:     if (defined $id) {
2261:         $id = $id->value;
2262:     } else {
2263:         if ($element->name ne 'ARTICLE.BODY' &&
2264:             $element->name ne 'ARTICLE.REAR') {
2265:             print $out "<!--WARNING:NO ID ATTRIBUTE-->" if $do_comments;
2266:         }
2267:     }
2268:     
2269:     $sgml->process_content;

2271:     finish_section($sgml,$element);
2272: }

2274: sub Reference {
2275:     my ($sgml,$element) = @_;
2276:     my ($idref,$elname,$saved,$ref);
2277:     $idref = lc $element->attr('IDREF')->value;
2278:     $elname = $element->name;

2280:     if ($elname eq 'FNREF') {
2281:         Count_Increment($sgml,'footnote');
2282:         print $out "<a href=\"#$idref\">";
2283:         if (Ancestor($element,'TABLE','INLINE.TABLE')) {
2284:             print $out "<sup>";
2285:             print $out &read_gen_numbering($idref);
2286:             print $out "</sup>";
2287:         #} elsif (Ancestor($element,'TITLE')) {
2288:         #    print $out "<strong>*</strong>";
2289:         #    $ref = $sgml->stack('Section Notes List');
2290:         #    $$ref{$idref} = 1;
2291:         } else {
2292:             print $out "<sup><strong>";
2293:             print $out &read_gen_numbering($idref);
2294:             print $out "</strong></sup>";
2295:             $ref = $sgml->stack('Section Notes List');
2296:             $$ref{$idref} = 1;
2297:         }
2298:         print $out "</a>";
2299:         #discard content
2300:         $saved = $out;
2301:         $out = new Data::Locations::Shell('/dev/null');
2302:         $sgml->process_content;
2303:         $out->delete();
2304:         $out = $saved;
2305:     } else {
2306:         if ($elname eq 'REFERENCE') {
2307:             #local file reference
2308:             print $out "<A HREF=\"#$idref\">";
2309:             $ref = $sgml->stack('Section References List');
2310:             $$ref{lc $idref} = 1;
2311:         } elsif ($elname eq 'XREF') {
2312:             print $out "<A HREF=\"",read_ID_file($idref),"#$idref\">";
2313:         }
2314:         Count_Increment($sgml,'crossref');
2315:         $sgml->process_content; #prints the label for the ref--could gen this
2316:         if ($elname eq 'REFERENCE' ||
2317:             $element->attr('XREF.TYPE')->value ne 'other') {
2318:             print $out " ";
2319:             print $out &read_gen_numbering($idref);
2320:         } else {
2321:             warn "WARN:Cross reference with type 'other' handled minimally\n";
2322:         }
2323:         print $out "</A>";
2324:     }
2325: }

2327: sub Table {
2328:     my ($sgml,$element) = @_;
2329:     my ($notecount,$subtable,$label,$realtable,$numbered,$tdesc,
2330:         $titleloc,%args,$cref);

2332:     $notecount = $sgml->globalrefs('table footnote count');
2333:     $subtable = Ancestor($element,'TABLE','INLINE.TABLE');
2334:     $realtable = $element->name eq 'TABLE';
2335:     if (! $subtable) {
2336:         $$notecount = 0;
2337:     }

2339:     $sgml->stack('seen content',1);
2340:     if ($realtable) {
2341:         $label = gen_numbering_dual($element);
2342:         Count_Increment($sgml,'table');
2343:     }

2345:     #print $out '<div class="table">';
2346:     print $out &check_for_id($sgml,$element);
2347:     print $out "<table $layout_table_attr class='table'>";
2348:     print $out '<!--'.$element->name.'-->' if $do_comments;
2349:     $titleloc = $out->new;
2350:     print $titleloc "<tr><td><span class='title'><strong>";

2352:     $sgml->stack_new('table description' => $tdesc=new Data::Locations::Shell,
2353:                      'image caption position' => "bottom",
2354:                      'title location',$titleloc,
2355:                      'table section','UNKNOWN');
2356:     %args = ();
2357:     if ($realtable) {
2358:         print $titleloc "Table ",$label," " if $label ne '';
2359:         if (!$element->attr('TABSTYLE')->is_implied) {
2360:             $args{'table style name'} = $element->attr('TABSTYLE')->value;
2361:         }
2362:         if ($element->attr('COLSEP')->is_implied) {
2363:             $args{'table column separator'} = "1";
2364:         } else {
2365:             $args{'table column separator'} = $element->attr('COLSEP')->value;
2366:         }
2367:         if ($element->attr('ROWSEP')->is_implied) {
2368:             $args{'table row separator'} = "1";
2369:         } else {
2370:             $args{'table row separator'} = $element->attr('ROWSEP')->value;
2371:         }
2372:         if (!$element->attr('FOLD')->is_implied) {
2373:             $args{'table folding'} = $element->attr('FOLD')->value;
2374:         }
2375:         if (!$element->attr('ORIENT')->is_implied) {
2376:             $args{'table orientation'} = $element->attr('ORIENT')->value;
2377:         }
2378:         if (!$element->attr('FRAME')->is_implied) {
2379:             $args{'table frame'} = $element->attr('FRAME')->value;
2380:         }
2381:     } else {
2382:         #these are all implied in real tables, anyway
2383:         $args{'table row separator'} = "1";
2384:         $args{'table column separator'} = "1";
2385:         $args{'table frame'} = "all";
2386:     }

2388:     $sgml->process_content_filt(%args);

2390:     print $titleloc "</strong>";
2391:     print $titleloc "TableID:".($element->attr('ID')->value) if ($do_manuscript && defined($element->attr('ID')));
2392:     print $titleloc "</span></td></tr>\n<tr><td>";
2393:     $tdesc->reset;
2394:     if (defined $tdesc->read()) {
2395:         print $titleloc $tdesc,"</td></tr>\n<tr><td>";
2396:     }

2398:     print $out "</td></tr>\n";
2399:     
2400:     if (! $subtable && $$notecount > 0) {
2401:         print $out "<tr><td>";
2402:         print $out "<!--Footnotes-->" if $do_comments;
2403:         print $out "<table $layout_table_attr class='note-list'>\n";
2404:         print $out $sgml->global('table notes');
2405:         print $out "</table></td></tr>\n";
2406:     }
2407:     #if ($sgml->stack('table has title') {
2408:     print $out "<!--".$element->name."-->" if $do_comments;
2409:     print $out "</table>\n";
2410:     #};
2411:     #print $out "</div>\n";
2412: }
2413: sub proc_artinfosub {
2414:     my ($sgml,$element) = @_;
2415:     my $prev = $out;
2416:     $out = $sgml->stack(lc $element->name);
2417:     $sgml->process_content;
2418:     $out = $prev;
2419: }

2421: sub simple_mapped_element {
2422:     my ($sgml,$element) = @_;
2423:     print $out "<" . $simple_element_map{$element->name} . ">";
2424:     $sgml->process_content;
2425:     print $out "</" . $simple_element_map{$element->name} . ">";
2426:     #print $out " " if $element->name eq 'ITALIC'
2427: }

2429: #############################################################################
2430: ## Handler subroutines

2432: sub start_section {
2433:     my ($sgml,$element,%flags) = @_;
2434:     my ($split,$outersecttype,$secttype,$name,$temp,$savedout,$toc);
2435:     Count_Increment($sgml,'section');

2437:     $outersecttype = $sgml->stack('Section Type');
2438:     $secttype = $flags{'type'};
2439:     if (!defined $secttype || $secttype eq '') {
2440:         #check for section type (callout,runin,extralevel)
2441:         $name = $element->name;
2442:         $secttype = $section_type{$name};
2443:         if ($secttype eq 'callout') {
2444:             my $el = $element->attr('EXTRALEVEL');
2445:             if (defined $el && ! $el->is_implied && $el->value != 0) {
2446:                 $secttype = 'extralevel' ;
2447:             }
2448:         }

2450:         if (!defined($secttype) || $secttype eq '') {
2451:             warn "WARN:Section element [$name] not recognized as callout or runin\n";
2452:             $secttype = 'callout';
2453:         }
2454:     }

2456:     #setup Section Path
2457:     $temp = new Data::Locations::Shell('/dev/null');
2458:     print $temp $sgml->stack('Section Path');
2459:     $sgml->stack_new('Section Path'=>$temp);

2461:     #open file
2462:     $savedout = $out;
2463:     if ($flags{'toplevel'}) {
2464:         $out = $sgml->stack('Article Top-level Location');
2465:         $split = 0;
2466:     } elsif ($do_section_split &&
2467:              (!defined $flags{'nosplit'} || !$flags{'nosplit'}) &&
2468:              ($secttype eq 'extralevel' ||
2469:               ($secttype eq 'callout' && $outersecttype ne 'callout' &&
2470:                $sgml->stack('seen content')))) {
2471:         $split = 1;
2472:         ($out) = open_section_file($sgml,$element,$secttype);
2473:         print $out &check_for_id($sgml,$element); #so links go to top of file
2474:         #$secttype = 'extralevel' if $secttype eq 'article';
2475:     } else {
2476:         $split=0;
2477:     }

2479:     if ($flags{'notoc'}) {
2480:         #set up toc for non-listed sects
2481:         toc_add_entry($sgml,$element,'hidden');
2482:     } else {
2483:         #set up toc for callout sects
2484:         toc_add_entry($sgml,$element,$secttype);
2485:     }

2487:     print $out '<div class="'.$secttype.'-sect">';
2488:     print $out &check_for_id($sgml,$element) unless $split;
2489:     my $pretitle = $out->new;
2490:     my $title = $out->new;
2491:     my $byline = $out->new;
2492:     my $permission = $out->new;
2493:     
2494:     $sgml->stack_new('Section Type',$secttype, 'section byline'=>$byline,
2495:                      'section permission'=>$permission,
2496:                      'section title'=>$title->new,
2497:                      'section top'=>$pretitle,
2498:                      '_section title'=>$title,
2499:                      '_savedout',$savedout,
2500:                      '_splitatthislevel',$split);
2501:     return $secttype;
2502: }

2504: sub finish_section {
2505:     my ($sgml,$element) = @_;
2506:     my ($split,$savedout,$titlepost,$secttype,$sectpath,
2507:         $pretitle,$title,$byline,$permission) =
2508:         $sgml->stackvals('_splitatthislevel','_savedout','_section title',
2509:                          'Section Type',
2510:                          'Section Path','section top','section title',
2511:                          'section byline','section permission');
2512:     my ($id);

2514:     #cleanup toc
2515:     toc_finish_entry($sgml,$element);

2517:     #cleanup file
2518:     print $out "<!--".$element->name."-->" if $do_comments;
2519:     print $out "</div>\n";

2521:     #finish section heading
2522:     my ($fmt_title_s,$fmt_title_e,$fmt_byline_s,$fmt_byline_e,
2523:         $fmt_perm_s,$fmt_perm_e) = ('','',"<p class='byline'>","</p>\n",
2524:                                     "<p class='permission'>","</p>\n");
2525:     if ($secttype eq 'extralevel') {
2526:         $fmt_title_s  = "<h2 class=\"sect-title\">";
2527:         $fmt_title_e  = "</h2>\n";
2528:     } elsif ($secttype eq 'callout') {
2529:         $fmt_title_s  = "<h3 class=\"sect-title\">";
2530:         $fmt_title_e  = "</h3>\n";
2531:     } elsif ($secttype eq 'runin') {
2532:         #title handler blocks open para
2533:         $fmt_title_s  = "<" . $simple_element_map{"PARA"} . ">" .
2534:             '<span class="sect-title">';
2535:         $fmt_title_e  = "</span> ";
2536:         $fmt_byline_s = "";
2537:         $fmt_byline_e = "";
2538:         $fmt_perm_s   = "";
2539:         $fmt_perm_e   = "";
2540:     }

2542:     #print $pretitle "<hr>" if $secttype eq 'extralevel';
2543:     if (defined $title->read) {
2544:         print $pretitle $fmt_title_s;
2545:         print $titlepost $fmt_title_e;
2546:     }
2547:     if (defined $byline->read) {
2548:         print $titlepost $fmt_byline_s;
2549:         print $byline $fmt_byline_e;
2550:     }
2551:     if (defined $permission->read) {
2552:         print $byline $fmt_perm_s;
2553:         print $permission $fmt_perm_e;
2554:     }
2555:     print $permission "<hr>" if $secttype eq 'extralevel';

2557:     #update section path
2558:     print $sectpath " --> ";
2559:     $id = $element->attr('ID');
2560:     $id = $id->value if (defined $id);
2561:     if (defined $id) {
2562:         print $sectpath "<a href=\"",read_ID_file($id),"#".lc($id)."\">";
2563:     }
2564:     print $sectpath "Section: ",$title;
2565:     print $sectpath "</a>" if defined $id;

2567:     if ($split) {
2568:         close_section_file($sgml,$element);
2569:     }
2570:     $sgml->global("Suppress Next Open Para" => 0); #failsafe
2571:     $out = $savedout;
2572: }

2574: sub toc_add_entry {
2575:     my ($sgml,$element,$secttype) = @_;
2576:     my ($toc,$id,$toctitle,$tocdata,$tocbyline,$toccontent,$outersecttype);
2577:     $outersecttype = $sgml->stack('Section Type');
2578:     if ($secttype ne 'hidden' && 
2579:         ($do_full_toc || 
2580:          ( ($secttype eq 'callout' || $secttype eq 'extralevel') && 
2581:           ($outersecttype eq 'article' || 
2582:            $outersecttype eq 'extralevel')))) {
2583:         $toc = $sgml->stack('Table of Contents');
2584:     } else {
2585:         $toc = new Data::Locations::Shell('/dev/null');
2586:     }
2587:     print $toc "<li>";
2588:     $id = $element->attr('ID');
2589:     $id = $id->value if (defined $id);
2590:     if (defined $id) {
2591:         print $toc "<a href=\"",read_ID_file($id),"#".lc($id)."\">";
2592:     }
2593:     print $toc "<big><strong>" if ($secttype eq 'extralevel');
2594:     print $toc "<strong>" if ($secttype eq 'callout');
2595:     print $toc "<small>" if ($secttype eq 'runin');
2596:     $toctitle = $toc->new;
2597:     print $toc "</strong></big>" if ($secttype eq 'extralevel');
2598:     print $toc "</strong>" if ($secttype eq 'callout');
2599:     print $toc "</small>" if ($secttype eq 'runin');
2600:     print $toc (defined $id?"</a>":"");
2601:     $tocdata = $toc->new;
2602:     $tocbyline = $toc->new;
2603:     print $toc "<ul compact>";
2604:     $toccontent = $toc->new;
2605:     print $toc "</ul>\n</li>\n";
2606:     $sgml->stack_new('toc title',$toctitle,'toc byline',$tocbyline,
2607:                      'toc title byline divider',$tocdata,
2608:                      'Table of Contents',$toccontent);
2609: }

2611: sub toc_finish_entry {
2612:     my ($sgml,$element) = @_;
2613:     my ($tb,$tt,$ttbd) = $sgml->stackvals('toc byline','toc title',
2614:                                           'toc title byline divider');
2615:     if (defined $tb->read) {
2616:         print $ttbd "<br>\n";
2617:     }
2618:     if (! defined $tt->read) {
2619:         if (defined $map_element_default_title{$element->name}) {
2620:             print $tt $map_element_default_title{$element->name};
2621:         } else {
2622:             print $tt "[".$element->name."]";
2623:         }
2624:     }
2625: }

2627: #starts a new section file
2628: #pre: on stack: 'Article Section Location List','Article Heading','Table of Contents','div list reference','Link to Previous Loc','Link to Next Loc','Link to Up Loc'
2629: #     working directory is right place for content objects
2630: # in: sgml, element, section-type (for saved div elements)
2631: #out: content location, toc location, %hash of special stack args
2632: #Proper call sequence
2633: #if ($do_section_split) {
2634: #    $savedout = $out;
2635: #    ($out,$toc,@stackargs) = open_section_file($sgml,$element,$secttype);
2636: #}
2637: #$sgml->process_content_filt(@stackargs,[other stack args]);
2638: #if ($do_section_split) {
2639: #    $out = $savedout;
2640: #    close_section_file($sgml,$element,@stackargs);
2641: #}
2642: sub open_section_file {
2643:     my ($sgml,$element,$secttype) = @_;
2644:     my ($fname,$fileout,$id,$tmp,$toc,$divlistref,$content,$refs,$notes,
2645:         @sectionargs,%reflist,%notelist,$savedout,$navbarloc,$pathloc,
2646:         $currenturl,$prevlink,$nextlink,$uplink,$pretoc);
2647:     
2648:     $id = $element->attr('ID');
2649:     $id = uc $id->value if defined $id;
2650:     if (!defined $id) {
2651:         warn "WARN:open_section_file called for ". $element->name .
2652:             " with no ID, using SDUMMYID\n";
2653:         $id = 'SDUMMYID';
2654:     }
2655:     #make a new section file
2656:     #$fname = $dirpath."/".$id.".html";
2657:     if ($secttype eq 'article') {
2658:         $fname = "index.html";
2659:     } else {
2660:         $fname = $id.".html";
2661:     }
2662:     $fileout = new Data::Locations::Shell($fname);
2663:     $tmp = $sgml->stack('Article Section Location List');
2664:     push @$tmp,$fileout;
2665:     $currenturl = $fname;
2666:     
2667:     print $fileout $doctype_html,"<html>\n<head>\n";
2668:     print $fileout "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n";
2669:     print $fileout "<meta name=\"robots\" content=\"noindex,nofollow\">\n";
2670:     print $fileout "<!--TIME:".scalar(localtime(time))."-->\n"; # if $do_comments;
2671:     print $fileout "<!--VERSION:".$version_marker."-->\n"; # if $do_comments;
2672:     print $fileout "<title>",$sgml->stack('Article Title'),"</title>\n";
2673:     print $fileout $stylesheetloc if $do_stylesheet;
2674:     print $fileout "</head>\n<body bgcolor=\"white\" text=\"black\">\n";
2675:     print $fileout "<A NAME=\"".lc($id)."\"></A>"; #cheat to get section links to go to top of file
2676:     $pathloc = $fileout->new;
2677:     print $pathloc "<p class='file-path'>",$sgml->stack('Section Path'),"</p>";

2679:     print $fileout $sgml->stack('Article Heading');
2680:     $pretoc = $fileout->new;

2682:     if ($secttype ne 'article') {
2683:         #fill in next link from previous section before making new navbar
2684:         $nextlink = $sgml->stack('Link to Next Loc');
2685:         $nextlink->print("<a href='$currenturl'>[Next section in this article]</a>") if ref($nextlink);
2686:     }

2688:     #set up top navigation bar

2690:     if ($secttype ne 'article') {
2691:         $uplink = $sgml->stack('Link to Up Loc');
2692:         $prevlink = $sgml->stack('Link to Previous Loc');
2693:     } else {
2694:         $uplink = "<a href='../index.html'>[Listing of articles in this division]</a>";
2695:         $prevlink = '';
2696:     }
2697:     $navbarloc = $fileout->new;
2698:     print $navbarloc "<table $layout_table_attr width='100%'>";
2699:     print $navbarloc "<tr><td width='30%' align=left>";
2700:     print $navbarloc $prevlink;
2701:     print $navbarloc "</td><td width='40%' align=center>";
2702:     print $navbarloc $uplink;
2703:     print $navbarloc "</td><td width='30%' align=right>";
2704:     $nextlink = $navbarloc->new;
2705:     print $navbarloc "</td></tr></table>\n";

2707:     if ($secttype eq 'article') {
2708:         $uplink = "<a href='$currenturl'>[Listing of sections in this article]</a>";
2709:         $sgml->stack_new('Link to Up Loc' => $uplink,
2710:                          'Link to Next Loc' => '',
2711:                          'Link to Previous Loc' => '');
2712:         # #dont reset nextlink, so top points to first section
2713:         #$prevlink = '';
2714:     } else {
2715:         #set up new link values
2716:         #this is for next section  # at this level
2717:         #$sgml->stack('Link to Previous Loc',$prevlink);
2718:         #$sgml->stack('Link to Next Loc',$nextlink);
2719:         #this is for child sections (if used with stack_new)
2720:         #$prevlink = '';
2721:         #$nextlink = '';
2722:     }
2723:     $prevlink = 
2724:         "<a href='$currenturl'>[Previous section in this article]</a>";
2725:     $sgml->stack('Link to Next Loc' => $nextlink);
2726:     $sgml->stack('Link to Previous Loc' => $prevlink);



2730:     #set up table of contents
2731:     if  ($do_subfile_toc || $secttype eq 'article' ||
2732:          $secttype eq 'extralevel') {
2733:         print $fileout "<ul compact>\n";
2734:         $tmp = $fileout->new;
2735:         print $fileout "</ul>\n";
2736:         print $fileout "<hr>\n";
2737:         $toc = $sgml->stack('Table of Contents');
2738:         print $toc $tmp;  #insert into enclosing toc
2739:         $toc = $tmp;
2740:         $sgml->stack_new('Table of Contents' => $toc);
2741:     } else {
2742:         $toc = $sgml->stack('Table of Contents');
2743:         #print $fileout "<hr>\n";  #article heading
2744:     }

2746:     #set up included content sections
2747:     $divlistref = $sgml->stack('div list reference');
2748:     print $fileout @$divlistref;
2749:     $content = $fileout->new;
2750:     print $fileout "</div>" x scalar(@$divlistref);
2751:     push @$divlistref,'<div class="'.$secttype.'-sect">';
2752:     
2753:     #set up section reference section
2754:     $refs = $fileout->new;

2756:     #set up section notes section
2757:     $notes = $fileout->new;
2758:            
2759:     #print bottom of page navigation links
2760:     #if ($secttype ne 'article') {
2761:     print $fileout "<hr>\n";
2762:     print $fileout $navbarloc;
2763:     print $fileout $pathloc;
2764:     #if ($secttype eq 'article') {
2765:     #    $nextlink = new Data::Locations::Shell('/dev/null');
2766:     #}
2767:     print $fileout "</body>\n</html>\n";
2768:     
2769:     #need to special case this because it has to be available at current
2770:     #level for check_for_id to read the current file correctly
2771:     $sgml->stack('seen content' => 1); #prevents "sliding" before sections
2772:     $sgml->stack_new('Section File' => $fname,
2773:                      'Section References List' => { },
2774:                      'Section Notes List' => { },
2775:                      'seen content' => 0,
2776:                      #'Link to Next Loc' => $nextlink,
2777:                      #'Link to Previous Loc' => $prevlink,
2778:                      '_Section End Location' => $fileout,
2779:                      '_Section Notes Location' => $notes,
2780:                      '_Section Refs Location' => $refs);
2781:     return ($content,$toc);
2782: }

2784: #clean up after a file section
2785: # in: sgml,$element
2786: #out: n/a
2787: sub close_section_file {
2788:     my ($sgml,$element) = @_;
2789:     my ($eof_todo,$extra,@items);

2791:     my ($divlistref,$refs,$notes,$notelist,$reflist,$secttype) = 
2792:         $sgml->stackvals('div list reference','_Section Refs Location',
2793:                          '_Section Notes Location','Section Notes List',
2794:                          'Section References List','Section Type');
2795:     pop @$divlistref;

2797:     if ($secttype eq 'article') {
2798:         $extra = '';
2799:     } else {
2800:         $extra = " cited in this section";
2801:     }

2803:     $eof_todo = $sgml->stack('end of article cleanup');

2805:     @items = keys %$reflist;
2806:     if (@items > 0) {
2807:         push @$eof_todo, [ \&make_end_list, 'Reference', $extra, $refs,
2808:                           @items ];
2809:     }

2811:     @items = keys %$notelist;
2812:     if (@items > 0) {
2813:         push @$eof_todo, [ \&make_end_list, 'Note', $extra, $notes, @items ];
2814:     }

2816: }

2818: sub make_end_list {
2819:     my ($title,$post_title,$loc,@items) = @_;
2820:     # prepare a sorted (by gen num, if possible)  list of IDs

2822:     my %hash = (); #%$data;
2823:     $hash{''} = 0;
2824:     
2825:   INNER: foreach my $id (@items) {
2826:       my $num = read_gen_numbering($id);
2827:       if (ref $num) {
2828:           $num->reset;
2829:           if (defined $num->read) {
2830:               $num->reset;
2831:               $num = join '',$num->read;
2832:           } else {
2833:               $num = '';
2834:           }
2835:       }
2836:       if (defined($num) && $num ne '') {
2837:           if ($num =~ /^\d+$/) {
2838:               $hash{$id} = 0 + $num;
2839:           } elsif (exists $footnote_map{$num}) {
2840:               $hash{$id} = 0 + $footnote_map{$num};
2841:           } else {
2842:               warn "WARN:close_section_file:$title $id has unexpected ".
2843:                   "marker:[$num]\n";
2844:           }
2845:       } else {
2846:           warn "WARN:close_section_file:$title $id without ".
2847:               "marker at end of section\n";
2848:           $hash{$id} = 99999;
2849:       }
2850:   }
2851:     
2852:     @items = sort {
2853:         ($hash{$a} <=> $hash{$b}) || 
2854:             ($a cmp $b);
2855:     } @items;
2856:     
2857:     # print title
2858:     my $plural = (@items == 1) ? '' : 's';
2859:     print $loc "<hr>\n<h3 class='sect-title'>" .
2860:         $title . $plural . $post_title . "</h3>\n";
2861:     # print tag
2862:     print $loc "<table $layout_table_attr class='";
2863:     if ($title eq 'Reference') {
2864:         print $loc "numbered-ref-list";
2865:     } elsif ($title eq 'Note') {
2866:         print $loc "note-list";
2867:     }
2868:     print $loc "'>\n";
2869:     # print list  entries
2870:     foreach my $id (@items) {
2871:         print $loc &read_ID_content($id);
2872:     }
2873:     #close tag
2874:     print $loc "</table>\n";
2875: }

2877: sub check_for_id {
2878:     my ($sgml,$element) = @_;
2879:     my ($attr,$val,$file,$content,@content);
2880:     #croak "screwed up" if (! ref $element);
2881:     $attr = $element->attr('ID');
2882:     $val = '';
2883:     if (defined $attr) {
2884:         @content = $attr->value;
2885:         foreach $content (@content) {
2886:             if (ref $content) {
2887:                 if (ref $content eq 'SGML::SData') {
2888:                     $val .= "<!--SDATA:-->" if $do_comments;
2889:                 } else {
2890:                     warn "WARN:Unexpected type for attribute content: ".(ref $content);
2891:                 }
2892:             } else {
2893:                 $val .= lc $content;
2894:             }
2895:         }
2896:         if ($val ne '') {
2897:             $file = $sgml->stack('Section File');
2898:             set_ID_file($val,$file);
2899:             return '<A NAME="' . $val . '"></A>';
2900:         } else {
2901:             return '';
2902:         }
2903:     } else {
2904:         #warn "Check for ID on element with no ID attribute [".$element->name."]";
2905:         return "";
2906:     }
2907: }

2909: sub read_ID_content {
2910:     my ($id) = @_;
2911:     $id   =~ tr/A-Z/a-z/;
2912:     if (!defined $ID_Content{$id}) {
2913:         $ID_Content{$id} = Data::Locations::Shell->new("/dev/null");
2914:     }

2916:     return $ID_Content{$id};
2917: }

2919: sub set_ID_content {
2920:     my ($id,$file) = @_;
2921:     $id   =~ tr/A-Z/a-z/;
2922:     if (defined $ID_Content{$id}) {
2923:         #$ID_Content{$id}->delete;
2924:         $ID_Content{$id}->print($file);
2925:     } else {
2926:         $ID_Content{$id} = Data::Locations::Shell->new("/dev/null");
2927:         $ID_Content{$id}->print($file);
2928:     }

2930:     return $ID_Content{$id};
2931: }

2933: sub read_ID_file {
2934:     my ($id) = @_;
2935:     $id   =~ tr/A-Z/a-z/;
2936:     if (!defined $ID_File{$id}) {
2937:         $ID_File{$id} = Data::Locations::Shell->new("/dev/null");
2938:     }

2940:     return $ID_File{$id};
2941: }

2943: sub set_ID_file {
2944:     my ($id,$file) = @_;
2945:     $id   =~ tr/A-Z/a-z/;
2946:     if (defined $ID_File{$id}) {
2947:         #$ID_File{$id}->delete;
2948:         $ID_File{$id}->print($file);
2949:     } else {
2950:         $ID_File{$id} = Data::Locations::Shell->new("/dev/null");
2951:         $ID_File{$id}->print($file);
2952:     }

2954:     return $ID_File{$id};
2955: }

2957: sub read_gen_numbering {
2958:     my ($id) = @_;
2959:     $id   =~ tr/A-Z/a-z/;
2960:     if (!defined $Label{$id}) {
2961:         $Label{$id} = Data::Locations::Shell->new("/dev/null");
2962:     }

2964:     return $Label{$id};
2965: }

2967: sub set_gen_numbering {
2968:     my ($id,$label) = @_;
2969:     $id   =~ tr/A-Z/a-z/;
2970:     if (defined $Label{$id}) {
2971:         #$Label{$id}->delete;
2972:         $Label{$id}->print($label);
2973:     } else {
2974:         $Label{$id} = Data::Locations::Shell->new("/dev/null");
2975:         $Label{$id}->print($label);
2976:     }

2978:     return $Label{$id};
2979: }

2981: sub gen_numbering_dual {
2982:     my ($element) = @_;
2983:     my $numbered = $element->attr('NUMBERED');
2984:     if (defined $numbered && ref $numbered) {
2985:         $numbered = $numbered->value;
2986:     } else {
2987:         warn "WARN:Attempted to gen_numbering_dual for element without NUMBERED attribute: '".$element->name."'\n";
2988:     }
2989:     if ($numbered != 1) {
2990:         return "";
2991:     }
2992:     #if ($element->name eq 'EQUATION') {
2993:     #    my ($k,$atref);
2994:     #    $atref = $element->[2];
2995:     #    warn "Equation Attributes:\n";
2996:     #    foreach $k (keys %$atref) {
2997:     #        warn "EQ:$k:".$$atref{$k}->value."\n";
2998:     #    }
2999:     #    return "HORK";
3000:     #}
3001:     if ((ref($element) ne 'SGML::Element') ||
3002:         (ref($element->attr('ID')) ne 'SGML::Attribute') ||
3003:         (ref($element->attr('INCREASE.FIRST')) ne 'SGML::Attribute') ||
3004:         (ref($element->attr('SECOND.LEVEL')) ne 'SGML::Attribute')) {
3005:         my ($atth,$att);
3006:         warn "WARNING:Invalid object structure in gen_numbering_dual. debugging ".$element->name.":\n";
3007:         $atth = $element->attributes;
3008:         foreach $att (keys %$atth) {
3009:             #my $self = $$atth{$att};
3010:             my $attribute = $$atth{$att};
3011:             warn "A:". ($element->attr($att)->name) . "\n";
3012:             #$element->attr($att)->accept($self,$depth + 2, @_);
3013:             #warn ("Attribute: ".($$self{'name'})."\n");
3014:             warn ("defaulted\n") if $attribute->is_defaulted;
3015:             warn ("current\n") if $attribute->is_current;
3016:             warn ("specified\n") if $attribute->is_specified;
3017:             warn ("invalid\n") if $attribute->is_invalid;
3018:             warn ("implied\n") if $attribute->is_implied;
3019:             warn ("data\n") if $attribute->is_data;
3020:             warn ("tokenized\n") if $attribute->is_tokenized;
3021:             my $contents = $attribute->value();
3022:             #$"='][';
3023:             warn "V:[$contents]\n";
3024:         }
3025:  
3026:         
3027:         return "[[DEBUGTHIS]]";
3028:     }
3029:     my ($name,$id) = ($element->name,$element->attr('ID')->value);
3030:     my ($label);
3031:     $name =~ tr/A-Z/a-z/;
3032:     $id   =~ tr/A-Z/a-z/;

3034:     if ($element->attr('INCREASE.FIRST')->value eq "1") {
3035:         $Label_Prime{$name} += 1;
3036:     }
3037:     if ($element->attr('SECOND.LEVEL')->value =~ /^increase/i) {
3038:         $Label_Sub{$name}++; # magic auto-increment
3039:     } elsif ($element->attr('SECOND.LEVEL')->value =~ /^reset/i) {
3040:         $Label_Sub{$name} = "a";
3041:     }
3042:     if  ($element->attr('SECOND.LEVEL')->value =~ /^no/i) {
3043:         $label = "" . $Label_Prime{$name};
3044:     } else {
3045:         if ($name eq "table" || $name eq 'fig') {
3046:             $label = "" . $Label_Prime{$name} . "(" . $Label_Sub{$name} . ")";
3047:         } else {
3048:             $label = "" . $Label_Prime{$name} . $Label_Sub{$name};
3049:         }
3050:     }
3051:     if (defined $Label{$id}) {
3052:         #warn "Redefined label for $id\n";
3053:         #$Label{$id}->delete;
3054:         $Label{$id}->print($label);
3055:     } else {
3056:         $Label{$id} = Data::Locations::Shell->new("/dev/null");
3057:         $Label{$id}->print($label);
3058:     }

3060:     return $Label{$id};
3061: }

3063: sub gen_numbering_simple {
3064:     my ($element) = @_;
3065:     my ($name,$id) = ($element->name,$element->attr('ID')->value);
3066:     my $label;
3067:     $name =~ tr/A-Z/a-z/;
3068:     $id   =~ tr/A-Z/a-z/;
3069:     $Label_Prime{$name} = 0 unless exists $Label_Prime{$name};
3070:     $Label_Prime{$name} += 1;
3071:     $label = "" . $Label_Prime{$name};

3073:     if (defined $Label{$id}) {
3074:         #warn "Redefined label for $id\n";
3075:         #$Label{$id}->delete;
3076:         $Label{$id}->print($label);
3077:     } else {
3078:         $Label{$id} = Data::Locations::Shell->new("/dev/null");
3079:         $Label{$id}->print($label);
3080:     }
3081:   
3082:     return $Label{$id};
3083: }

3085:         
3086: sub NumToTableNoteLetter {
3087:     use integer;
3088:     my ($num) = @_;
3089:     my @let = ('a' .. 'z');
3090:     $num -= 1; # shift to 0 based
3091:     my $count = $num / @let;
3092:     my $l = $num - $count * @let;
3093:     my $str = $let[$l] x ($count + 1);
3094:     return $str;
3095: }

3097: # not used
3098: sub NumToLetter {
3099:     my ($num) = @_;
3100:     my $str = '';
3101:     my @let = ('a' .. 'z');
3102:     while ($num > 0) {
3103:         use integer;
3104:         $num -= 1; # shift to 0 based
3105:         my $onum = $num;
3106:         $num = $num / @let;
3107:         my $l = $onum - $num * @let;
3108:         $str .= $let[$l];
3109:     }
3110:     return scalar reverse $str; #chr(ord('a')-1+$num);
3111: }

3113: # returns paths to full size and inline versions, and width and height
3114: sub LookupGraphic {
3115:     my ($id,$class,$type) = @_;
3116:     my ($pathfrag,$idtype,$idnum,$fheight,$fwidth,$iwidth,$iheight,$format,
3117:         $iformat,%data,$urltofull,$urltoinline);

3119:     $class = lc $class;
3120:     $type = lc $type;
3121:     $id = lc $id;

3123:     #read database file
3124:     %data = GetGraphicDBEntry($id);
3125:     if (defined $data{'id'}) {
3126:         $iheight = $data{'inline height'};
3127:         $iwidth = $data{'inline width'};
3128:         $iformat = $format = $data{'format'};
3129:         $iformat = 'png' unless $iformat eq 'jpg';
3130:         $urltofull = Graphic_ID_Expand_Path("/data1/httpd/root/graphics/detail",
3131:                                             $id,$class,$iformat);
3132:         $urltoinline = Graphic_ID_Expand_Path("/data1/httpd/root/graphics/inline",
3133:                                               $id,$class,$iformat);
3134:     } else {
3135:         warn "WARN:Failed to find entry for $id in graphics database file\n";
3136:         $urltoinline = $urltofull = undef;
3137:         $iheight = $iwidth = undef;
3138:     }
3139:     $urltofull = "/data1/httpd/root/graphics/ASMLogo.png"
3140:         unless defined $urltofull;
3141:     $urltoinline = "/data1/httpd/root/graphics/ASMLogo.png"
3142:         unless defined $urltoinline;
3143:     if (!defined $iwidth || !defined $iheight) {
3144:         $iwidth = $iheight = 10;
3145:         $urltoinline = "/data1/httpd/root/graphics/ASMLogo.png";
3146:     }
3147:     
3148:     my $pathtofull = $urltofull;
3149:     my $pathtoinline = $urltoinline;
3150:     $urltofull =~ s|^/data1/httpd/root||;
3151:     $urltoinline =~ s|^/data1/httpd/root||;
3152:     my $basefull = $pathtofull;
3153:     my $baseinline = $pathtoinline;
3154:     $basefull =~ s/(.*\/)//;
3155:     $baseinline =~ s/(.*\/)//;

3157:     if ($with_graphics_at eq 'local') {
3158:         $urltofull = 'detail/' . $basefull;
3159:         $urltoinline = $baseinline;
3160:         symlink $pathtofull,$urltofull if $do_external_images{$class};
3161:         symlink $pathtoinline,$urltoinline;
3162:     } elsif ($with_graphics_at eq 'division') {
3163:         $urltofull = '../graphics/detail/' . $basefull;
3164:         $urltoinline = '../graphics/inline/' . $baseinline;
3165:         symlink $pathtofull,$urltofull if $do_external_images{$class};
3166:         symlink $pathtoinline,$urltoinline;
3167:     }

3169:     return ($urltofull,$urltoinline,$iwidth,$iheight);
3170: }


3173: sub TeXtoImage {
3174:     use integer;
3175:     my ($flags,@tex) = @_;
3176:     my ($texexpr,$imagef,$tempf,$width,$height,$base_adj,$comment,$data,
3177:         $line,%flag,$scale);
3178:     #read flags
3179:     $line = 0;
3180:     foreach $data (split /\s+/,$flags) {
3181:         if ($line == 0) {
3182:             $line = 1;
3183:             $imagef = $data;
3184:             next;
3185:         }
3186:         if ($data =~ /^([^=]+)=(.*)$/) {
3187:             $flag{lc $1} = lc $2;
3188:         } else {
3189:             $flag{lc $data} = 1;
3190:         }
3191:     }
3192:     #construct the TeX expression
3193:     $texexpr = '';
3194:     foreach $data (@tex) {
3195:         if (ref $data) {
3196:             #prob a location
3197:             $data->reset;
3198:             while (defined ($line = $data->read)) {
3199:                 $texexpr .= $line;
3200:             }
3201:         } else {
3202:             $texexpr .= $data;
3203:         }
3204:     }
3205:     #$texexpr =~ s/\s+/ /g; # drop newlines?
3206:     $texexpr =~ s/\A\s+//s;
3207:     $texexpr =~ s/\s+\Z//s;

3209:     #check for existing image
3210:     #warn "INFO:TeX:$imagef:".$texexpr."\n" ;
3211:     if (-f $imagef) {
3212:         if (! $flag{'force'}) {
3213:             #scan image file
3214:             warn "INFO:TeX:reusing:".$texexpr."\n" if $debug;
3215:             ($comment,$width,$height) = 
3216:                 Graphic_File_Data($imagef,'comments','width','height');
3217:             if (defined $comment) {
3218:                 if   ($comment =~ /\A\s*v(\d+)\s+(-?\d+)\s+(.*?)\s*\Z/s &&
3219:                       $1 == 1) { # comment data version
3220:                     my ($adj,$tex) = ($2,$3);
3221:                     if (! (0 > index $tex, '%')) { # undo my escape seqs
3222:                         $tex = join "\\", split '%/', $tex;
3223:                         $tex = join "\n", split '%n', $tex;
3224:                         $tex = join '%', split '%%', $tex;
3225:                     }
3226:                     if ($tex eq $texexpr) {
3227:                         #warn "DBG:TEX:reusing $comment\n";
3228:                         return ($width,$height,$adj);
3229:                     } else {
3230:                         warn "DBG:TEX: [$texexpr] CANNOT reuse [$comment]\n";
3231:                     }
3232:                 } else {
3233:                     warn "DBG:TEX: not reusing old [$comment]\n";
3234:                     #chomp $comment;
3235:                     #return ($width,$height) if $comment eq $texexpr;
3236:                 }
3237:             }
3238:         }
3239:         unlink $imagef;
3240:     }
3241:     #create new image
3242:     $tempf = "$$";
3243:     open(TMP,">$tempf.tex") || return undef;
3244:     print TMP "\\batchmode\\input amssym \\nopagenumbers";
3245:     print TMP "\\vbox{";
3246:     #print TMP "\\hrule width3pt"; # min width spacer
3247:     print TMP "\\hrule\\hbox{";
3248:     #print TMP "\\hbox{\\vbox{\\hrule width2pt height0.2pt depth0.0pt}}";
3249:     #print TMP "\\vrule height1ex depth0"; #baseline marker
3250:     print TMP "\\vrule width1pt depth0pt"; #baseline marker
3251:     print TMP "\\setbox0=\\hbox{H}\\dimen0=\\ht0\\vbox to \\dimen0{}";  # min height spacer
3252:     #print TMP "\\hbox{\\setbox0=\\hbox{H}\\vbox to \\ht0{\\hrule width0.1pt height0.1pt depth 0.0pt}}";  # min height spacer
3253:     print TMP "\\vrule";
3254:     print TMP "\\kern0.2pt{\\vtop{\\vbox{\\kern0.2pt\\hbox{";
3255:     print TMP $texexpr;
3256:     print TMP "}}\\kern0.2pt}}\\kern0.2pt";
3257:     print TMP "\\vrule";
3258:     print TMP "}\\hrule}";
3259:     print TMP "\\bye\n";
3260:     close TMP;
3261:     unlink $tempf.".log" if -f $tempf.".log";
3262:     unlink $tempf.".dvi" if -f $tempf.".dvi";
3263:     warn "INFO:TeX:generating:".$texexpr."\n" if $debug;
3264:     system 'tex',"$tempf.tex";
3265:     if (-f $tempf.".log" && `grep -c '^[!lL ]' $tempf.log` =~ /^[^0]/) {
3266:         open TMP,"<$tempf.log";
3267:         warn "" . join("",<TMP>);
3268:         close TMP;
3269:     }
3270:     if (-f "$tempf.dvi") {
3271:         unlink "$tempf.tex";
3272:         unlink "$tempf.log";
3273:     } else {
3274:         warn "WARN:TeX:Failed to generate DVI from TeX: $texexpr\n";
3275:         return undef;
3276:     }
3277:     unlink $tempf.".eps" if -f $tempf.".eps";
3278:     system 'dvips','-q',"-E","-D","600",'-x','4750',"-o","$tempf.eps","$tempf.dvi";
3279:     if (-f "$tempf.eps") {
3280:         unlink "$tempf.dvi";
3281:     } else {
3282:         warn "WARN:TeX:Failed to generate PS image from DVI: $texexpr\n";
3283:         return undef;
3284:     }
3285:     unlink $tempf.".bmp" if -f $tempf.".bmp";
3286:     system("convert",
3287:            "-density","600", #set PS resolution
3288:            "-monochrome",
3289:            "-bordercolor","white","-border","5x5", #insure outer white border
3290:            "-pen","black","-draw","color 1,1 floodfill", #fill around box
3291:            "-crop","0x0", #crop box
3292:            "$tempf.eps","$tempf.bmp");
3293:     system("convert",
3294:            "-density","600", #set PS resolution
3295:            "-monochrome",
3296:            "-bordercolor","white","-border","5x5", #insure outer white border
3297:            #"-pen","black","-draw","color 1,1 floodfill", #fill around box
3298:            "-crop","0x0", #crop white box
3299:            "-crop","0x0", #crop black box
3300:            "$tempf.eps","$tempf-size.bmp");
3301:     #if ($imagef =~ /emsp/) {
3302:     #    warn "DBG:TEX:emsp:$tempf\n";
3303:     #    system('cp', "$tempf-size.bmp","emsp-size.bmp");
3304:     #    system('cp', "$tempf.bmp", "emsp-img.bmp");
3305:     #}

3307:     if (-f "$tempf.bmp") {
3308:         unlink "$tempf.eps";
3309:     } else {
3310:         warn "WARN:TeX:Failed to generate BMP from PS image for TeX: $texexpr\n";
3311:         return undef;
3312:     }
3313:     unlink $tempf."-slice.bmp", $tempf."-space.bmp";
3314:     $width = Graphic_File_Data($tempf."-size.bmp",'width');
3315:     system("convert",
3316:            "-crop","-".($width-1)."+0", #slice off all but left edge
3317:            $tempf."-size.bmp",$tempf."-slice.bmp");
3318:     system("convert",
3319:            "-bordercolor","black","-border","5x5", #insure outer white border
3320:            #"-pen","black","-draw","color 1,1 floodfill", #fill around box
3321:            "-crop","0x0", #crop box
3322:            $tempf."-slice.bmp",$tempf."-space.bmp");
3323:     my $h_all = Graphic_File_Data($tempf."-slice.bmp",'height');
3324:     my $h_depth = Graphic_File_Data($tempf."-space.bmp",'height');
3325:     if  (! defined $h_depth || $h_depth == 0) {
3326:         $base_adj = 0;
3327:     } else {
3328:         $base_adj = 0 - (100 * $h_depth)/$h_all;
3329:     }
3330:     unlink $tempf."-slice.bmp", $tempf."-size.bmp", $tempf."-space.bmp";
3331:     
3332:     #system("mogrify",
3333:     #       "-monochrome",
3334:     #       "-crop","0x0", #crop outside white space
3335:     #       "$tempf.bmp");
3336:     #system 'cp',$tempf.".bmp",$imagef."-crop.bmp";
3337:     $flag{'size'} = 'normal' unless defined $flag{'size'};
3338:     if ($flag{'size'} eq 'large') {
3339:         $scale = '10%x10%';
3340:     } else {
3341:         $scale = '5%x5%';
3342:     }
3343:     unlink $tempf."-s.bmp" if -f $tempf."-s.bmp";
3344:     system "convert","-geometry",$scale,"$tempf.bmp",$tempf."-s.bmp";
3345:     #system 'cp',$tempf.".bmp",$imagef."-scale.bmp";
3346:     if (-f $tempf."-s.bmp") {
3347:         unlink $tempf . ".bmp";
3348:     } else {
3349:         warn "WARN:TeX:Failed to reduce BMP for TeX: $texexpr\n";
3350:         return undef;
3351:     }
3352:     unlink $imagef if -f $imagef;
3353:     system("convert","-density","25",$tempf."-s.bmp","$imagef");
3354:     if (-f $imagef) {
3355:         unlink $tempf . "-s.bmp";
3356:     } else {
3357:         warn "WARN:TeX:Failed to reduce BMP to $imagef for TeX: $texexpr\n";
3358:         return undef;
3359:     }

3361:     # have to escape \n because imagemagick changes it to newline, but no \\
3362:     # use %, a TeX special char (comment starter, I think)
3363:     $texexpr = join('%%', split '%', $texexpr);
3364:     $texexpr = join('%n', split /\n/s, $texexpr);
3365:     $texexpr = join('%/', split /\\/, $texexpr);

3367:     system("mogrify","-comment","v1 ".$base_adj." ".$texexpr,$imagef);
3368:     ($width,$height) = Graphic_File_Data($imagef,'width','height');
3369:     if (defined $width && defined $height) {
3370:         return ($width,$height,$base_adj);
3371:     }
3372:     return undef;
3373: }

3375: #adds to current count set
3376: sub Count_Increment {
3377:     my ($sgml,$count) = @_;
3378:     my ($ref);
3379:     if ($sgml->stack_exists("$count count")) {
3380:         $ref = $sgml->stackrefs("$count count");
3381:         $$ref += 1 if defined $$ref;
3382:     }
3383: }

3385: sub ReadArgs {
3386:     my (@args) = @_;
3387:     my ($arg,$val,$oarg,@nonargs,$noscan);

3389:     $noscan = 0;
3390:     @nonargs = ();
3391:     foreach $oarg (@args) {
3392:         if ($noscan) {
3393:             push @nonargs,$oarg;
3394:         } elsif ($oarg eq '--') {
3395:             $noscan = 1;
3396:         } elsif ($oarg =~ /^-([^-].*)$/) {
3397:             ReadArgs('--verbose') if ($oarg =~ /v/);
3398:             ReadArgs('--debug') if ($oarg =~ /d/);
3399:             ReadArgs('--debug=99') if ($oarg =~ /D/);
3400:             ReadArgs('--help') if ($oarg =~ /h/);
3401:         } elsif ($oarg =~ /^--([^=]+)(=(.*))?$/) {
3402:             $arg = $1;
3403:             $val = $3;
3404:             if ($arg eq 'manuscript') {
3405:                 $do_manuscript = 1;
3406:             } elsif ($arg eq 'one-big-page') {
3407:                 $do_section_split = 0;
3408:             } elsif ($arg eq 'hide-comments') {
3409:                 $do_comments = 0;
3410:             } elsif ($arg eq 'show-comments') {
3411:                 $do_comments = 1;
3412:             } elsif ($arg eq 'show-table-lines') {
3413:                 $show_borders = 1;
3414:             } elsif ($arg eq 'hide-table-lines') {
3415:                 $show_borders = 0;
3416:             } elsif ($arg eq 'subfile-toc') {
3417:                 $do_subfile_toc = 1;
3418:             } elsif ($arg eq 'full-toc') {
3419:                 $do_full_toc = 1;
3420:             } elsif ($arg eq 'id-path') {
3421:                 $topleveldir = $val;
3422:                 $topleveldirtype = 'id';
3423:             } elsif ($arg eq 'content-path') {
3424:                 $topleveldir = $val;
3425:                 $topleveldirtype = 'content';
3426:             } elsif ($arg eq 'article-path') {
3427:                 $topleveldir = $val;
3428:                 $topleveldirtype = 'article';
3429:             } elsif ($arg eq 'division-path') {
3430:                 $topleveldir = $val;
3431:                 $topleveldirtype = 'division';
3432:             } elsif ($arg eq 'volume-path') {
3433:                 $topleveldir = $val;
3434:                 $topleveldirtype = 'volume';
3435:             } elsif ($arg eq 'stylesheet') {
3436:                 $do_stylesheet = 1;
3437:                 $stylesheet = $val;
3438:             } elsif ($arg eq 'purge-before') {
3439:                 $do_purge_before = 1;
3440:             } elsif ($arg eq 'graphics') {
3441:                 $with_graphics_at = $val
3442:             } elsif ($arg eq 'debug') {
3443:                 if (defined $val && $val ne '') {
3444:                     $debug = $val;
3445:                 } else {
3446:                     $debug = 1;
3447:                 }
3448:                 $do_comments = 1 if $debug;
3449:             } elsif ($arg eq 'help') {
3450:                 print STDOUT "
3451: $0 [arguments] sgmlfile1 sgmlfile2 ...

3453: Command line arguments:
3454:    --help                   Print helpful summary
3455:    --debug[=VAL]            Turn on debugging (set debug level to VAL)
3456:    --manuscript             Prepare manuscript review version
3457:    --stylesheet=FILE        Use stylesheet formatting (include stylesheet FILE)
3458:    --hide-comments          Hide processing comments from output
3459:    --show-comments          Opposite of above
3460:    --one-big-page           Output as a single html page, no splitting
3461:    --show-table-lines       Show all table borders (includes formatting tables)
3462:    --purge-before           Delete article directory before processing
3463:    --graphics=TOKEN         Use local, division level, or absolute link paths
3464:    --subfile-toc            Include table of contents in section files
3465:    --full-toc               List runin sections in table of contents
3466:  Only one of the following should be specified (last one will override):
3467:    --content-path=PATH      Directory to write article contents in
3468:    --article-path=PATH      Directory to create article (NUM) directories in
3469:    --division-path=PATH     Directory to create division directories in
3470:    --volume-path=PATH       Directory to create volume directories in
3471:    --id-path=PATH           Directory to create article (ID) directories in

3473: Note that all arguments are read and take effect before any processing.
3474: ";
3475:                 exit;
3476:             } else {
3477:                 die "$0: Unrecognized argument: $arg\n";
3478:             }
3479:         } else {
3480:             push @nonargs,$oarg;
3481:         }
3482:     }
3483:     
3484:     return wantarray ? @nonargs : 0 == @nonargs;
3485: }


3488: 1;