Sync with trunk r47367
[reactos.git] / lib / 3rdparty / freetype / src / tools / docmaker / tohtml.py
1 # ToHTML (c) 2002, 2003, 2005, 2006, 2007, 2008
2 # David Turner <david@freetype.org>
3
4 from sources import *
5 from content import *
6 from formatter import *
7
8 import time
9
10
11 # The following defines the HTML header used by all generated pages.
12 html_header_1 = """\
13 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
14 "http://www.w3.org/TR/html4/loose.dtd">
15 <html>
16 <head>
17 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
18 <title>\
19 """
20
21 html_header_2 = """\
22 API Reference</title>
23 <style type="text/css">
24 body { font-family: Verdana, Geneva, Arial, Helvetica, serif;
25 color: #000000;
26 background: #FFFFFF; }
27
28 p { text-align: justify; }
29 h1 { text-align: center; }
30 li { text-align: justify; }
31 td { padding: 0 0.5em 0 0.5em; }
32 td.left { padding: 0 0.5em 0 0.5em;
33 text-align: left; }
34
35 a:link { color: #0000EF; }
36 a:visited { color: #51188E; }
37 a:hover { color: #FF0000; }
38
39 span.keyword { font-family: monospace;
40 text-align: left;
41 white-space: pre;
42 color: darkblue; }
43
44 pre.colored { color: blue; }
45
46 ul.empty { list-style-type: none; }
47 </style>
48 </head>
49 <body>
50 """
51
52 html_header_3 = """
53 <table align=center><tr><td><font size=-1>[<a href="\
54 """
55
56 html_header_3i = """
57 <table align=center><tr><td width="100%"></td>
58 <td><font size=-1>[<a href="\
59 """
60
61 html_header_4 = """\
62 ">Index</a>]</font></td>
63 <td width="100%"></td>
64 <td><font size=-1>[<a href="\
65 """
66
67 html_header_5 = """\
68 ">TOC</a>]</font></td></tr></table>
69 <center><h1>\
70 """
71
72 html_header_5t = """\
73 ">Index</a>]</font></td>
74 <td width="100%"></td></tr></table>
75 <center><h1>\
76 """
77
78 html_header_6 = """\
79 API Reference</h1></center>
80 """
81
82
83 # The HTML footer used by all generated pages.
84 html_footer = """\
85 </body>
86 </html>\
87 """
88
89 # The header and footer used for each section.
90 section_title_header = "<center><h1>"
91 section_title_footer = "</h1></center>"
92
93 # The header and footer used for code segments.
94 code_header = '<pre class="colored">'
95 code_footer = '</pre>'
96
97 # Paragraph header and footer.
98 para_header = "<p>"
99 para_footer = "</p>"
100
101 # Block header and footer.
102 block_header = '<table align=center width="75%"><tr><td>'
103 block_footer_start = """\
104 </td></tr></table>
105 <hr width="75%">
106 <table align=center width="75%"><tr><td><font size=-2>[<a href="\
107 """
108 block_footer_middle = """\
109 ">Index</a>]</font></td>
110 <td width="100%"></td>
111 <td><font size=-2>[<a href="\
112 """
113 block_footer_end = """\
114 ">TOC</a>]</font></td></tr></table>
115 """
116
117 # Description header/footer.
118 description_header = '<table align=center width="87%"><tr><td>'
119 description_footer = "</td></tr></table><br>"
120
121 # Marker header/inter/footer combination.
122 marker_header = '<table align=center width="87%" cellpadding=5><tr bgcolor="#EEEEFF"><td><em><b>'
123 marker_inter = "</b></em></td></tr><tr><td>"
124 marker_footer = "</td></tr></table>"
125
126 # Header location header/footer.
127 header_location_header = '<table align=center width="87%"><tr><td>'
128 header_location_footer = "</td></tr></table><br>"
129
130 # Source code extracts header/footer.
131 source_header = '<table align=center width="87%"><tr bgcolor="#D6E8FF"><td><pre>\n'
132 source_footer = "\n</pre></table><br>"
133
134 # Chapter header/inter/footer.
135 chapter_header = '<br><table align=center width="75%"><tr><td><h2>'
136 chapter_inter = '</h2><ul class="empty"><li>'
137 chapter_footer = '</li></ul></td></tr></table>'
138
139 # Index footer.
140 index_footer_start = """\
141 <hr>
142 <table><tr><td width="100%"></td>
143 <td><font size=-2>[<a href="\
144 """
145 index_footer_end = """\
146 ">TOC</a>]</font></td></tr></table>
147 """
148
149 # TOC footer.
150 toc_footer_start = """\
151 <hr>
152 <table><tr><td><font size=-2>[<a href="\
153 """
154 toc_footer_end = """\
155 ">Index</a>]</font></td>
156 <td width="100%"></td>
157 </tr></table>
158 """
159
160
161 # source language keyword coloration/styling
162 keyword_prefix = '<span class="keyword">'
163 keyword_suffix = '</span>'
164
165 section_synopsis_header = '<h2>Synopsis</h2>'
166 section_synopsis_footer = ''
167
168
169 # Translate a single line of source to HTML. This will convert
170 # a "<" into "&lt.", ">" into "&gt.", etc.
171 def html_quote( line ):
172 result = string.replace( line, "&", "&amp;" )
173 result = string.replace( result, "<", "&lt;" )
174 result = string.replace( result, ">", "&gt;" )
175 return result
176
177
178 # same as 'html_quote', but ignores left and right brackets
179 def html_quote0( line ):
180 return string.replace( line, "&", "&amp;" )
181
182
183 def dump_html_code( lines, prefix = "" ):
184 # clean the last empty lines
185 l = len( self.lines )
186 while l > 0 and string.strip( self.lines[l - 1] ) == "":
187 l = l - 1
188
189 # The code footer should be directly appended to the last code
190 # line to avoid an additional blank line.
191 print prefix + code_header,
192 for line in self.lines[0 : l + 1]:
193 print '\n' + prefix + html_quote( line ),
194 print prefix + code_footer,
195
196
197
198 class HtmlFormatter( Formatter ):
199
200 def __init__( self, processor, project_title, file_prefix ):
201 Formatter.__init__( self, processor )
202
203 global html_header_1, html_header_2, html_header_3
204 global html_header_4, html_header_5, html_footer
205
206 if file_prefix:
207 file_prefix = file_prefix + "-"
208 else:
209 file_prefix = ""
210
211 self.headers = processor.headers
212 self.project_title = project_title
213 self.file_prefix = file_prefix
214 self.html_header = html_header_1 + project_title + \
215 html_header_2 + \
216 html_header_3 + file_prefix + "index.html" + \
217 html_header_4 + file_prefix + "toc.html" + \
218 html_header_5 + project_title + \
219 html_header_6
220
221 self.html_index_header = html_header_1 + project_title + \
222 html_header_2 + \
223 html_header_3i + file_prefix + "toc.html" + \
224 html_header_5 + project_title + \
225 html_header_6
226
227 self.html_toc_header = html_header_1 + project_title + \
228 html_header_2 + \
229 html_header_3 + file_prefix + "index.html" + \
230 html_header_5t + project_title + \
231 html_header_6
232
233 self.html_footer = "<center><font size=""-2"">generated on " + \
234 time.asctime( time.localtime( time.time() ) ) + \
235 "</font></center>" + html_footer
236
237 self.columns = 3
238
239 def make_section_url( self, section ):
240 return self.file_prefix + section.name + ".html"
241
242 def make_block_url( self, block ):
243 return self.make_section_url( block.section ) + "#" + block.name
244
245 def make_html_words( self, words ):
246 """ convert a series of simple words into some HTML text """
247 line = ""
248 if words:
249 line = html_quote( words[0] )
250 for w in words[1:]:
251 line = line + " " + html_quote( w )
252
253 return line
254
255 def make_html_word( self, word ):
256 """analyze a simple word to detect cross-references and styling"""
257 # look for cross-references
258 m = re_crossref.match( word )
259 if m:
260 try:
261 name = m.group( 1 )
262 rest = m.group( 2 )
263 block = self.identifiers[name]
264 url = self.make_block_url( block )
265 return '<a href="' + url + '">' + name + '</a>' + rest
266 except:
267 # we detected a cross-reference to an unknown item
268 sys.stderr.write( \
269 "WARNING: undefined cross reference '" + name + "'.\n" )
270 return '?' + name + '?' + rest
271
272 # look for italics and bolds
273 m = re_italic.match( word )
274 if m:
275 name = m.group( 1 )
276 rest = m.group( 3 )
277 return '<i>' + name + '</i>' + rest
278
279 m = re_bold.match( word )
280 if m:
281 name = m.group( 1 )
282 rest = m.group( 3 )
283 return '<b>' + name + '</b>' + rest
284
285 return html_quote( word )
286
287 def make_html_para( self, words ):
288 """ convert words of a paragraph into tagged HTML text, handle xrefs """
289 line = ""
290 if words:
291 line = self.make_html_word( words[0] )
292 for word in words[1:]:
293 line = line + " " + self.make_html_word( word )
294 # convert `...' quotations into real left and right single quotes
295 line = re.sub( r"(^|\W)`(.*?)'(\W|$)", \
296 r'\1&lsquo;\2&rsquo;\3', \
297 line )
298 # convert tilde into non-breakable space
299 line = string.replace( line, "~", "&nbsp;" )
300
301 return para_header + line + para_footer
302
303 def make_html_code( self, lines ):
304 """ convert a code sequence to HTML """
305 line = code_header + '\n'
306 for l in lines:
307 line = line + html_quote( l ) + '\n'
308
309 return line + code_footer
310
311 def make_html_items( self, items ):
312 """ convert a field's content into some valid HTML """
313 lines = []
314 for item in items:
315 if item.lines:
316 lines.append( self.make_html_code( item.lines ) )
317 else:
318 lines.append( self.make_html_para( item.words ) )
319
320 return string.join( lines, '\n' )
321
322 def print_html_items( self, items ):
323 print self.make_html_items( items )
324
325 def print_html_field( self, field ):
326 if field.name:
327 print "<table><tr valign=top><td><b>" + field.name + "</b></td><td>"
328
329 print self.make_html_items( field.items )
330
331 if field.name:
332 print "</td></tr></table>"
333
334 def html_source_quote( self, line, block_name = None ):
335 result = ""
336 while line:
337 m = re_source_crossref.match( line )
338 if m:
339 name = m.group( 2 )
340 prefix = html_quote( m.group( 1 ) )
341 length = len( m.group( 0 ) )
342
343 if name == block_name:
344 # this is the current block name, if any
345 result = result + prefix + '<b>' + name + '</b>'
346 elif re_source_keywords.match( name ):
347 # this is a C keyword
348 result = result + prefix + keyword_prefix + name + keyword_suffix
349 elif self.identifiers.has_key( name ):
350 # this is a known identifier
351 block = self.identifiers[name]
352 result = result + prefix + '<a href="' + \
353 self.make_block_url( block ) + '">' + name + '</a>'
354 else:
355 result = result + html_quote( line[:length] )
356
357 line = line[length:]
358 else:
359 result = result + html_quote( line )
360 line = []
361
362 return result
363
364 def print_html_field_list( self, fields ):
365 print "<p></p>"
366 print "<table cellpadding=3 border=0>"
367 for field in fields:
368 if len( field.name ) > 22:
369 print "<tr valign=top><td colspan=0><b>" + field.name + "</b></td></tr>"
370 print "<tr valign=top><td></td><td>"
371 else:
372 print "<tr valign=top><td><b>" + field.name + "</b></td><td>"
373
374 self.print_html_items( field.items )
375 print "</td></tr>"
376 print "</table>"
377
378 def print_html_markup( self, markup ):
379 table_fields = []
380 for field in markup.fields:
381 if field.name:
382 # we begin a new series of field or value definitions, we
383 # will record them in the 'table_fields' list before outputting
384 # all of them as a single table
385 #
386 table_fields.append( field )
387 else:
388 if table_fields:
389 self.print_html_field_list( table_fields )
390 table_fields = []
391
392 self.print_html_items( field.items )
393
394 if table_fields:
395 self.print_html_field_list( table_fields )
396
397 #
398 # Formatting the index
399 #
400 def index_enter( self ):
401 print self.html_index_header
402 self.index_items = {}
403
404 def index_name_enter( self, name ):
405 block = self.identifiers[name]
406 url = self.make_block_url( block )
407 self.index_items[name] = url
408
409 def index_exit( self ):
410 # block_index already contains the sorted list of index names
411 count = len( self.block_index )
412 rows = ( count + self.columns - 1 ) / self.columns
413
414 print "<table align=center border=0 cellpadding=0 cellspacing=0>"
415 for r in range( rows ):
416 line = "<tr>"
417 for c in range( self.columns ):
418 i = r + c * rows
419 if i < count:
420 bname = self.block_index[r + c * rows]
421 url = self.index_items[bname]
422 line = line + '<td><a href="' + url + '">' + bname + '</a></td>'
423 else:
424 line = line + '<td></td>'
425 line = line + "</tr>"
426 print line
427
428 print "</table>"
429
430 print index_footer_start + \
431 self.file_prefix + "toc.html" + \
432 index_footer_end
433
434 print self.html_footer
435
436 self.index_items = {}
437
438 def index_dump( self, index_filename = None ):
439 if index_filename == None:
440 index_filename = self.file_prefix + "index.html"
441
442 Formatter.index_dump( self, index_filename )
443
444 #
445 # Formatting the table of content
446 #
447 def toc_enter( self ):
448 print self.html_toc_header
449 print "<center><h1>Table of Contents</h1></center>"
450
451 def toc_chapter_enter( self, chapter ):
452 print chapter_header + string.join( chapter.title ) + chapter_inter
453 print "<table cellpadding=5>"
454
455 def toc_section_enter( self, section ):
456 print '<tr valign=top><td class="left">'
457 print '<a href="' + self.make_section_url( section ) + '">' + \
458 section.title + '</a></td><td>'
459
460 print self.make_html_para( section.abstract )
461
462 def toc_section_exit( self, section ):
463 print "</td></tr>"
464
465 def toc_chapter_exit( self, chapter ):
466 print "</table>"
467 print chapter_footer
468
469 def toc_index( self, index_filename ):
470 print chapter_header + \
471 '<a href="' + index_filename + '">Global Index</a>' + \
472 chapter_inter + chapter_footer
473
474 def toc_exit( self ):
475 print toc_footer_start + \
476 self.file_prefix + "index.html" + \
477 toc_footer_end
478
479 print self.html_footer
480
481 def toc_dump( self, toc_filename = None, index_filename = None ):
482 if toc_filename == None:
483 toc_filename = self.file_prefix + "toc.html"
484
485 if index_filename == None:
486 index_filename = self.file_prefix + "index.html"
487
488 Formatter.toc_dump( self, toc_filename, index_filename )
489
490 #
491 # Formatting sections
492 #
493 def section_enter( self, section ):
494 print self.html_header
495
496 print section_title_header
497 print section.title
498 print section_title_footer
499
500 maxwidth = 0
501 for b in section.blocks.values():
502 if len( b.name ) > maxwidth:
503 maxwidth = len( b.name )
504
505 width = 70 # XXX magic number
506 if maxwidth <> 0:
507 # print section synopsis
508 print section_synopsis_header
509 print "<table align=center cellspacing=5 cellpadding=0 border=0>"
510
511 columns = width / maxwidth
512 if columns < 1:
513 columns = 1
514
515 count = len( section.block_names )
516 rows = ( count + columns - 1 ) / columns
517
518 for r in range( rows ):
519 line = "<tr>"
520 for c in range( columns ):
521 i = r + c * rows
522 line = line + '<td></td><td>'
523 if i < count:
524 name = section.block_names[i]
525 line = line + '<a href="#' + name + '">' + name + '</a>'
526
527 line = line + '</td>'
528 line = line + "</tr>"
529 print line
530
531 print "</table><br><br>"
532 print section_synopsis_footer
533
534 print description_header
535 print self.make_html_items( section.description )
536 print description_footer
537
538 def block_enter( self, block ):
539 print block_header
540
541 # place html anchor if needed
542 if block.name:
543 print '<h4><a name="' + block.name + '">' + block.name + '</a></h4>'
544
545 # dump the block C source lines now
546 if block.code:
547 header = ''
548 for f in self.headers.keys():
549 if block.source.filename.find( f ) >= 0:
550 header = self.headers[f] + ' (' + f + ')'
551 break;
552
553 # if not header:
554 # sys.stderr.write( \
555 # 'WARNING: No header macro for ' + block.source.filename + '.\n' )
556
557 if header:
558 print header_location_header
559 print 'Defined in ' + header + '.'
560 print header_location_footer
561
562 print source_header
563 for l in block.code:
564 print self.html_source_quote( l, block.name )
565 print source_footer
566
567 def markup_enter( self, markup, block ):
568 if markup.tag == "description":
569 print description_header
570 else:
571 print marker_header + markup.tag + marker_inter
572
573 self.print_html_markup( markup )
574
575 def markup_exit( self, markup, block ):
576 if markup.tag == "description":
577 print description_footer
578 else:
579 print marker_footer
580
581 def block_exit( self, block ):
582 print block_footer_start + self.file_prefix + "index.html" + \
583 block_footer_middle + self.file_prefix + "toc.html" + \
584 block_footer_end
585
586 def section_exit( self, section ):
587 print html_footer
588
589 def section_dump_all( self ):
590 for section in self.sections:
591 self.section_dump( section, self.file_prefix + section.name + '.html' )
592
593 # eof