roff.pm 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  1. # -*-perl-*-
  2. #+##############################################################################
  3. #
  4. # roff.pm: convert to roff
  5. #
  6. # So much out of date that it may be considered unuseful.
  7. #
  8. # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
  9. #
  10. # This program is free software; you can redistribute it and/or modify
  11. # it under the terms of the GNU General Public License as published by
  12. # the Free Software Foundation; either version 3 of the License,
  13. # or (at your option) any later version.
  14. #
  15. # This program is distributed in the hope that it will be useful,
  16. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. # GNU General Public License for more details.
  19. #
  20. # You should have received a copy of the GNU General Public License
  21. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. #
  23. # Originally written by Patrice Dumas.
  24. #
  25. #-##############################################################################
  26. # FIXME obsolete
  27. main::load_init_file('', 'noheaders.pm');
  28. set_default('SPLIT', 0);
  29. @EXPAND = ('info');
  30. set_default('USE_ISO', 0);
  31. $SMALL_RULE = '';
  32. $DEFAULT_RULE = '';
  33. $MIDDLE_RULE = '';
  34. $BIG_RULE = '';
  35. set_default('NODE_FILE_EXTENSION', 'roff');
  36. set_default('EXTENSION', 'roff');
  37. $MENU_SYMBOL = '*';
  38. set_default('AVOID_MENU_REDUNDANCY', 0);
  39. $print_Top = \&T2H_ROFF_print_Top;
  40. $print_misc = \&T2H_ROFF_print_misc;
  41. $print_page_head = \&T2H_ROFF_print_page_head;
  42. $print_page_foot = \&T2H_ROFF_print_page_foot;
  43. $toc_body = \&T2H_ROFF_toc_body;
  44. $titlepage = \&T2H_ROFF_titlepage;
  45. sub T2H_ROFF_print_page_head
  46. {
  47. my $fh = shift;
  48. print $fh <<EOT;
  49. .nr _- 0
  50. .tr \\(is'
  51. .tr \\(if`
  52. .tr \\(pd"
  53. $AFTER_BODY_OPEN
  54. EOT
  55. my $today = get_conf('today');
  56. print $fh $Texi2HTML::THISDOC{'copying_comment'} . "\n";
  57. print $fh "" . &$comment("Created by $Texi2HTML::THISDOC{'program_version'}, $Texi2HTML::THISDOC{'program_homepage'}\n");
  58. # FIXME this should instead be done in print_title
  59. print $fh ".ds St " . protect_spaces($Texi2HTML::THISDOC{'title'}) . "\n";
  60. print $fh '.oh \'\\\\*(St\'\'%\'' ."\n".'.eh \'%\'\'\\\\*(St\'' . "\n";
  61. }
  62. sub T2H_ROFF_print_page_foot
  63. {
  64. my $fh = shift;
  65. my $program_string = program_string();
  66. print $fh <<EOT;
  67. .br
  68. .pp
  69. $program_string
  70. EOT
  71. }
  72. sub T2H_ROFF_print_Top($$)
  73. {
  74. my $fh = shift;
  75. my $has_top_heading = shift;
  76. my $buttons = \@MISC_BUTTONS;
  77. &$print_head_navigation($fh, $buttons);
  78. # FIXME this is done in print_title now.
  79. # redo the titlepage with the actual state
  80. my ($titlepage_text, $titlepage_no_texi, $titlepage_simple_text) = main::do_special_region_lines('titlepage',$Texi2HTML::THISDOC{'state'});
  81. &$titlepage([],$titlepage_text, $titlepage_no_texi, $titlepage_simple_text);
  82. print $fh $Texi2HTML::TITLEPAGE;
  83. main::print_lines($fh, $Texi2HTML::THIS_SECTION);
  84. }
  85. # FIXME: use the vanilla print_misc instead, and add a
  86. # $heading_text
  87. sub T2H_ROFF_print_misc
  88. {
  89. my $fh = shift;
  90. &$print_misc_header($fh);
  91. main::print_lines($fh);
  92. &$print_misc_footer($fh);
  93. }
  94. # FIXME obsolete, main one is right now, need to do a heading_text
  95. sub T2H_ROFF_titlepage ($$$$)
  96. {
  97. my $titlepage_lines = shift;
  98. my $titlepage_text = shift;
  99. my $titlepage_no_texi = shift;
  100. my $titlepage_simple_text = shift;
  101. my $result = '';
  102. if (@{$Texi2HTML::THISDOC{'titles'}}
  103. or @{$Texi2HTML::THISDOC{'subtitles'}}
  104. or @{$Texi2HTML::THISDOC{'authors'}})
  105. {
  106. # FIXME obsolete, use $line_command instead
  107. foreach my $title (@{$Texi2HTML::THISDOC{'titles'}})
  108. {
  109. $result .= ".sz +10\n.ce\n" . protect_spaces($title) . "\n.sz -10\n";
  110. }
  111. foreach my $subtitle (@{$Texi2HTML::THISDOC{'subtitles'}})
  112. {
  113. $result .= ".sz +4\n.ce\n" . protect_spaces($subtitle) . "\n.sz -4\n";
  114. }
  115. $result .= ".sp 4\n" if ($result ne '');
  116. foreach my $author (@{$Texi2HTML::THISDOC{'authors'}})
  117. {
  118. $result .= protect_spaces($author) . "\n.br\n";
  119. }
  120. $result .= ".sp 2\n" if (@{$Texi2HTML::THISDOC{'authors'}});
  121. }
  122. if (($result ne '') or ($Texi2HTML::TITLEPAGE ne ''))
  123. {
  124. $Texi2HTML::TITLEPAGE = ".tp\n" . $result . $titlepage_text . ".++ C\n";
  125. }
  126. }
  127. ########################################################################
  128. # Control of formatting:
  129. # 1.) For some changes, it is often enough to change the value of
  130. # some global map. It might necessitate building a little
  131. # function along with the change in hash, if the change is the use
  132. # of another function (in style_map).
  133. # 2.) For other changes, reimplement one of the t2h_default_<fnc>* routines,
  134. # give them another name, and assign them to the respective
  135. # $<fnc> variable (below).
  136. #
  137. # This hash should have keys corresponding with the nonletter command accent
  138. # whose following character is considered to be the argument
  139. # This hash associates an accent macro to the ISO name for the accent if any.
  140. # The customary use of this map is to find the ISO name appearing in html
  141. # entity (like &eacute;) associated with a texinfo accent macro.
  142. #
  143. # The keys of the hash are
  144. # ": umlaut
  145. # ~: tilda accent
  146. # ^: circumflex accent
  147. # `: grave accent
  148. # ': acute accent
  149. # =: macron accent
  150. %accent_map = (
  151. '"', ':',
  152. '~', '~',
  153. '^', '^',
  154. '`', '`',
  155. ',', ',',
  156. "'", "'",
  157. '=', '',
  158. );
  159. #
  160. # texinfo "simple things" (@foo) to HTML ones
  161. #
  162. %simple_map = (
  163. # "*", "\n.br\n",
  164. ' ', '\ ',
  165. "\t", "\\\t",
  166. "\n", "\\\n",
  167. # "&#173;" or "&shy;" could also be possible for @-, but it seems
  168. # that some browser will consider this as an always visible hyphen mark
  169. # which is not what we want (see http://www.cs.tut.fi/~jkorpela/shy.html)
  170. '-', '', # hyphenation hint
  171. '|', '', # used in formatting commands @evenfooting and friends
  172. '/', '',
  173. # spacing commands
  174. ':', '',
  175. '!', '!',
  176. '?', '?',
  177. '.', '\&.',
  178. '@', '@',
  179. '}', '}',
  180. '{', '{',
  181. );
  182. # this map is used in preformatted text
  183. %simple_map_pre = %simple_map;
  184. #
  185. # texinfo "things" (@foo{}) to HTML ones
  186. #
  187. %things_map = (
  188. 'TeX' => 'TeX',
  189. 'LaTeX' => 'LaTeX',
  190. 'bullet' => '\(bu',
  191. 'copyright' => '\(co',
  192. 'registeredsymbol' => '\(rg',
  193. 'dots' => '\&...',
  194. 'enddots' => '\&...',
  195. 'equiv' => '\(==',
  196. # i18n
  197. 'error' => 'error->',
  198. 'expansion' => '\(->',
  199. 'minus' => '\-',
  200. 'point' => '*',
  201. 'print' => '-|',
  202. 'result' => '\(rh',
  203. # set in code using the language
  204. # 'today', &pretty_date,
  205. 'aa' => '\(oa',
  206. 'AA' => '\(oA',
  207. 'ae' => '\(ae',
  208. 'oe' => '\(oe',
  209. 'AE' => '\(AE',
  210. 'OE' => '\(OE',
  211. 'o' => '\(/o',
  212. 'O' => '\(/O',
  213. 'ss' => '\(ss',
  214. 'l' => '\(/l',
  215. 'L' => '\(/L',
  216. 'exclamdown' => '\(r!',
  217. 'questiondown' => '\(r?',
  218. 'pounds' => '\(Po',
  219. 'ordm' => '\(Om',
  220. 'ordf' => '\(Of',
  221. 'euro' => '\(eu',
  222. );
  223. # This map is used in preformatted environments
  224. %pre_map = %things_map;
  225. #%style_map = (
  226. # 'acronym', '',
  227. # 'asis', '',
  228. # 'b', ['\fB', '\fR'],
  229. # 'cite', ['\fI', '\fR'],
  230. # 'code', ['\fR\&\f(CW', '\fR'],
  231. # 'command', ['\fR\&\f(CW', '\fR'],
  232. # 'ctrl', ['\fR\&\f(CW', '\fR'],
  233. # 'dfn', ['\fI', '\fR'],
  234. # 'dmn', '',
  235. # 'email', ['\fB', '\fR'],
  236. # 'emph', ['\fI', '\fR'],
  237. # 'env', ['\fR\&\f(CW', '\fR'],
  238. # 'file', ['\fR\&\f(CW', '\fR', '"'],
  239. # 'i', ['\fI', '\fR'],
  240. # 'kbd', ['\fR\&\f(CW', '\fR'],
  241. # 'key', ['\fR\&\f(CW', '\fR'],
  242. # 'math', ['\fR\&\f(CW', '\fR'],
  243. # 'option', ['\fR\&\f(CW', '\fR', '"'],
  244. # 'r', ['\fR', ''],
  245. # 'samp', ['\fR\&\f(CW', '\fR', '"'],
  246. # 'sc', '&roff_sc',
  247. # 'strong', ['\fB', '\fR'],
  248. # 't', ['\fR\&\f(CW', '\fR'],
  249. # 'uref', '&default_uref',
  250. # 'url', '&default_url',
  251. # 'var', ['\fI', '\fR'],
  252. # 'verb', ['\fR\&\f(CW', '\fR'],
  253. # 'titlefont', ["\n.sz +10\n.ce\n", "\n.sz -10\n"],
  254. # 'w', '',
  255. # 'H', '&roff_accent',
  256. # 'dotaccent', '&roff_accent',
  257. # 'ringaccent', '&roff_accent',
  258. # 'tieaccent', '&roff_accent',
  259. # 'u', '&roff_accent',
  260. # 'ubaraccent', '&roff_accent',
  261. # 'udotaccent', '&roff_accent',
  262. # 'v', '&roff_accent',
  263. # ',', '&roff_accent',
  264. # 'dotless', ''
  265. # );
  266. my @bold_commands = ('strong', 'b', 'email');
  267. my @italic_commands = ('cite', 'dfn', 'emph', 'i', 'var', 'slanted');
  268. my @fixed_command = ('code', 'command', 'ctrl', 'env', 'file', 'kbd', 'key',
  269. 'math', 'option', 'samp', 't', 'verb');
  270. foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents), keys(%accent_map))
  271. {
  272. #$style_map{$accent_command} = { 'function' => \&t2h_roff_accent };
  273. $style_map{$accent_command} = '&roff_accent';
  274. }
  275. #foreach my $accent (keys(%accent_map))
  276. #{
  277. # $style_map{$accent} = '&roff_accent';
  278. #}
  279. foreach my $command (keys(%style_map))
  280. {
  281. delete $style_map{$command}->{'attribute'} if (exists($style_map{$command}->{'attribute'}));
  282. if (grep {$_ eq $command} @bold_commands)
  283. {
  284. delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
  285. $style_map{$command}->{'begin'} = '\fB';
  286. $style_map{$command}->{'end'} = '\fR';
  287. next;
  288. }
  289. elsif (grep {$_ eq $command} @italic_commands)
  290. {
  291. delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
  292. $style_map{$command}->{'begin'} = '\fI';
  293. $style_map{$command}->{'end'} = '\fR';
  294. next;
  295. }
  296. elsif (grep {$_ eq $command} @fixed_commands)
  297. {
  298. delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
  299. $style_map{$command}->{'begin'} = '\fR\&\f(CW';
  300. $style_map{$command}->{'end'} = '\fR';
  301. next;
  302. }
  303. }
  304. delete $style_map{'titlefont'}->{'function'} if (exists($style_map{'titlefont'}->{'function'}));
  305. $style_map{'titlefont'}->{'begin'} = "\n.sz +10\n.ce\n";
  306. $style_map{'titlefont'}->{'end'} = "\n.sz -10\n";
  307. delete $style_map{'r'}->{'function'} if (exists($style_map{'r'}->{'function'}));
  308. $style_map{'r'}->{'begin'} = '\r';
  309. #$style_map{'r'}->{'end'} = '';
  310. $style_map{'sc'} = '&roff_sc';
  311. $style_map{'indicateurl'}->{'begin'} = '<';
  312. $style_map{'indicateurl'}->{'end'} = '>';
  313. foreach my $command (keys(%style_map))
  314. {
  315. if (ref($style_map{$command}) ne 'HASH')
  316. {
  317. $style_map_pre{$command} = $style_map{$command};
  318. next;
  319. }
  320. $style_map_pre{$command} = {};
  321. foreach my $key (keys(%{$style_map{$command}}))
  322. {
  323. $style_map_pre{$command}->{$key} = $style_map{$command}->{$key};
  324. }
  325. }
  326. %special_accents = (
  327. 'ringaccent' => 'aA',
  328. "'" => 'aeiouyAEIOUY',
  329. ',' => 'cC',
  330. '^' => 'aeiouAEIOU',
  331. '`' => 'aeiouAEIOU',
  332. '~' => 'nNaoAO',
  333. '"' => 'aeiouyAEIOUY',
  334. 'v' => 'sSzZ',
  335. );
  336. sub roff_accent($$)
  337. {
  338. my $text = shift;
  339. my $accent = shift;
  340. return $text if ($accent eq 'dotless');
  341. return "\\($accent_map{$accent}${text}" if (defined($accent_map{$accent}) and defined($special_accents{$accent}) and ($text =~ /^[$special_accents{$accent}]$/));
  342. return "\\(o${text}" if (($accent eq 'ringaccent') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
  343. return "\\(v${text}" if (($accent eq 'v') and (defined($special_accents{$accent})) and ($text =~ /^[$special_accents{$accent}]$/));
  344. #FIXME maybe we should protect the symbols such that they look like strings and
  345. # not ponctuation marks ? Like it is done in texi2roff ?
  346. return $text . '\\&.' if ($accent eq 'dotaccent');
  347. return '\\&.' . $text if ($accent eq 'udotaccent');
  348. return ascii_accents($text, $accent);
  349. }
  350. sub roff_sc($$)
  351. {
  352. return "\n.sz -6\n" . uc($_[0]) . "\n.sz +6\n" ;
  353. }
  354. sub roff_ctrl($$)
  355. {
  356. return "\\*^$_[0]";
  357. }
  358. $format = \&T2H_ROFF_format;
  359. sub T2H_ROFF_format($$$)
  360. {
  361. my $tag = shift;
  362. my $element = shift;
  363. my $text = shift;
  364. return '' if (!defined($element) or ($text !~ /\S/));
  365. return $element->[0] . $text . $element->[1];
  366. }
  367. %format_map = (
  368. 'quotation' => [ ".(q\n", ".)q\n" ],
  369. 'smallquotation' => [ ".(q\n", ".)q\n" ],
  370. # lists
  371. 'itemize' => [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
  372. 'enumerate' => [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
  373. 'multitable' => [ ".(l M\n.nh\n", ".hy\n.)l\n" ],
  374. 'table' => [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
  375. 'vtable' => [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
  376. 'ftable' => [ ".(l L F\n.ba +5\n", ".ba -5\n.)l\n" ],
  377. );
  378. %special_list_commands = (
  379. 'table' => {},
  380. 'vtable' => {},
  381. 'ftable' => {},
  382. 'itemize' => {}
  383. );
  384. $complex_format_map =
  385. (
  386. 'example' =>
  387. {
  388. 'begin' => "",
  389. 'end' => "",
  390. 'begin_region' => ".(l I\n\\&\\fR\\f(CW",
  391. 'end_region' => "\\&\\fR\n.)l\n"
  392. },
  393. 'smallexample' =>
  394. {
  395. 'begin' => "",
  396. 'end' => "",
  397. 'begin_region' => ".(l I\n.size -2\n\\&\\fR\\f(CW",
  398. 'end_region' => "\\&\\fR\n.size +2\n.)l\n"
  399. },
  400. 'display' =>
  401. {
  402. 'begin' => "",
  403. 'end' => "",
  404. 'begin_region' => ".(l I\n\\&\\fR\\f(CW",
  405. 'end_region' => "\\&\\fR\n.)l\n"
  406. },
  407. 'smalldisplay' =>
  408. {
  409. 'begin' => "",
  410. 'end' => "",
  411. 'begin_region' => ".(l I\n.size -2\n\\&\\fR\\f(CW",
  412. 'end_region' => "\\&\\fR\n.size +2\n.)l\n"
  413. },
  414. 'menu-comment' =>
  415. {
  416. 'begin' => "",
  417. 'end' => "",
  418. 'begin_region' => "",
  419. 'end_region' => "\n"
  420. },
  421. 'menu-preformatted' =>
  422. {
  423. 'begin' => "",
  424. 'end' => "",
  425. 'begin_region' => "",
  426. 'end_region' => "\n"
  427. }
  428. );
  429. # format shouldn't narrow the margins
  430. $complex_format_map{'lisp'} = $complex_format_map{'example'};
  431. $complex_format_map{'smalllisp'} = $complex_format_map{'smallexample'};
  432. $complex_format_map{'format'} = $complex_format_map{'display'};
  433. $complex_format_map{'smallformat'} = $complex_format_map{'smalldisplay'};
  434. sub protect_spaces($)
  435. {
  436. my $text = shift;
  437. my $result = '';
  438. while($text)
  439. {
  440. if ($text =~ s/^([^\\]*)\\//o)
  441. {
  442. my $leading = $1;
  443. if (defined($leading))
  444. {
  445. $leading =~ s/([\t ])/\\$1/go;
  446. $result .= $leading . '\\';
  447. }
  448. if (($text =~ s/^(\s)//o) or ($text =~ s/^(.)//o))
  449. {
  450. $result .= $1;
  451. }
  452. }
  453. else
  454. {
  455. $text =~ s/([\t ])/\\$1/go;
  456. $result .= $text;
  457. $text = '';
  458. }
  459. }
  460. return $result;
  461. }
  462. # formatting functions
  463. $anchor = \&t2h_roff_anchor;
  464. $def_item = \&t2h_roff_def_item;
  465. $def = \&t2h_roff_def;
  466. $menu = \&t2h_roff_menu;
  467. $menu_link = \&t2h_roff_menu_link;
  468. $menu_comment = \&t2h_roff_menu_comment;
  469. $menu_description = \&t2h_roff_menu_description;
  470. $simple_menu_link = \&t2h_roff_simple_menu_link;
  471. $table_item = \&t2h_roff_table_item;
  472. $table_line = \&t2h_roff_table_line;
  473. $row = \&t2h_roff_row;
  474. $cell = \&t2h_roff_cell;
  475. $list_item = \&t2h_roff_list_item;
  476. $comment = \&t2h_roff_comment;
  477. $def_line = \&t2h_roff_def_line;
  478. $raw = \&t2h_roff_raw;
  479. $heading = \&t2h_roff_heading;
  480. $paragraph = \&t2h_roff_paragraph;
  481. $preformatted = \&t2h_roff_preformatted;
  482. $foot_line_and_ref = \&t2h_roff_foot_line_and_ref;
  483. $foot_section = \&t2h_roff_foot_section;
  484. $image = \&t2h_roff_image;
  485. $index_entry_label = \&t2h_roff_index_entry_label;
  486. $index_summary = \&t2h_roff_index_summary;
  487. $print_index = \&t2h_roff_print_index;
  488. $protect_text = \&t2h_roff_protect_text;
  489. $cartouche = \&t2h_roff_cartouche;
  490. $sp = \&t2h_roff_sp;
  491. $normal_text = \&t2h_roff_normal_text;
  492. $empty_line = \&t2h_roff_empty_line;
  493. $unknown = \&t2h_roff_unknown;
  494. $float = \&t2h_roff_float;
  495. $listoffloats = \&t2h_roff_listoffloats;
  496. $listoffloats_entry = \&t2h_roff_listoffloats_entry;
  497. # This function is used to protect characters which are special in html
  498. # in inline text: &, ", <, and >.
  499. #
  500. # argument:
  501. # text to be protected
  502. sub t2h_roff_protect_text($)
  503. {
  504. my $text = shift;
  505. $text =~ s/\\/\\e/g;
  506. # $text =~ s/$;---$;/\\(em/g;
  507. # $text =~ s/$;--$;/-/g;
  508. # $text =~ s/$;-$;/\\-/g;
  509. $text =~ s/^\./\\&./;
  510. $text =~ s/([\s])\./$1\\&./g;
  511. return $text;
  512. }
  513. sub t2h_roff_normal_text($$$$$$$;$)
  514. {
  515. my $text = shift;
  516. my $in_raw_text = shift;
  517. my $in_preformatted = shift;
  518. my $in_code =shift;
  519. my $in_math = shift;
  520. my $in_simple = shift;
  521. my $style_stack = shift;
  522. my $state = shift;
  523. $text = &$protect_text($text) unless($in_raw_text);
  524. if (! $in_code and !$in_preformatted and !$in_raw_text)
  525. {
  526. $text =~ s/---/\\(em/g;
  527. $text =~ s/--/\\(en/g;
  528. $text =~ s/-/\\-/g;
  529. $text =~ s/``/\\(lq/g;
  530. $text =~ s/''/\\(rq/g;
  531. }
  532. #$text =~ s/---/\\(em/g;
  533. #$text =~ s/(--?-?)/$;$1$;/go;
  534. return $text;
  535. }
  536. sub t2h_roff_unknown($$$)
  537. {
  538. my $macro = shift;
  539. my $line = shift;
  540. my $pass = shift;
  541. if ($macro eq '*' and $pass == 2)
  542. {
  543. $line = '' if ($line =~ /^\s*$/);
  544. return ($line, 1, "\n.br\n", undef);
  545. }
  546. return ($line, 0, undef, undef);
  547. }
  548. # This function produces an anchor
  549. #
  550. # arguments:
  551. # $name : anchor name
  552. # $href : anchor href
  553. # text : text displayed
  554. # extra_attribs : added to anchor attributes list
  555. sub t2h_roff_anchor($;$$$)
  556. {
  557. my $name = shift;
  558. my $href = shift;
  559. my $text = shift;
  560. my $attributes = shift;
  561. $href = '' if (!defined($href) or ($href !~ /\S/));
  562. $text = '' if (!defined($text));
  563. return $text if ($text ne '');
  564. return "[$href]" if ($href ne '');
  565. return '';
  566. }
  567. # This function is used to format the text associated with a @deff/@end deff
  568. #
  569. # argument:
  570. # text
  571. sub t2h_roff_def_item($)
  572. {
  573. my $text = shift;
  574. if ($text =~ /\S/)
  575. {
  576. {
  577. #return ".ba +5\n.(l L F\n" . $text . ".)l\n.ba -5\n";
  578. return ".(l L F\n.ba +5\n" . $text . ".ba -5\n.)l\n";
  579. }
  580. }
  581. return '';
  582. }
  583. # format the container for the @deffn line and text
  584. #
  585. # argument
  586. # text of the whole @def, line and associated text.
  587. sub t2h_roff_def($)
  588. {
  589. my $text = shift;
  590. return $text;
  591. }
  592. # a whole menu
  593. #
  594. # argument:
  595. # the whole menu text (entries and menu comments)
  596. #
  597. # argument:
  598. # whole menu text.
  599. sub t2h_roff_menu($)
  600. {
  601. my $text = shift;
  602. chomp $text;
  603. return ".(l M\n\\&\\s8" . gdt('Menu:') . "\n" . $text . "\\&\\s0\n.)l\n";
  604. }
  605. # a simple menu entry ref in case we aren't in a standard menu context
  606. sub t2h_roff_simple_menu_link($$$$$$$)
  607. {
  608. my $entry = shift;
  609. my $preformatted = shift; # We assume this is true.
  610. my $href = shift;
  611. my $node = shift;
  612. my $title = shift;
  613. my $ending = shift;
  614. my $has_title = shift;
  615. $title = '' unless ($has_title);
  616. $title .= ':' if ($title ne '');
  617. return "$MENU_SYMBOL$title$node$ending";
  618. }
  619. # formats a menu entry link pointing to a node or section
  620. #
  621. # arguments:
  622. # the entry text
  623. # the state, a hash reference holding informations about the context, with a
  624. # usefull entry, 'preformatted', true if we are in a preformatted format
  625. # (a format keeping space between words). In that case a function
  626. # of the main program, main::do_preformatted($text, $state) might
  627. # be used to format the text with the current format style.
  628. # href is optionnal. It is the reference to the section or the node anchor
  629. # which should be used to make the link (typically it is the argument
  630. # of a href= attribute in a <a> element).
  631. sub t2h_roff_menu_link($$$$$$)
  632. {
  633. my $entry = shift;
  634. my $state = shift;
  635. my $href = shift;
  636. my $node = shift;
  637. my $title = shift;
  638. my $ending = shift;
  639. my $has_title = shift;
  640. $title = '' unless ($has_title);
  641. $title .= ':' if ($title ne '');
  642. return "$MENU_SYMBOL$title$node$ending";
  643. }
  644. # formats a menu entry description, ie the text appearing after the node
  645. # specification in a menu entry an spanning until there is another
  646. # menu entry, an empty line or some text at the very beginning of the line
  647. # (we consider that text at the beginning of the line begins a menu comment)
  648. #
  649. # arguments:
  650. # the description text
  651. # the state. See menu_entry.
  652. sub t2h_roff_menu_description($$)
  653. {
  654. my $text = shift;
  655. my $state = shift;
  656. return $text;
  657. }
  658. # a menu comment (between menu lines)
  659. # formats the container of a menu comment. A menu comment is any text
  660. # appearing between menu lines, either separated by an empty line from
  661. # the preceding menu entry, or a text beginning at the first character
  662. # of the line (text not at the very beginning of the line is considered to
  663. # be the continuation of a menu entry description text).
  664. #
  665. # The text itself is considered to be in a preformatted environment
  666. # with name 'menu-commment' and with style $MENU_PRE_STYLE.
  667. #
  668. # argument
  669. # text contained in the menu comment.
  670. sub t2h_roff_menu_comment($)
  671. {
  672. my $text = shift;
  673. return $text;
  674. }
  675. # text after @item in table, vtable and ftable
  676. sub t2h_roff_table_item($$$$$)
  677. {
  678. my $text = shift;
  679. my $index_label = shift;
  680. my $format = shift;
  681. my $command = shift;
  682. # my $formatted_command = shift;
  683. my $style_stack = shift;
  684. # my $text_formatted = shift;
  685. # my $text_formatted_leading_spaces = shift;
  686. # my $text_formatted_trailing_spaces = shift;
  687. my $item_cmd = shift;
  688. # if (defined($text_formatted))
  689. # {
  690. # $text = $text_formatted_leading_spaces . $text_formatted .$text_formatted_trailing_spaces;
  691. # }
  692. # $formatted_command = '' if (!defined($formatted_command) or
  693. # exists($special_list_commands{$format}->{$command}));
  694. $text = '.ip ' . $formatted_command . protect_spaces($text) . "\n";
  695. $text .= $index_label if (defined($index_label));
  696. return $text;
  697. }
  698. # format text on the line following @item (in table, vtable and ftable)
  699. sub t2h_roff_table_line($)
  700. {
  701. my $text = shift;
  702. return $text;
  703. }
  704. # row in multitable
  705. sub t2h_roff_row($)
  706. {
  707. my $text = shift;
  708. if ($text =~ /\S/)
  709. {
  710. return $text ."\n" ;
  711. }
  712. return '';
  713. }
  714. # cell in multitable
  715. sub t2h_roff_cell($)
  716. {
  717. my $text = shift;
  718. chomp $text;
  719. return protect_spaces($text) . "\\\t";
  720. }
  721. # format an item in a list
  722. #
  723. # argument:
  724. # text of the item
  725. sub t2h_roff_list_item($$$$$$$)
  726. {
  727. my $text = shift;
  728. my $format = shift;
  729. my $command = shift;
  730. my $formatted_command = shift;
  731. my $item_nr = shift;
  732. my $enumerate_style = shift;
  733. my $number = shift;
  734. $formatted_command = '' if (!defined($formatted_command) or
  735. exists($special_list_commands{$format}->{$command}));
  736. if ($text =~ /\S/)
  737. {
  738. #return $formatted_command . $text;
  739. return $text . "\n";
  740. }
  741. return '';
  742. }
  743. # an comment
  744. sub t2h_roff_comment($)
  745. {
  746. my $text = shift;
  747. my $result = '';
  748. while ($text)
  749. {
  750. $text =~ s/$;---$;/--/g;
  751. $text =~ s/$;--$;/-/g;
  752. $text =~ s/$;-$;/-/g;
  753. $text =~ s/^(.*)//;
  754. $result .= ".\\\"$1";
  755. $result .= "\n" if ($text =~ s/^\n//);
  756. }
  757. return $result;
  758. }
  759. # a paragraph
  760. sub t2h_roff_paragraph($$$$$$$$$$)
  761. {
  762. my $text = shift;
  763. my $align = shift;
  764. my $indent = shift;
  765. my $paragraph_command = shift;
  766. my $paragraph_command_formatted = shift;
  767. my $paragraph_number = shift;
  768. my $format = shift;
  769. my $item_nr = shift;
  770. my $enumerate_style = shift;
  771. my $number = shift;
  772. return '' if ($text =~ /^\s*$/);
  773. if (defined($paragraph_number) and defined($$paragraph_number))
  774. {
  775. $$paragraph_number++;
  776. $paragraph_command_formatted = undef if ($$paragraph_number > 1);
  777. }
  778. # $paragraph_command_formatted = '' if (!defined($paragraph_command_formatted) or
  779. # exists($special_list_commands{$format}->{$paragraph_command}));
  780. #return $text if (defined($format) and $format eq 'multitable');
  781. return $text if (defined($format) and (($format eq 'multitable') or ($format eq 'quotation') or ($format eq 'smallquotation')));
  782. my $open = ".pp\n";
  783. if (defined($format) and (($format eq 'itemize') or ($format eq 'enumerate')) and
  784. defined($paragraph_number) and defined($$paragraph_number) and ($$paragraph_number == 1))
  785. {
  786. $open = ".lp\n";
  787. }
  788. my $close = '';
  789. if ($align)
  790. {
  791. if ($align eq 'flushleft')
  792. {
  793. $open .= ".ad l\n";
  794. $close .= ".ad b\n";
  795. }
  796. elsif ($align eq 'flushright')
  797. {
  798. $open .= ".ad r\n";
  799. $close .= ".ad b\n";
  800. }
  801. elsif ($align eq 'center')
  802. {
  803. $open .= ".ce\n";
  804. }
  805. }
  806. if (defined($format) and ($format eq 'enumerate') and
  807. defined($paragraph_number) and defined($$paragraph_number) and ($$paragraph_number == 1) and defined($number) and ($number ne ''))
  808. {
  809. $open .= "$number.";
  810. }
  811. chomp ($text);
  812. #return $open. $paragraph_command_formatted . $text . "\n" . $close;
  813. return $open. $text . "\n" . $close;
  814. }
  815. # a preformatted region
  816. sub t2h_roff_preformatted($$$$$$$$$$)
  817. {
  818. my $text = shift;
  819. my $pre_style = shift;
  820. my $class = shift;
  821. my $leading_command = shift;
  822. my $leading_command_formatted = shift;
  823. my $preformatted_number = shift;
  824. my $format = shift;
  825. my $item_nr = shift;
  826. my $enumerate_style = shift;
  827. my $number = shift;
  828. $leading_command_formatted = '' if (!defined($leading_command_formatted) or
  829. exists($special_list_commands{$format}->{$leading_command}));
  830. if (defined($format) and $format eq 'multitable')
  831. {
  832. my $chomped = chomp($text);
  833. my $result = '\&\fR\f(CW' . $text . '\&\fR';
  834. $result .= "\n" if ($chomped);
  835. return $result;
  836. }
  837. return '' if ($text eq '');
  838. if (defined($preformatted_number) and defined($$preformatted_number))
  839. {
  840. $$preformatted_number++;
  841. $leading_command_formatted = undef if ($$preformatted_number > 1);
  842. }
  843. $leading_command_formatted = '' if (!defined($leading_command_formatted));
  844. chomp $text;
  845. my $open = '';
  846. if (defined($format) and ($format eq 'enumerate') and
  847. defined($paragraph_number) and defined($$paragraph_number) and ($$paragraph_number == 1) and defined($number) and ($number ne ''))
  848. {
  849. $open = "$number. ";
  850. }
  851. return $complex_format_map{$class}->{'begin_region'} . $leading_command_formatted . $open . $text . $complex_format_map{$class}->{'end_region'};
  852. }
  853. # This function formats a heading for an element
  854. #
  855. # argument:
  856. # an element. It is a hash reference for a node or a sectioning command.
  857. # The interesting keys are:
  858. # 'text': the heading text
  859. # 'name': the heading text without section number
  860. # 'node': true if it is a node
  861. # 'level': level of the element. 0 for @top, 1 for chapter, heading,
  862. # appendix..., 2 for section and so on...
  863. # 'tag_level': the sectioning element name, raisesections and lowersections
  864. # taken into account
  865. sub t2h_roff_heading($$$$$;$$)
  866. {
  867. my $element = shift;
  868. my $command = shift;
  869. my $texi_line = shift;
  870. my $line = shift;
  871. my $in_preformatted = shift;
  872. my $one_section = shift;
  873. my $element_heading = shift;
  874. my $name = $element->{'text'};
  875. if (!$element->{'node'})
  876. {
  877. $name = $element->{'name'};
  878. }
  879. return '' if ($element->{'name'} !~ /\S/);
  880. my $class = $element->{'tag_level'};
  881. $class = 'unnumbered' if ($class eq 'top');
  882. $level = $element->{'level'};
  883. $level = 3 if (!defined($level));
  884. $level = 1 if ($level == 0);
  885. my $heading = '';
  886. $heading = ".bp\n" if ($level == 1);
  887. $heading .= '.if !\n(_- \{\\' . "\n.nr _- 1\n.nr \$1 0 1\n" . '.af $1 A\}' . "\n"
  888. if ($class =~ /^appendix/);
  889. $name = protect_spaces($name);
  890. my $toc_entry = '\&';
  891. if ($class =~ /^unnumbered/ or ($class eq 'node'))
  892. {
  893. $heading .= ".uh $name\n";
  894. $toc_entry .= ' ';
  895. }
  896. elsif (($class =~ /section$/) or ($class eq 'chapter') or ($class =~ /^appendix/))
  897. {
  898. $heading .= ".sh $level $name\n";
  899. my $number = 1;
  900. while ($number < $level)
  901. {
  902. $toc_entry .= "\\n(\$$number.";
  903. $number++;
  904. }
  905. $toc_entry .= "\\n(\$$number ";
  906. }
  907. $toc_entry .= $name;
  908. return $heading . "\n" if ($class eq 'node');
  909. return $heading . ".(x\n" . $toc_entry . "\n.)x\n\\&\\fR\n";
  910. }
  911. sub T2H_ROFF_toc_body($$$)
  912. {
  913. my $elements_list = shift;
  914. my $do_contents = shift;
  915. my $do_scontents = shift;
  916. if ($do_contents or $do_scontents)
  917. {
  918. my $lines = ".pp\n.nr % 0 1\n.af % i\n.bp \\n%+1\n.ce\n\\&\\fB" . gdt('Table of Contents') . "\\fR\n.sp 2\n.xp\n";
  919. if (!$do_contents)
  920. {
  921. push @{$Texi2HTML::OVERVIEW}, $lines;
  922. }
  923. else
  924. {
  925. push @{$Texi2HTML::TOC_LINES}, $lines;
  926. }
  927. }
  928. }
  929. # formatting of raw regions
  930. # ih L2H is true another mechanism is used for tex
  931. sub t2h_roff_raw($$)
  932. {
  933. my $style = shift;
  934. my $text = shift;
  935. my $expanded = 1 if (grep {$style eq $_} @EXPAND);
  936. if ($style eq 'verbatim' or $style eq 'verbatiminclude' or ($expanded and ($style eq 'tex' or $style eq 'html')))
  937. {
  938. chomp ($text);
  939. return ".(l M\n\\fR\\&\\f(CW" . &$protect_text($text) . "\\fR\n.)l\n" ;
  940. }
  941. elsif ($expanded)
  942. {
  943. main::msg_debug ("(bug) unknown style $style");
  944. return &$protect_text($text);
  945. }
  946. return '';
  947. }
  948. # This function formats a footnote reference and the footnote text associated
  949. # with a given footnote.
  950. # The footnote reference is the text appearing in the main document pointing
  951. # to the footnote text.
  952. #
  953. # arguments:
  954. # absolute number of the footnote (in the document)
  955. # relative number of the footnote (in the page)
  956. # identifier for the footnote
  957. # identifier for the footnote reference in the main document
  958. # main document file
  959. # footnote text file
  960. # array with the footnote text lines
  961. # the state. See menu entry.
  962. #
  963. # returns:
  964. # reference on an array containing the footnote text lines which should
  965. # have been updated
  966. # the text for the reference pointing on the footnote text
  967. sub t2h_roff_foot_line_and_ref($$$$$$$)
  968. {
  969. my $number_in_doc = shift;
  970. my $number_in_page = shift;
  971. my $footnote_id = shift;
  972. my $place_id = shift;
  973. my $document_file = shift;
  974. my $footnote_file = shift;
  975. my $lines = shift;
  976. my $state = shift;
  977. my $text = '';
  978. my $line;
  979. while (@$lines)
  980. {
  981. $line = shift @$lines;
  982. $text .= $line;
  983. }
  984. chomp $text;
  985. return ([], "\n.(f\n" . $text . "\n.)f\n" );
  986. }
  987. # formats a group of footnotes.
  988. #
  989. # argument:
  990. # array reference on the footnotes texts lines
  991. #
  992. # returns an array reference on the group of footnotes lines
  993. sub t2h_roff_foot_section($)
  994. {
  995. my $lines = shift;
  996. @$lines = ();
  997. }
  998. # format an image
  999. #
  1000. # arguments:
  1001. # image file name
  1002. # image basename
  1003. # a boolean true if we are in a preformatted format
  1004. sub t2h_roff_image($$$$)
  1005. {
  1006. my $file = shift;
  1007. my $base = shift;
  1008. my $preformatted = shift;
  1009. my $file_name = shift;
  1010. return "[$base src=$file_name]" if ($base ne $file_name);
  1011. return "[$base]";
  1012. }
  1013. # format a target in the main document for an index entry.
  1014. #
  1015. # arguments:
  1016. # target identifier
  1017. # boolean true if in preformatted format
  1018. sub t2h_roff_index_entry_label($$$$$$$$$)
  1019. {
  1020. my $identifier = shift;
  1021. my $preformatted = shift;
  1022. my $entry = shift;
  1023. my $index_name = shift;
  1024. my $index_command = shift;
  1025. my $texi_entry = shift;
  1026. my $formatted_entry = shift;
  1027. my $in_region_not_in_output = shift;
  1028. my $index_entry_ref = shift;
  1029. return ".(x $index_name\n" . protect_spaces($entry) . "\n.)x\n";
  1030. }
  1031. # process definition commands line @deffn for example
  1032. sub t2h_roff_def_line($$$$$)
  1033. {
  1034. my $category = shift;
  1035. my $name = shift;
  1036. my $type = shift;
  1037. my $arguments = shift;
  1038. my $index_label = shift;
  1039. $index_label = '' if (!defined($index_label));
  1040. $name = '' if (!defined($name) or ($name =~ /^\s*$/));
  1041. $type = '' if (!defined($type) or $type =~ /^\s*$/);
  1042. if (!defined($arguments) or $arguments =~ /^\s*$/)
  1043. {
  1044. $arguments = '';
  1045. }
  1046. else
  1047. {
  1048. $arguments = '\fI' . protect_spaces($arguments) . '\fR';
  1049. }
  1050. my $type_name = ' ';
  1051. $type_name = " $type" if ($type ne '');
  1052. $type_name .= '\fB' . protect_spaces($name) . '\fR' if ($name ne '');
  1053. $type_name .= $arguments . "\n";
  1054. return '\fI' . protect_spaces($category) . ':\fR' . $type_name . $index_label;
  1055. }
  1056. # a cartouche
  1057. sub t2h_roff_cartouche($$)
  1058. {
  1059. my $text = shift;
  1060. return $text;
  1061. }
  1062. sub t2h_roff_sp($$)
  1063. {
  1064. my $number = shift;
  1065. my $preformatted = shift;
  1066. return "\n.sp $number\n";
  1067. }
  1068. # format a whole index
  1069. #
  1070. # argument:
  1071. # index text
  1072. # index name
  1073. sub t2h_roff_print_index($$)
  1074. {
  1075. my $text = shift;
  1076. my $name = shift;
  1077. return ".xp $name\n";
  1078. }
  1079. # format an index summary. This is a list of letters linking to the letter
  1080. # entries.
  1081. #
  1082. # arguments:
  1083. # array reference containing the formatted alphabetical letters
  1084. # array reference containing the formatted non lphabetical letters
  1085. sub t2h_roff_index_summary($$)
  1086. {
  1087. my $alpha = shift;
  1088. my $nonalpha = shift;
  1089. my $join = '';
  1090. my $nonalpha_text = '';
  1091. my $alpha_text = '';
  1092. return '';
  1093. }
  1094. # FIXME the following construct leads to something wrong ?
  1095. # something @c a comment
  1096. #
  1097. # other thing
  1098. sub t2h_roff_empty_line($)
  1099. {
  1100. my $text = shift;
  1101. return '';
  1102. }
  1103. sub t2h_roff_listoffloats_entry($$$$)
  1104. {
  1105. my $style_texi = shift;
  1106. my $float = shift;
  1107. my $float_style = shift;
  1108. my $caption = shift;
  1109. my $href = shift;
  1110. chomp ($caption);
  1111. return '.ip ' . protect_spaces($float_style) . "\n" . $caption . "\n";
  1112. }
  1113. sub t2h_roff_listoffloats($$$)
  1114. {
  1115. my $style_texi = shift;
  1116. my $style = shift;
  1117. my $float_entries = shift;
  1118. my $result = ".(l L F\n.ba +5\n";
  1119. foreach my $float_entry (@$float_entries)
  1120. {
  1121. $result .= $float_entry;
  1122. }
  1123. return $result . ".ba -5\n.)l\n";
  1124. }
  1125. sub t2h_roff_float($$$$$)
  1126. {
  1127. my $text = shift;
  1128. my $float = shift;
  1129. my $caption = shift;
  1130. my $shortcaption = shift;
  1131. my $caption_text = '';
  1132. if (defined($float->{'caption_texi'}))
  1133. {
  1134. $caption_text = $caption;
  1135. }
  1136. elsif (defined($float->{'shortcaption_texi'}))
  1137. {
  1138. $caption_text = $shortcaption;
  1139. }
  1140. elsif (defined($caption))
  1141. {
  1142. $caption_text = $caption;
  1143. }
  1144. chomp ($caption_text);
  1145. return ".(b L F\n" . $text . $caption_text . "\n.b)\n";
  1146. }
  1147. 1;