info.pm 139 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663
  1. # vim: set filetype=perl:
  2. #
  3. #+##############################################################################
  4. #
  5. # info.pm: convert to info
  6. #
  7. # Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
  8. #
  9. # This program is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation; either version 3 of the License,
  12. # or (at your option) any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License
  20. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. #
  22. #
  23. # Some error messages come from texinfo (makeinfo), so copyright holder
  24. # is the FSF or the individual who wrote them. All come from before the
  25. # switch of texinfo to GPLv3+.
  26. #
  27. #
  28. # Originally written by Patrice Dumas.
  29. #
  30. #-##############################################################################
  31. use Data::Dumper;
  32. use strict;
  33. $Data::Dumper::Maxdepth = 25;
  34. my %info_default_indented_commands;
  35. my %info_default_format;
  36. my %info_default_enable_encoding_accents;
  37. my @simple_quoted_commands;
  38. my @asis_commands;
  39. my @chevron_commands;
  40. my %info_default_accent_commands = ();
  41. my %info_default_leaf_command = ();
  42. my $info_default_end_sentence_character;
  43. my $info_default_after_punctuation_characters;
  44. my $info_default_indent_length;
  45. my %info_default_indent_format_length;
  46. my $info_default_index_length_to_node;
  47. my $info_default_listoffloat_caption_entry_length;
  48. my $info_default_listoffloat_append;
  49. my %info_default_index_entries_counts;
  50. sub info_default_load(;$)
  51. {
  52. my $from_command_line = shift;
  53. t2h_default_set_variables_default();
  54. set_default('USE_SECTIONS', 0);
  55. set_default('USE_NODES', 1);
  56. set_default('SPLIT', '');
  57. @T2H_FORMAT_EXPAND = ('info', 'direntry');
  58. set_default('EXTENSION', 'info');
  59. set_default('SHOW_MENU', 1);
  60. set_default('SHOW_TITLE', 0);
  61. set_default('USE_SETFILENAME_EXTENSION', 1);
  62. set_default('INLINE_INSERTCOPYING', 1);
  63. set_default('SIMPLE_MENU', 1);
  64. $MENU_SYMBOL = '*';
  65. set_default('ENABLE_ENCODING_USE_ENTITY', 0);
  66. set_default('ENABLE_ENCODING', 1);
  67. @IMAGE_EXTENSIONS = ('png', 'jpg', 'txt');
  68. $CAPTION_STYLE = 'asis';
  69. set_default('DEFAULT_ENCODING', 'ascii');
  70. set_default('HEADERS', 1);
  71. set_default('INLINE_CONTENTS', 0);
  72. $no_paragraph_commands{'anchor'} = 1;
  73. %simple_map = %default_simple_map;
  74. %simple_map_pre = %simple_map;
  75. %simple_map_texi = %simple_map;
  76. %things_map = %default_things_map;
  77. %pre_map = %things_map;
  78. %line_command_map = (
  79. 'dircategory' => ''
  80. );
  81. # sc and var upcase.
  82. @simple_quoted_commands = ('cite', 'code', 'command', 'env', 'file', 'kbd',
  83. 'option', 'samp');
  84. @asis_commands = ('asis', 'w', 'b', 'ctrl', 'i', 'math', 'sc', 't', 'r',
  85. 'slanted', 'sansserif', 'var', 'titlefont', 'verb', 'clickstyle',
  86. 'headitemfont');
  87. @chevron_commands = ('key', 'indicateurl');
  88. %info_default_accent_commands = ();
  89. %info_default_leaf_command = ();
  90. %style_map = ();
  91. t2h_default_copy_style_map (\%default_style_map, \%style_map);
  92. foreach my $accent_command ('tieaccent', 'dotless', keys(%unicode_accents), keys(%accent_map))
  93. {
  94. $info_default_accent_commands{$accent_command} = 1;
  95. $style_map{$accent_command} = { 'function' => \&info_default_accent };
  96. }
  97. foreach my $command (keys(%style_map))
  98. {
  99. delete $style_map{$command}->{'quote'} if (exists($style_map{$command}->{'quote'}));
  100. if (grep {$_ eq $command} @simple_quoted_commands)
  101. {
  102. delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
  103. $style_map{$command}->{'begin'} = '`';
  104. $style_map{$command}->{'end'} = "'";
  105. next;
  106. }
  107. elsif (grep {$_ eq $command} @asis_commands)
  108. {
  109. delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
  110. delete $style_map{$command}->{'begin'} if (exists($style_map{$command}->{'begin'}));
  111. delete $style_map{$command}->{'end'} if (exists($style_map{$command}->{'end'}));
  112. }
  113. if (grep {$_ eq $command} @chevron_commands)
  114. {
  115. delete $style_map{$command}->{'function'} if (exists($style_map{$command}->{'function'}));
  116. $style_map{$command}->{'begin'} = '<';
  117. $style_map{$command}->{'end'} = '>';
  118. next;
  119. }
  120. $info_default_leaf_command{$command} = 1 if ($style_map{$command}->{'type'} and $style_map{$command}->{'type'} eq 'simple_style');
  121. }
  122. $style_map{'strong'}->{'begin'} = '*';
  123. $style_map{'strong'}->{'end'} = '*';
  124. $style_map{'dfn'}->{'begin'} = '"';
  125. $style_map{'dfn'}->{'end'} = '"';
  126. $style_map{'emph'}->{'begin'} = '_';
  127. $style_map{'emph'}->{'end'} = '_';
  128. foreach my $command (keys(%info_default_leaf_command))
  129. {
  130. if (defined ($style_map{$command}->{'args'}))
  131. {
  132. $style_map{$command}->{'orig_args'} = [ @{$style_map{$command}->{'args'}} ];
  133. }
  134. else
  135. {
  136. $style_map{$command}->{'orig_args'} = [ 'normal' ];
  137. }
  138. $style_map{$command}->{'args'} = [];
  139. foreach my $arg (@{$style_map{$command}->{'orig_args'}})
  140. {
  141. push @{$style_map{$command}->{'args'}}, 'keep';
  142. }
  143. }
  144. $style_map{'uref'}->{'function'} = \&info_default_uref;
  145. $style_map{'url'}->{'function'} = \&info_default_uref;
  146. $style_map{'email'}->{'function'} = \&info_default_email;
  147. %style_map_pre = ();
  148. %style_map_texi = ();
  149. t2h_default_copy_style_map (\%style_map, \%style_map_pre);
  150. t2h_default_copy_style_map (\%style_map, \%style_map_texi);
  151. $special_list_commands{'itemize'} = {};
  152. %info_default_indent_format_length = ('enumerate' => 2,
  153. 'itemize' => 3,
  154. 'table' => 0,
  155. 'vtable' => 0,
  156. 'ftable' => 0,
  157. );
  158. %format_map = ();
  159. foreach my $format ('group', 'raggedright', 'cartouche')
  160. {
  161. $format_map{$format} = '';
  162. }
  163. foreach my $menu_command('menu', 'detailmenu', 'direntry', 'menu_comment')
  164. {
  165. $complex_format_map{$menu_command} = {'begin' => '' , 'end' => ''};
  166. }
  167. foreach my $command (keys (%complex_format_map), keys(%info_default_indent_format_length), 'quotation', 'smallquotation', 'deff_item', 'deff_itemx')
  168. {
  169. $info_default_indented_commands{$command} = 1;
  170. }
  171. foreach my $command (keys(%info_default_indented_commands), 'multitable', 'float', 'flushright', 'flushleft', 'center')
  172. {
  173. $info_default_format{$command} = 1;
  174. }
  175. # it doesn't change anything for multitable
  176. foreach my $non_indented_command('format', 'smallformat', 'menu',
  177. 'detailmenu', 'direntry', 'multitable')
  178. {
  179. $info_default_indented_commands{$non_indented_command} = 0;
  180. }
  181. $info_default_end_sentence_character = quotemeta($punctuation_characters);
  182. $info_default_after_punctuation_characters = quotemeta($after_punctuation_characters);
  183. $info_default_indent_length = 5;
  184. $info_default_index_length_to_node = 41;
  185. $info_default_listoffloat_caption_entry_length = 41;
  186. $info_default_listoffloat_append = '...';
  187. t2h_default_push_handler(\&info_default_init_accent_enable_encoding, \@command_handler_init);
  188. t2h_default_push_handler(\&info_default_init_variables, \@command_handler_init);
  189. $style = \&info_default_style;
  190. $print_page_head = \&info_default_print_page_head;
  191. $contents = \&info_default_noop;
  192. $shortcontents = \&info_default_noop;
  193. $about_body = \&info_default_noop;
  194. $print_Footnotes = \&info_default_noop;
  195. $copying_comment = \&info_default_copying_comment;
  196. $element_heading = \&info_default_element_heading;
  197. $heading = \&info_default_heading;
  198. $normal_text = \&info_default_normal_text;
  199. $paragraph = \&info_default_paragraph;
  200. $preformatted = \&info_default_preformatted;
  201. $empty_preformatted = \&info_default_preformatted;
  202. $empty_line = \&info_default_empty_line;
  203. # maybe should not be called from the main program?
  204. $print_page_foot = \&info_default_print_page_foot;
  205. $print_Top_footer = \&info_default_print_Top_footer;
  206. $print_Top = \&info_default_print_section;
  207. $print_section = \&info_default_print_section;
  208. $end_section = \&info_default_end_section;
  209. $one_section = \&info_default_one_section;
  210. $begin_format_texi = \&info_default_begin_format_texi;
  211. $begin_style_texi = \&info_default_begin_style_texi;
  212. $begin_paragraph_texi = \&info_default_begin_paragraph_texi;
  213. $simple_command = \&info_default_simple_command;
  214. $thing_command = \&info_default_thing_command;
  215. $begin_special_region = \&info_default_begin_special_region;
  216. $end_special_region = \&info_default_end_special_region;
  217. $anchor_label = \&info_default_anchor_label;
  218. $element_label = \&info_default_noop;
  219. $menu_link = \&info_default_menu_link;
  220. #$menu_command = \&info_default_menu_command;
  221. $complex_format = \&info_default_complex_format;
  222. $quotation = \&info_default_quotation;
  223. $misc_command_line = \&info_default_misc_commands;
  224. $external_ref = \&info_default_external_ref;
  225. $internal_ref = \&info_default_internal_ref;
  226. $image = \&info_default_image;
  227. $image_files = \&info_default_image_files;
  228. $index_summary = \&info_default_index_summary;
  229. $summary_letter = \&info_default_summary_letter;
  230. $index_entry = \&info_default_index_entry;
  231. $index_entry_command = \&t2h_default_index_entry_command;
  232. $index_letter = \&info_default_index_letter;
  233. $printindex = \&info_default_printindex;
  234. $print_index = \&info_default_print_index;
  235. $index_entry_label = \&info_default_index_entry_label;
  236. $foot_section = \&info_default_foot_lines;
  237. $foot_line_and_ref = \&info_default_foot_line_and_ref;
  238. $footnote_texi = \&info_default_footnote_texi;
  239. $list_item = \&info_default_list_item;
  240. $format_list_item_texi = \&info_default_format_list_item_texi;
  241. $format = \&info_default_format;
  242. $tab_item_texi = \&info_default_tab_item_texi;
  243. $acronym_like = \&info_default_acronym_like;
  244. $sp = \&info_default_sp;
  245. $paragraph_style_command = \&info_default_paragraph_style_command;
  246. $cell = \&info_default_cell;
  247. $row = \&info_default_row;
  248. $table_list = \&info_default_table_list;
  249. $def_item = \&info_default_def_item;
  250. $def = \&info_default_def;
  251. $def_line = \&info_default_def_line;
  252. $float = \&info_default_float;
  253. $listoffloats_entry = \&info_default_listoffloats_entry;
  254. $listoffloats = \&info_default_listoffloats;
  255. $colon_command = \&info_default_colon_command;
  256. $raw = \&info_default_raw;
  257. $line_command = \&info_default_line_command;
  258. $comment = \&t2h_default_comment;
  259. $unknown_style = \&info_default_unknown_style;
  260. $heading_text = \&t2h_default_heading_text;
  261. }
  262. my %info_default_state_map = ();
  263. my $info_default_out_file_nr = 1;
  264. my $info_default_dir_specification = '';
  265. my @info_default_pending_indirect = ();
  266. my @info_default_pending_footnotes = ();
  267. my $info_default_state_nr = 0;
  268. # maximal length of index entries line number information. Each entry is
  269. # an index name.
  270. my %info_default_index_line_string_length = ();
  271. my %info_default_index_entries = ();
  272. my $info_default_footnote_index = 0;
  273. my $info_default_current_node = undef;
  274. my %info_default_command_handler_expand;
  275. sub info_default_intercept_handler
  276. {
  277. my $command = $_[0];
  278. my $result = &{$info_default_command_handler_expand{$command}}(@_);
  279. return info_default_store_text (undef, $result, $command);
  280. }
  281. sub info_default_init_variables()
  282. {
  283. %info_default_state_map = ();
  284. $info_default_out_file_nr = 1;
  285. $info_default_dir_specification = '';
  286. @info_default_pending_indirect = ();
  287. @info_default_pending_footnotes = ();
  288. $info_default_state_nr = 0;
  289. %info_default_index_line_string_length = ();
  290. %info_default_index_entries = ();
  291. $info_default_footnote_index = 0;
  292. $info_default_current_node = undef;
  293. #$Texi2HTML::THISDOC{'SPLIT'} = 0 if ($OUTPUT_FORMAT eq 'info');
  294. #$FRAMES = 0 if ($OUTPUT_FORMAT eq 'info');
  295. foreach my $command (keys (%command_handler))
  296. {
  297. if ($command_handler{$command}->{'expand'})
  298. {
  299. $info_default_command_handler_expand{$command} = $command_handler{$command}->{'expand'};
  300. $command_handler{$command}->{'expand'} = \&info_default_intercept_handler;
  301. }
  302. }
  303. }
  304. # this is put in command_handler_init such that it sets things right
  305. # in case ENABLE_ENCODING is set and has lead to modification of the
  306. # accent functions
  307. sub info_default_init_accent_enable_encoding()
  308. {
  309. return unless (get_conf('ENABLE_ENCODING') and get_conf('USE_UNICODE'));
  310. foreach my $key (keys(%unicode_accents), 'dotless')
  311. {
  312. $info_default_enable_encoding_accents{$key} = 1;
  313. $t2h_enable_encoding_default_accent{'normal'}->{$key} = \&t2h_default_accent;
  314. $t2h_enable_encoding_default_accent{'texi'}->{$key} = \&t2h_default_accent;
  315. $t2h_enable_encoding_default_accent{'pre'}->{$key} = \&t2h_default_accent;
  316. $style_map{$key}->{'function'} = \&info_default_accent;
  317. $style_map_texi{$key}->{'function'} = \&info_default_accent;
  318. $style_map_pre{$key}->{'function'} = \&info_default_accent;
  319. }
  320. }
  321. sub info_default_uref($$)
  322. {
  323. shift;
  324. my $args = shift;
  325. my $url = shift @$args;
  326. my $text = shift @$args;
  327. my $replacement = shift @$args;
  328. $url = main::normalise_space($url);
  329. $replacement = '' if (!defined($replacement));
  330. $replacement = main::normalise_space($replacement);
  331. return $replacement if ($replacement ne '');
  332. $text = '' if (!defined($text));
  333. $text = main::normalise_space($text);
  334. return "`$url'" if ($text eq '');
  335. return "$text ($url)";
  336. }
  337. sub info_default_email($$)
  338. {
  339. my $command = shift;
  340. my $args = shift;
  341. my $mail = shift @$args;
  342. my $text = shift @$args;
  343. $mail = main::normalise_space($mail);
  344. $text = '' if (!defined($text));
  345. $text = main::normalise_space($text);
  346. $mail = "<$mail>";
  347. return $mail unless ($text ne '');
  348. return "$text $mail";
  349. }
  350. sub info_default_accent($$$)
  351. {
  352. my @args = @_;
  353. my $command = shift;
  354. my $args = shift;
  355. my $text = $args->[0];
  356. my $style_stack = shift;
  357. my $state = shift;
  358. my $result;
  359. if (get_conf('ENABLE_ENCODING') and $info_default_enable_encoding_accents{$command})
  360. {
  361. $result = &t2h_enable_encoding_normal_accent(@args);
  362. }
  363. else
  364. {
  365. $result = &t2h_default_accent(@args);
  366. }
  367. if (scalar(@$style_stack) and $info_default_accent_commands{$style_stack->[-1]})
  368. { # still more accents on the stack
  369. return $result;
  370. }
  371. return info_default_store_text($state,$result,'accents_commands');
  372. }
  373. sub info_default_noop
  374. {
  375. return '';
  376. }
  377. sub info_default_copying_comment($$$$)
  378. {
  379. my $copying_lines = shift;
  380. my $copying_text = shift;
  381. my $copying_no_texi = shift;
  382. my $copying_simple_text = shift;
  383. return '' if ($copying_text eq '');
  384. return $copying_text;
  385. }
  386. sub info_default_byte_count($)
  387. {
  388. my $string = shift;
  389. my $out_encoding = get_conf('OUT_ENCODING');
  390. if ($out_encoding and lc($out_encoding) ne 'us-ascii' and get_conf('USE_UNICODE'))
  391. {
  392. return length (Encode::encode($out_encoding, $string));
  393. }
  394. # There is no default encoding. We assume it is us-ascii. Not sure
  395. # about what perl thinks it is...
  396. #print STDERR "Unknown encoding for: $string\n" if (!$out_encoding);
  397. return length($string);
  398. }
  399. sub info_default_count_lines($;$$)
  400. {
  401. my $text = shift;
  402. my $indent_length = shift;
  403. my $indentation_done = shift;
  404. my $blank_line;
  405. my $no_indentation = 0;
  406. if (!defined($indentation_done) or $indentation_done)
  407. {
  408. $no_indentation = 1;
  409. $indent_length = 0;
  410. }
  411. my @lines = split /^/, $text;
  412. # don't accept empty text.
  413. @lines = ('') if (!@lines);
  414. my $line_passed = scalar(@lines);
  415. $line_passed-- if ($line_passed);
  416. my $end_of_line = 0;
  417. if (($#lines > 1) and !$end_of_line and ($lines[-1] !~ /\S/) and ($lines[-2] !~ /\S/))
  418. {
  419. $blank_line = 1;
  420. }
  421. my $last_line = $lines[-1];
  422. my $indented_text = shift (@lines);
  423. #print STDERR "COUNT info_default_count_lines(i_done $no_indentation, i_l $indent_length) i_t `$indented_text'\n";
  424. foreach my $line (@lines)
  425. {
  426. if ($indent_length and $line =~ /\S/)
  427. {
  428. $indented_text .= ' ' x $indent_length . $line;
  429. }
  430. else
  431. {
  432. $indented_text .= $line;
  433. }
  434. }
  435. if (chomp($text))
  436. {
  437. $line_passed++;
  438. $end_of_line = 1;
  439. }
  440. return ($line_passed, $end_of_line, $last_line, $indented_text, $blank_line);
  441. }
  442. sub info_default_get_state($)
  443. {
  444. my $state = shift;
  445. if (!exists $info_default_state_map{$state})
  446. {
  447. #print STDERR "NEW state $info_default_state_nr\n";
  448. my ($current_command, $top_stack);
  449. $info_default_state_map{$state} = {};
  450. info_default_reset_state($info_default_state_map{$state});
  451. # since the page head always leave a blank line, and the state may be
  452. # used for text right after the page head, we set it to 1 here.
  453. # it may be wrong in other contexts, to be seen.
  454. $info_default_state_map{$state}->{'blank_line'} = 1;
  455. $info_default_state_map{$state}->{'only_spaces'} = 1;
  456. # this is the first line, so set to 1. This is reset later in
  457. # most cases, when a node is seen, but may still be useful in
  458. # @footnote, for example
  459. $info_default_state_map{$state}->{'line_count'} = 1;
  460. $info_default_state_map{$state}->{'offset_in_file'} = 0;
  461. $info_default_state_map{$state}->{'nr'} = $info_default_state_nr;
  462. $info_default_state_map{$state}->{'state'} = $state;
  463. $info_default_state_map{$state}->{'multitable_stack'} = [];
  464. @{$info_default_state_map{$state}->{'align_stack'}} = ({'command'=>'normal'});
  465. $info_default_state_nr++;
  466. }
  467. #print STDERR "RETURN state $state $info_default_state_map{$state} $info_default_state_map{$state}->{'nr'}\n";
  468. return $info_default_state_map{$state};
  469. }
  470. sub info_default_reset_state($)
  471. {
  472. my $info_state = shift;
  473. $info_state->{'top'} = {};
  474. $info_state->{'current'} = $info_state->{'top'};
  475. }
  476. sub info_default_iterator_next($$$)
  477. {
  478. my $current_command = shift;
  479. my $command_index = shift;
  480. my $command_close = shift;
  481. #print STDERR "NNNNNNNNNNNNNN iterator_next current $current_command idx $command_index close $command_close\n";
  482. my $sub_command = $current_command->{'content'}->[$command_index];
  483. if ($sub_command->{'content'} and !$command_close)
  484. {
  485. return ($sub_command, 0, 0);
  486. }
  487. if ($current_command->{'content'}->[$command_index+1])
  488. {
  489. return ($current_command, $command_index+1, 0);
  490. }
  491. elsif (defined($current_command->{'parent'}))
  492. {
  493. return ($current_command->{'parent'}, $current_command->{'index_in_parent'}, 1);
  494. }
  495. else
  496. {
  497. return (undef, undef, undef);
  498. }
  499. }
  500. # return ($current_next, $index_next, $close_next, $text, $command);
  501. #
  502. # returns the next in tree, identified by the triplet
  503. # ($current_next, $index_next, $close_next) and also the command
  504. # and/or text if defined, in $text and $command.
  505. sub info_default_next($$$)
  506. {
  507. my $current = shift;
  508. my $index = shift;
  509. my $close = shift;
  510. my $text;
  511. my $command;
  512. my ($current_next, $index_next, $close_next) = info_default_iterator_next($current, $index, $close);
  513. return ($current_next, $index_next, $close_next, $text, $command) if (!defined($current_next));
  514. my $content = $current_next->{'content'}->[$index_next];
  515. $command = $content->{'command'} if (defined($content->{'command'}));
  516. if ($close_next)
  517. {
  518. return ($current_next, $index_next, $close_next, $content->{'end'}, $command);
  519. }
  520. if (defined($content->{'text'}))
  521. {
  522. return ($current_next, $index_next, $close_next, $content->{'text'}, $command);
  523. }
  524. if (defined($content->{'begin'}))
  525. {
  526. $text = $content->{'begin'};
  527. }
  528. if (defined($content->{'end'}) and !defined($content->{'content'}))
  529. {
  530. if (!defined($text))
  531. {
  532. $text = $content->{'end'};
  533. }
  534. else
  535. {
  536. $text .= $content->{'end'};
  537. }
  538. }
  539. return ($current_next, $index_next, $close_next, $text, $command);
  540. }
  541. sub info_default_process_line_text($$$)
  542. {
  543. my $text = shift;
  544. my $line_width_counter = shift;
  545. my $indent_length = shift;
  546. $indent_length = 0 if (!defined($indent_length));
  547. my $line_passed = 0;
  548. my $chomped_text = $text;
  549. my $end_of_line = chomp($chomped_text);
  550. if ($indent_length > $line_width_counter and $chomped_text ne '')
  551. {
  552. $text = ' ' x ($indent_length - $line_width_counter) . $text;
  553. }
  554. $line_width_counter += t2h_default_string_width($text);
  555. # it seems like it never happens in the tests.
  556. if ($end_of_line)
  557. {
  558. $line_passed = 1;
  559. $line_width_counter = 0;
  560. }
  561. return ($line_width_counter, $line_passed, $text);
  562. }
  563. # Beware that there is a pending word if the text doesn't end with
  564. # a space
  565. sub info_default_process_para_text($$$$$;$$)
  566. {
  567. my $text = shift;
  568. my $line_char_counter = shift;
  569. my $pending_spaces_word = shift;
  570. my $indent_length = shift;
  571. my $max_column = shift;
  572. my $keep_end_of_lines = shift;
  573. $keep_end_of_lines = 0 if (!$keep_end_of_lines);
  574. # indentation for the lines except for the first one
  575. my $indent_length_next = shift;
  576. $indent_length = 0 if (!defined($indent_length));
  577. $indent_length_next = $indent_length if (!defined($indent_length_next));
  578. my $line_passed = 0;
  579. my $result = '';
  580. #print STDERR "process_text(indent($indent_length,$indent_length_next),keep_eol $keep_end_of_lines) spaces `$pending_spaces_word->{'spaces'}') line_char_counter $line_char_counter |$text|\n";
  581. while ($text ne '')
  582. {
  583. #print STDERR "l_c_c $line_char_counter pending_word ".var_to_str($pending_spaces_word->{'word'}).", pending_spaces `$pending_spaces_word->{'spaces'}', result `$result'\n";
  584. if (!$keep_end_of_lines and $text =~ s/^(\s+)//)
  585. {
  586. my $new_spaces = $1;
  587. # in general there are no end of lines in the lines cut, since they
  588. # are replaced by spaces in the main loop. However, it may happen
  589. # with @* in @def* lines
  590. my @lines = split /^/, $new_spaces;
  591. my $eol_spaces;
  592. # last line is in $new_spaces, other lines are in $eol_spaces
  593. if (@lines > 1)
  594. {
  595. $new_spaces = pop @lines;
  596. $eol_spaces = join ("", @lines);
  597. #print STDERR "EOL_SPACES[$line_char_counter](+$pending_spaces_word->{'spaces'}) `$eol_spaces'\n";
  598. }
  599. if (defined($pending_spaces_word->{'word'}))
  600. {
  601. # add spaces in front if needed for the indentation
  602. if ($indent_length > $line_char_counter + t2h_default_string_width($pending_spaces_word->{'spaces'}))
  603. {
  604. $pending_spaces_word->{'spaces'} = ' ' x ($indent_length - $line_char_counter) . $pending_spaces_word->{'spaces'};
  605. }
  606. $result .= $pending_spaces_word->{'spaces'} . $pending_spaces_word->{'word'};
  607. $line_char_counter += t2h_default_string_width($pending_spaces_word->{'spaces'})+t2h_default_string_width($pending_spaces_word->{'word'});
  608. $pending_spaces_word->{'spaces'} = $new_spaces;
  609. $pending_spaces_word->{'word'} = undef;
  610. }
  611. elsif (!$eol_spaces)
  612. {
  613. $pending_spaces_word->{'spaces'} .= $new_spaces;
  614. }
  615. if ($eol_spaces)
  616. {
  617. $result .= $eol_spaces;
  618. $line_passed += scalar(@lines);
  619. $indent_length = $indent_length_next;
  620. $line_char_counter = 0;
  621. $pending_spaces_word->{'spaces'} = '';
  622. }
  623. if ((t2h_default_string_width($pending_spaces_word->{'spaces'}) + $line_char_counter > $max_column))
  624. {
  625. $pending_spaces_word->{'spaces'} = '';
  626. $result .= "\n";
  627. $line_passed++;
  628. $indent_length = $indent_length_next;
  629. $line_char_counter = 0;
  630. }
  631. }
  632. else
  633. {
  634. my $word;
  635. if ($keep_end_of_lines)
  636. {
  637. $word = $text;
  638. $text = '';
  639. }
  640. elsif ($text =~ s/^([^\s]+)//)
  641. {
  642. $word = $1;
  643. }
  644. #else
  645. #{
  646. # die "BUG: Impossible situation.\n";
  647. #}
  648. $pending_spaces_word->{'word'} = '' if (!defined($pending_spaces_word->{'word'}));
  649. $pending_spaces_word->{'word'} .= $word;
  650. # The $line_char_counter != 0 is here to cope with the case of a
  651. # word longer than $line_char_counter followed by more text:
  652. # a line would be passed each time some piece text is appended.
  653. if ((t2h_default_string_width($pending_spaces_word->{'spaces'})+t2h_default_string_width($pending_spaces_word->{'word'}) + $line_char_counter > $max_column) and $line_char_counter != 0)
  654. {
  655. $pending_spaces_word->{'spaces'} = '';
  656. $result .= "\n";
  657. $line_passed++;
  658. $indent_length = $indent_length_next;
  659. $line_char_counter = 0;
  660. }
  661. }
  662. }
  663. return ($line_char_counter, $pending_spaces_word, $line_passed, $result)
  664. }
  665. sub info_default_skip_spaces($$$)
  666. {
  667. my $current = shift;
  668. my $index = shift;
  669. my $close = shift;
  670. #print STDERR "SKIP_SPACES\n";
  671. while(1)
  672. {
  673. my ($current_next, $index_next, $close_next) = info_default_iterator_next($current, $index, $close);
  674. return if ($close_next or (!defined($current_next)));
  675. my $content = $current_next->{'content'}->[$index_next];
  676. if (defined($content->{'begin'}))
  677. {
  678. $content->{'begin'} =~ s/^\s*//;
  679. #print STDERR "SKIP_SPACES begin\n";
  680. return if ($content->{'begin'} ne '');
  681. }
  682. if (defined($content->{'content'}) or defined($content->{'format_name'})
  683. or $content->{'definition_line'})
  684. { # non empty commands stop space skipping, even if they contain
  685. # only spaces, like @asis{ }
  686. # also for item(x) that have format_name defined
  687. #print STDERR "SKIP_SPACES command?\n";
  688. return;
  689. }
  690. if (defined($content->{'text'}))
  691. {
  692. my $command = '';
  693. $command = $content->{'command'} if (defined($content->{'command'}));
  694. #print STDERR "SKIP_SPACES($command) text\n";
  695. $content->{'text'} =~ s/^\s*//;
  696. return if ($content->{'text'} ne '');
  697. }
  698. if (defined($content->{'end'}))
  699. {
  700. #print STDERR "SKIP_SPACES end\n";
  701. $content->{'end'} =~ s/^\s*//;
  702. return if ($content->{'end'} ne '');
  703. }
  704. ($current, $index, $close) = ($current_next, $index_next, $close_next);
  705. }
  706. }
  707. sub info_default_store_pending($$;$)
  708. {
  709. my $line_char_counter = shift;
  710. my $pending_spaces_word = shift;
  711. my $indent_length = shift;
  712. $indent_length = 0 if (!defined($indent_length));
  713. my $indent_text = '';
  714. $indent_text = ' ' x $indent_length;
  715. #print STDERR "store_pending(spaces `$pending_spaces_word->{'spaces'}', indent($indent_length) `$indent_text' word `".var_to_str($pending_spaces_word->{'word'})."'\n";
  716. my $result = $pending_spaces_word->{'spaces'};
  717. $pending_spaces_word->{'spaces'} = '';
  718. if (defined($pending_spaces_word->{'word'}))
  719. {
  720. $result .= $pending_spaces_word->{'word'};
  721. $pending_spaces_word->{'word'} = undef;
  722. }
  723. my $chomped_result = $result;
  724. chomp ($chomped_result);
  725. if ($line_char_counter == 0 and $chomped_result ne '')
  726. {
  727. $result = $indent_text . $result;
  728. }
  729. $line_char_counter += t2h_default_string_width($result);
  730. return ($line_char_counter, $pending_spaces_word, $result);
  731. }
  732. sub info_default_output($)
  733. {
  734. my $info_state = shift;
  735. my $result = '';
  736. #print STDERR "Storing the stack\n";
  737. print STDERR "" . Data::Dumper->Dump([$info_state->{'top'}]) if (get_conf('DEBUG'));
  738. my ($bytes_count, $lines_count);
  739. ($bytes_count, $result, $lines_count) = info_default_process_content($info_state->{'top'}, $info_state);
  740. $info_state->{'offset_in_file'} += $bytes_count;
  741. $info_state->{'line_count'} += $lines_count;
  742. #print STDERR "HHHHHH($lines_count) $info_state->{'line_count'}: $result\n";
  743. info_default_reset_state($info_state)
  744. if (!defined($info_state->{'current'}->{'command'}));
  745. return $result;
  746. }
  747. sub info_default_process_content($$)
  748. {
  749. my $current_command = shift;
  750. my $info_state = shift;
  751. my $length = 0;
  752. my $result = '';
  753. my $line_char_counter = 0;
  754. my $all_line_passed = 0;
  755. my $pending_spaces_word;
  756. $pending_spaces_word->{'spaces'} = '';
  757. my $preformatted = 0;
  758. my $indent_level = 0;
  759. my $item_pending;
  760. my $in_exdent = 0;
  761. my $in_para = 0;
  762. my $in_w = 0;
  763. my $table_item_line = 0;
  764. my $in_table_item = 0;
  765. my $max_column = get_conf('FILLCOLUMN');
  766. my $direntry = 0;
  767. my $preformatted_format = 0;
  768. my $indent_length = 0;
  769. # for formats that needs to process a full line (center and flushright)
  770. # to know the line length before outputing
  771. my $current_line = undef;
  772. my ($current, $index, $close) = ($current_command, 0, 0);
  773. #print STDERR "info_default_process_content: $current_command\n";
  774. while(1)
  775. {
  776. last if (!defined($current));
  777. my $content = $current->{'content'}->[$index];
  778. my $text_added = '';
  779. my $line_added_before_item = 0;
  780. my $indentation_done = 0;
  781. my $prepend_newline;
  782. if (get_conf('DEBUG'))
  783. {
  784. my $text_item_pending = '';
  785. $text_item_pending = $item_pending if (defined($item_pending));
  786. my $text_length = '';
  787. $text_length = "$content->{'text'}" if defined($content->{'text'});
  788. my $text_command = '';
  789. $text_command = $content->{'command'} if defined($content->{'command'});
  790. my $in_node_count = 0;
  791. $in_node_count = $info_state->{'line_count'} if defined($info_state->{'line_count'});
  792. print STDERR "($text_command|$text_length|$close|${all_line_passed}+$in_node_count|l_c_cnt $line_char_counter) prfrmted $preformatted para $in_para indent_lvl $indent_level($indent_length) in_exdent $in_exdent in_w $in_w only_spaces $info_state->{'only_spaces'} blank_line $info_state->{'blank_line'} table_item_line $table_item_line in_table_item $in_table_item item_pending $text_item_pending spaces: `$pending_spaces_word->{'spaces'}' word: ".main::var_to_str($pending_spaces_word->{'word'})."\n";
  793. }
  794. if ($close)
  795. {
  796. if (defined($content->{'end'}))
  797. {
  798. $text_added .= $content->{'end'};
  799. }
  800. if ($complex_format_map{$content->{'command'}} and $content->{'content'})
  801. {
  802. $preformatted_format--;
  803. }
  804. # the format is always empty in the main program so the warning
  805. # has to be done here
  806. if (defined($content->{'total_item_nr'}) and !$content->{'total_item_nr'} and $content->{'content'})
  807. {
  808. main::line_warn (sprintf(__("\@%s has text but no \@item"), $content->{'command'}), $content->{'line_nr'});
  809. }
  810. # check whether there is a blank line following, to avoid adding
  811. # one when closing a format.
  812. # This is not a required check if not in preformatted since doubled
  813. # blank lines are discarded.
  814. my $followed_by_blank_line = 0;
  815. if ($preformatted_format)
  816. {
  817. my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close);
  818. if (defined($command_next) and $command_next eq 'preformatted')
  819. {
  820. ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current_next, $index_next, $close_next);
  821. $followed_by_blank_line = 1 if (defined($text_next) and $text_next =~ /^\s*$/);
  822. }
  823. }
  824. if ($info_default_indented_commands{$content->{'command'}})
  825. {
  826. $indent_level--;
  827. $indent_length = $indent_level * $info_default_indent_length;
  828. # $preformatteed cannot be used here since preformatted
  829. # is closed before the end of a format
  830. #if ($indent_level > 0 and !$info_state->{'blank_line'} and $content->{'command'} !~ /^deff_item/ and !$preformatted_format)
  831. if ($indent_level > 0 and !$info_state->{'blank_line'} and $content->{'command'} !~ /^deff_item/ and !$followed_by_blank_line)
  832. {
  833. $text_added .= "\n";
  834. }
  835. # this nullify a potential noindent in a random format
  836. $info_state->{'indent_para'} = undef;
  837. }
  838. elsif (($complex_format_map{$content->{'command'}} and $content->{'command'} ne 'menu') or $content->{'command'} eq 'cartouche')
  839. {
  840. if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level > 0) and !$followed_by_blank_line)
  841. {
  842. $text_added .= "\n";
  843. }
  844. }
  845. if ($content->{'command'} eq 'paragraph' and $info_state->{'align_stack'}->[-1]->{'command'} eq 'normal')
  846. {
  847. # if there is no space at the end of a paragraph, there may be
  848. # pending text, for example, if there is an ending line like
  849. # Some text@c a comment
  850. my $pending;
  851. ($line_char_counter, $pending_spaces_word, $pending) = info_default_store_pending($line_char_counter, $pending_spaces_word, $indent_length);
  852. $text_added .= $pending if (defined($pending));
  853. $text_added =~ s/\s*$//;
  854. $pending_spaces_word->{'spaces'} = '';
  855. $in_para = 0;
  856. $info_state->{'indent_para'} = undef;
  857. $text_added .= "\n" unless (($line_char_counter + t2h_default_string_width($text_added)) == 0);
  858. }
  859. elsif ($content->{'command'} eq 'preformatted')
  860. {
  861. # if preformatted doesn't end with a newline, it is added here
  862. $text_added .= "\n" unless ($line_char_counter == 0);
  863. $preformatted--;
  864. }
  865. elsif ($content->{'command'} eq 'menu')
  866. {
  867. $text_added .= "\n" unless ($info_state->{'blank_line'});
  868. }
  869. elsif ($content->{'command'} eq 'float')
  870. {
  871. #$text_added = "\n" . $text_added unless ($info_state->{'blank_line'});
  872. $prepend_newline = 1 unless ($info_state->{'blank_line'});
  873. }
  874. elsif ($content->{'command'} eq 'w')
  875. {
  876. $in_w--;
  877. }
  878. elsif ($paragraph_style{$content->{'command'}})
  879. {
  880. my $popped = pop @{$info_state->{'align_stack'}};
  881. print STDERR "BUG".main::format_line_number().": align_stack, popped $popped->{'command'} ne command $content->{'command'}\n" if ($popped->{'command'} ne $content->{'command'});
  882. }
  883. elsif ($content->{'command'} eq 'multitable')
  884. {
  885. my $multitable = pop @{$info_state->{'multitable_stack'}};
  886. if (!defined($multitable->{'cells'}) and ($result ne ''))
  887. {
  888. $multitable->{'result'} .= $result;
  889. $multitable->{'length'} += $length;
  890. $multitable->{'line_count'} += $all_line_passed;
  891. }
  892. $max_column = $multitable->{'max_column_kept'};
  893. $result = $multitable->{'result_kept'};
  894. $line_char_counter = $multitable->{'line_char_counter_kept'};
  895. $all_line_passed = $multitable->{'all_line_passed_kept'};
  896. $indent_level = $multitable->{'indent_level_kept'};
  897. $indent_length = $multitable->{'indent_length_kept'};
  898. #$indent_length_next_line = undef;
  899. $length = $multitable->{'length_kept'};
  900. $info_state->{'offset_in_file'} = $multitable->{'offset_in_file_kept'};
  901. $info_state->{'line_count'} = $multitable->{'line_count_kept'};
  902. #print STDERR "MULTITABLE close, lines: $multitable->{'line_count_kept'} + $all_line_passed\n";
  903. foreach my $anchor_and_index (@{$multitable->{'anchors'}}, @{$multitable->{'index_entries'}})
  904. {
  905. $anchor_and_index->{'line_nr'} += $multitable->{'line_count_kept'} + $all_line_passed;
  906. }
  907. if (! scalar(@{$info_state->{'multitable_stack'}}))
  908. {
  909. #print STDERR "MULTITABLE close, lengths: $multitable->{'offset_in_file_kept'} + $length\n";
  910. foreach my $anchor (@{$multitable->{'anchors'}})
  911. {
  912. $anchor->{'info_offset'} += $multitable->{'offset_in_file_kept'} + $length;
  913. }
  914. }
  915. else
  916. {
  917. push @{$info_state->{'multitable_stack'}->[-1]->{'anchors'}}, @{$multitable->{'anchors'}};
  918. push @{$info_state->{'multitable_stack'}->[-1]->{'index_entries'}}, @{$multitable->{'index_entries'}};
  919. }
  920. $text_added .= $multitable->{'result'};
  921. $indentation_done = 1;
  922. goto new_text;
  923. }
  924. elsif ($content->{'command'} eq 'multitable_cell')
  925. {
  926. my $cell = $info_state->{'multitable_stack'}->[-1]->{'cells'}->[-1];
  927. $cell->{'result'} = $result;
  928. $cell->{'length'} = $length;
  929. $cell->{'line_passed'} = $all_line_passed;
  930. }
  931. elsif ($content->{'command'} eq 'direntry')
  932. {
  933. $direntry--;
  934. # this has to be done here, otherwise, at the end, $direntry
  935. # would be 0
  936. $info_default_dir_specification .= $text_added;
  937. $text_added = '';
  938. }
  939. elsif ($content->{'command'} eq 'multitable_row')
  940. {
  941. my $multitable = $info_state->{'multitable_stack'}->[-1];
  942. my $indent_len = $multitable->{'indent_length_kept'};
  943. #print STDERR "INDENT: $indent_len\n";
  944. my $row_length = 0;
  945. my $row = '';
  946. my $max_lines = 0;
  947. my $cell_beginning = 0;
  948. my @anchor_lines_array;
  949. my $cell_idx = 0;
  950. my @anchors;
  951. my @indices;
  952. foreach my $cell (@{$multitable->{'cells'}})
  953. {
  954. $cell->{'beginning'} = $cell_beginning;
  955. $cell_beginning += $cell->{'cell_width'}+1;
  956. @{$cell->{'lines'}} = split /^/, $cell->{'result'};
  957. $max_lines = scalar(@{$cell->{'lines'}}) if (scalar(@{$cell->{'lines'}}) > $max_lines);
  958. foreach my $anchor (@{$cell->{'anchors'}})
  959. {
  960. push @{$anchor_lines_array[$anchor->{'line_nr'}]}, $anchor;
  961. $anchor->{'cell_idx'} = $cell_idx;
  962. push @anchors, $anchor;
  963. }
  964. push @indices, @{$cell->{'index_entries'}};
  965. $cell_idx++;
  966. }
  967. my $previous_last_cell = scalar(@{$multitable->{'cells'}});
  968. #print STDERR "ROW cell_beginning $cell_beginning, max_lines $max_lines, previous_last_cell $previous_last_cell\n";
  969. for (my $line_idx = 0; $line_idx < $max_lines; $line_idx++)
  970. {
  971. my $line_width = $indent_len;
  972. my $line_bytes = info_default_byte_count(' ' x$indent_len);
  973. my $line = '';
  974. # determine the last cell in the line, to fill spaces in
  975. # cells preceding that cell on the line
  976. my $last_cell = 0;
  977. for (my $cell_idx = 0; $cell_idx < $previous_last_cell; $cell_idx++)
  978. {
  979. $last_cell = $cell_idx+1 if (defined($multitable->{'cells'}->[$cell_idx]->{'lines'}->[$line_idx]));
  980. }
  981. #print STDERR " L(last_cell $last_cell): $line_idx\n";
  982. for (my $cell_idx = 0; $cell_idx < $last_cell; $cell_idx++)
  983. {
  984. my $cell_text = $multitable->{'cells'}->[$cell_idx]->{'lines'}->[$line_idx];
  985. #print STDERR " C($cell_idx) ";
  986. if (defined($cell_text))
  987. {
  988. chomp($cell_text);
  989. #print STDERR "$cell_text";
  990. if ($line eq '' and $cell_text ne '')
  991. {
  992. $line = ' ' x $indent_len;
  993. }
  994. $line .= $cell_text;
  995. $line_width += t2h_default_string_width($cell_text);
  996. $line_bytes += info_default_byte_count($cell_text);
  997. }
  998. if ($cell_idx+1 < $last_cell)
  999. {
  1000. if ($line_width < $indent_len + $multitable->{'cells'}->[$cell_idx+1]->{'beginning'})
  1001. {
  1002. if ($line eq '')
  1003. {
  1004. $line = ' ' x $indent_len;
  1005. }
  1006. my $spaces = ' ' x ($indent_len + $multitable->{'cells'}->[$cell_idx+1]->{'beginning'} - $line_width);
  1007. $line_width += t2h_default_string_width($spaces);
  1008. $line_bytes += info_default_byte_count($spaces);
  1009. $line .= $spaces;
  1010. #print STDERR " Csp($line_width) `$spaces'";
  1011. }
  1012. }
  1013. }
  1014. if (defined($anchor_lines_array[$line_idx]))
  1015. {
  1016. foreach my $anchor (@{$anchor_lines_array[$line_idx]})
  1017. {
  1018. my $anchor_position = $indent_len + $anchor->{'line_char_counter'} + $multitable->{'cells'}->[$anchor->{'cell_idx'}]->{'beginning'};
  1019. if ($anchor_position > $line_width)
  1020. {
  1021. my $spaces = ' ' x ($anchor_position - $line_width);
  1022. $line .= $spaces;
  1023. $line_width += t2h_default_string_width($spaces);
  1024. $line_bytes += info_default_byte_count($spaces);
  1025. }
  1026. $anchor->{'info_offset'} = $line_bytes + $row_length + $multitable->{'length'};
  1027. #print STDERR "ROW anchor close: anchor[$anchor->{'cell_idx'}]($multitable->{'cells'}->[$anchor->{'cell_idx'}]->{'beginning'}+$anchor->{'line_char_counter'}) $anchor_position $anchor->{'info_offset'}\n";
  1028. $anchor->{'line_char_counter'} = $anchor_position;
  1029. }
  1030. }
  1031. $line .= "\n";
  1032. $row_length += info_default_byte_count($line);
  1033. #print STDERR " ($line_width,".length($line).") $line";
  1034. $row .= $line;
  1035. $previous_last_cell = $last_cell;
  1036. }
  1037. foreach my $anchor_and_index (@anchors, @indices)
  1038. {
  1039. $anchor_and_index->{'line_nr'} += $multitable->{'line_count'};
  1040. #print STDERR "ROW close: new line count: $anchor_and_index->{'line_nr'} + \n";
  1041. }
  1042. if ($content->{'item_command'} eq 'headitem')
  1043. {
  1044. # at this point cell_beginning is at the beginning of
  1045. # the cell following the end of the table -> full width
  1046. my $line = ' ' x $indent_len . '-' x $cell_beginning . "\n";
  1047. $row .= $line;
  1048. $row_length += info_default_byte_count($line);
  1049. }
  1050. #print STDERR "ROW_LENGTH $row_length\n";
  1051. $multitable->{'result'} .= $row;
  1052. $multitable->{'length'} += $row_length;
  1053. $multitable->{'line_count'} += $max_lines;
  1054. $multitable->{'cells'} = [];
  1055. push @{$multitable->{'anchors'}}, @anchors;
  1056. push @{$multitable->{'index_entries'}}, @indices;
  1057. }
  1058. }
  1059. else
  1060. {
  1061. if ($content->{'command'})
  1062. {
  1063. # if processing a paragraph, there may be some pending text
  1064. # and spaces, as the idea is to write them down only when
  1065. # there is a space in case of pending text, or when there is some
  1066. # text in case of pending space. So all the commands
  1067. # that should write something within paragraph must flush the
  1068. # pending text/spaces _before_ they output something, or the
  1069. # text order will be reversed, with the pending things output
  1070. # after the other commands text.
  1071. my $pending_added_length = 0;
  1072. my $pending_added_bytes = 0;
  1073. if ($content->{'command'} eq 'anchor' or $content->{'command'} eq 'image' or $content->{'command'} eq 'index_command' or $content->{'command'} eq 'sp' or $content->{'raw_command'})
  1074. {
  1075. my $pending;
  1076. ($line_char_counter, $pending_spaces_word, $pending) = info_default_store_pending($line_char_counter, $pending_spaces_word, $indent_length);
  1077. # here spaces out of any environment are ignored.
  1078. if ($in_para or $preformatted or $pending =~ /\S/)
  1079. { # this has to be done before the anchor related code
  1080. # to have the right count.
  1081. # FIXME this is wrong if an end of line was passed.
  1082. # in that case line_char_counter has been increased and
  1083. # $pending ends with an end of line
  1084. $pending_added_length += t2h_default_string_width($pending);
  1085. $pending_added_bytes += info_default_byte_count($pending);
  1086. $text_added .= $pending;
  1087. }
  1088. }
  1089. if ($content->{'command'} eq 'strong')
  1090. {
  1091. my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close);
  1092. if (defined($text_next) and $text_next =~ /^Note\b/i)
  1093. {
  1094. main::line_warn(__("\@strong{Note...} produces a spurious cross-reference in Info; reword to avoid that"), $content->{'line_nr'});
  1095. }
  1096. }
  1097. elsif ($content->{'command'} eq 'w')
  1098. {
  1099. $in_w++ if ($content->{'content'});
  1100. }
  1101. elsif ($content->{'command'} eq 'anchor' or ($content->{'command'} eq 'float' and $content->{'anchor_reference'}))
  1102. {
  1103. #print STDERR "anchor: offset_in_file $info_state->{'offset_in_file'}, line_count $info_state->{'line_count'}, line_char_counter $line_char_counter pending_added_length $pending_added_length\n";
  1104. $content->{'anchor_reference'}->{'info_offset'} = $length + $info_state->{'offset_in_file'} + $pending_added_bytes;
  1105. $content->{'anchor_reference'}->{'line_nr'} = $all_line_passed + $info_state->{'line_count'};
  1106. $content->{'anchor_reference'}->{'line_char_counter'} = $line_char_counter + $pending_added_length;
  1107. if (@{$info_state->{'multitable_stack'}})
  1108. {
  1109. if ($info_state->{'multitable_stack'}->[-1]->{'cells'})
  1110. {
  1111. push @{$info_state->{'multitable_stack'}->[-1]->{'cells'}->[-1]->{'anchors'}}, $content->{'anchor_reference'};
  1112. }
  1113. else
  1114. {
  1115. push @{$info_state->{'multitable_stack'}->[-1]->{'anchors'}}, $content->{'anchor_reference'};
  1116. }
  1117. }
  1118. push @{$info_state->{'pending_tags'}}, $content->{'anchor_reference'};
  1119. push @{$info_state->{'align_stack'}->[-1]->{'anchors'}}, $content->{'anchor_reference'} if ($info_state->{'align_stack'}->[-1]->{'command'} eq 'center' or $info_state->{'align_stack'}->[-1]->{'command'} eq 'flushright');
  1120. }
  1121. elsif ($content->{'command'} eq 'index_label')
  1122. {
  1123. #print STDERR "FFFFFFFFF($content->{'index_command'}) $all_line_passed + $info_state->{'line_count'} `$content->{'texi_entry'}'\n";
  1124. my $index_line_nr = $all_line_passed + $info_state->{'line_count'};
  1125. if ($info_state->{'blank_line'} and $content->{'index_command'} =~ /index$/)
  1126. {
  1127. my ($current_next, $index_next, $close_next) = info_default_iterator_next($current, $index, $close);
  1128. $index_line_nr-- if (!defined($current_next));
  1129. }
  1130. elsif ($content->{'index_command'} =~ /^[vf]table$/)
  1131. {
  1132. # if in a table, index label is systematically entered after
  1133. # the line is processed, as the line is processed with the
  1134. # item command, while the index entry is entered with the
  1135. # index_label callback that is done much later.
  1136. $index_line_nr--;
  1137. }
  1138. #print STDERR "index in a blank_line $content->{'index_command'} `$content->{'texi_entry'}'\n" if ($info_state->{'blank_line'});
  1139. my $index_name = $content->{'index_entry_reference'}->{'index_name'};
  1140. $info_default_index_line_string_length{$index_name} = t2h_default_string_width($index_line_nr)
  1141. if (!defined($info_default_index_line_string_length{$index_name}) or $info_default_index_line_string_length{$index_name} < t2h_default_string_width($index_line_nr));
  1142. #print STDERR "RRRRRRRRRRRRR($content->{'index_entry_reference'}) $content->{'index_entry_reference'}->{'texi'} name: $index_name line: $index_line_nr max: $info_default_index_line_string_length{$index_name}\n";
  1143. my $index_ref = { 'index_entry_reference' => $content->{'index_entry_reference'}, 'line_nr' => $index_line_nr };
  1144. #print STDERR "INDEX($index_name) line $index_line_nr\n";
  1145. $info_default_index_entries{$content->{'index_entry_reference'}} = $index_ref;
  1146. # there may be no cell in case of an empty multitable
  1147. if (@{$info_state->{'multitable_stack'}})
  1148. {
  1149. if ($info_state->{'multitable_stack'}->[-1]->{'cells'})
  1150. {
  1151. push @{$info_state->{'multitable_stack'}->[-1]->{'cells'}->[-1]->{'index_entries'}}, $index_ref;
  1152. }
  1153. else
  1154. {
  1155. push @{$info_state->{'multitable_stack'}->[-1]->{'index_entries'}}, $index_ref;
  1156. }
  1157. }
  1158. push @{$info_state->{'pending_index_entries'}}, $index_ref;
  1159. }
  1160. elsif ($content->{'command'} eq '*' and !$preformatted)
  1161. {
  1162. if (defined($pending_spaces_word->{'word'}))
  1163. {
  1164. $text_added .= $pending_spaces_word->{'spaces'} . $pending_spaces_word->{'word'};
  1165. $pending_spaces_word->{'word'} = undef;
  1166. }
  1167. # spaces preceding @* are skipped
  1168. $pending_spaces_word->{'spaces'} = '';
  1169. $text_added .= $content->{'text'};
  1170. # just like following spaces
  1171. info_default_skip_spaces($current, $index, $close);
  1172. # this isn't done otherwise, though, here it is not important
  1173. # since this end the line
  1174. $line_char_counter += t2h_default_string_width($content->{'text'});
  1175. goto new_text;
  1176. }
  1177. elsif ($content->{'command'} eq 'paragraph' and $info_state->{'align_stack'}->[-1]->{'command'} eq 'normal')
  1178. {
  1179. # empty paragraph
  1180. goto new_text if (!$content->{'content'});
  1181. my $paragraphindent = get_conf('paragraphindent');
  1182. $paragraphindent = 0 if ($paragraphindent eq 'none');
  1183. if ($paragraphindent ne 'asis')
  1184. {
  1185. info_default_skip_spaces($current, $index, $close);
  1186. }
  1187. # if within a format $content->{'paragraph_in_element_nr'}
  1188. # should not be defined so no indentation will take place
  1189. if ($paragraphindent ne 'asis' and $paragraphindent and $line_char_counter == 0 and (defined($content->{'paragraph_in_element_nr'})) and ($info_state->{'indent_para'} or (!defined($info_state->{'indent_para'}) and ($content->{'paragraph_in_element_nr'} or (get_conf('firstparagraphindent') eq 'insert')))))
  1190. {
  1191. $text_added .= ' ' x $paragraphindent;
  1192. }
  1193. $in_para = 1;
  1194. }
  1195. elsif ($content->{'command'} eq 'preformatted')
  1196. {
  1197. $preformatted++ if ($content->{'content'});
  1198. }
  1199. elsif ($content->{'command'} eq 'exdent')
  1200. {
  1201. # if an end of line is added, in_exdent is set to 2 and
  1202. # set to one when processing the end of line that was just
  1203. # added, and set to 0 at the end of the line.
  1204. # if there is no end of line added, it is only set to 1.
  1205. if ($line_char_counter != 0)
  1206. {
  1207. $text_added .= "\n";
  1208. $in_exdent = 2;
  1209. }
  1210. else
  1211. {
  1212. $in_exdent = 1;
  1213. }
  1214. $indent_length = ($indent_level -1) * $info_default_indent_length if ($indent_level > 0);
  1215. #goto new_text;
  1216. }
  1217. elsif ($content->{'command'} eq 'indent')
  1218. {
  1219. $info_state->{'indent_para'} = 1;
  1220. }
  1221. elsif ($content->{'command'} eq 'noindent')
  1222. {
  1223. $info_state->{'indent_para'} = 0;
  1224. }
  1225. elsif ($content->{'command'} eq 'sp')
  1226. {
  1227. $text_added .= $content->{'text'};
  1228. goto new_text;
  1229. }
  1230. elsif ($content->{'command'} eq 'image')
  1231. {
  1232. # @image result count isn't counted in line_char_counter
  1233. # since it is not displayed in info
  1234. my $indent_added = 0;
  1235. $indent_added = ($indent_length - $line_char_counter) if ($indent_length - $line_char_counter > 0);
  1236. $text_added .= ' ' x $indent_added . $content->{'text'};
  1237. $line_char_counter += $indent_added;
  1238. goto new_text;
  1239. }
  1240. elsif ($content->{'command'} eq 'ref')
  1241. { # adds a . if needed.
  1242. if ($content->{'text'} !~ /[\.,]$/ and $content->{'text'} !~ /::$/)
  1243. {
  1244. my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close);
  1245. if (!defined($text_next) or $text_next !~ /^[\.,]/)
  1246. {
  1247. $content->{'text'} .= '.';
  1248. }
  1249. }
  1250. }
  1251. elsif ($content->{'command'} eq 'xref')
  1252. { # warn if there is no punctuation following
  1253. my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close);
  1254. if (!defined($text_next) or $text_next !~ /^./)
  1255. { # in makeinfo it is
  1256. # "End of file reached while looking for `.' or `,'"
  1257. # but maybe it may not be true.
  1258. main::line_warn(__("`.' or `,' must follow \@xref."), $Texi2HTML::THISDOC{'line_nr'});
  1259. }
  1260. elsif ($text_next !~ /^[\.,]/)
  1261. {
  1262. my $char = substr($text_next, 0, 1);
  1263. main::line_warn(sprintf(__("`.' or `,' must follow \@xref, not %s"), $char), $Texi2HTML::THISDOC{'line_nr'});
  1264. }
  1265. }
  1266. elsif ($content->{'definition_line'})
  1267. {
  1268. my $dummy_line_passed;
  1269. print STDERR "BUG: defined pending_word before DEFINITION_LINE\n" if defined($pending_spaces_word->{'word'});
  1270. #print STDERR "DEFINITION_LINE($line_char_counter,$pending_spaces_word->{'spaces'},$indent_length,$in_para,$max_column): $content->{'text'}";
  1271. ($line_char_counter, $pending_spaces_word, $dummy_line_passed, $text_added) = info_default_process_para_text($content->{'text'}, $line_char_counter, $pending_spaces_word, $indent_length, $max_column, 0, $indent_length+2*$info_default_indent_length);
  1272. $text_added .= $pending_spaces_word->{'spaces'};
  1273. $pending_spaces_word->{'spaces'} = '';
  1274. #print STDERR "DEFINITION_LINE($line_char_counter,$pending_spaces_word->{'spaces'}) -> $text_added";
  1275. print STDERR "BUG: defined pending_word after DEFINITION_LINE\n" if defined($pending_spaces_word->{'word'});
  1276. $indentation_done = 1;
  1277. goto new_text;
  1278. }
  1279. elsif (($content->{'command'} eq 'item' or $content->{'command'} eq 'itemx') and exists $info_default_indent_format_length{$content->{'format_name'}})
  1280. {
  1281. $item_pending = $content->{'format_name'};
  1282. #if (!$info_state->{'blank_line'} and $content->{'command'} eq 'item')
  1283. my $first_item = 0;
  1284. if ($content->{'command'} eq 'item')
  1285. {
  1286. if (!defined($content->{'parent'}->{'item_nr'}))
  1287. {
  1288. $content->{'parent'}->{'item_nr'} = 1;
  1289. $first_item = 1;
  1290. }
  1291. else
  1292. {
  1293. $content->{'parent'}->{'item_nr'}++;
  1294. }
  1295. }
  1296. if ($item_pending =~ /table$/)
  1297. {
  1298. $table_item_line = 1;
  1299. $indent_length = ($indent_level -1) * $info_default_indent_length if ($indent_level > 0);
  1300. $in_table_item = 0;
  1301. }
  1302. else
  1303. {
  1304. $indent_length = ($info_default_indent_format_length{$item_pending}
  1305. +($indent_level -1)* $info_default_indent_length);
  1306. }
  1307. if (!$info_state->{'blank_line'} and ($content->{'command'} ne 'itemx') and (!$first_item or $indent_level > 1))
  1308. {
  1309. my $dummy_line_passed;
  1310. ($line_char_counter, $dummy_line_passed, $text_added) = info_default_process_line_text($text_added, $line_char_counter, $indent_length);
  1311. $indentation_done = 1;
  1312. $line_added_before_item = 1;
  1313. $prepend_newline = 1;
  1314. #$text_added = "\n" . $text_added;
  1315. }
  1316. if ($item_pending =~ /table$/)
  1317. {
  1318. # one less indentation level and no line break
  1319. # adding line_added_before_item allows the table_item_line to
  1320. # still be active after the additional blank line
  1321. $table_item_line = 1+$line_added_before_item;
  1322. }
  1323. else
  1324. {
  1325. info_default_skip_spaces($current, $index, $close);
  1326. }
  1327. }
  1328. elsif ($content->{'command'} eq 'menu' or $content->{'command'} eq 'listoffloats' or $content->{'heading_command'})
  1329. {
  1330. $text_added .= "\n" unless ($info_state->{'blank_line'});
  1331. }
  1332. elsif ($content->{'command'} eq 'direntry')
  1333. {
  1334. if ($content->{'content'})
  1335. {
  1336. $direntry++;
  1337. }
  1338. }
  1339. elsif ($paragraph_style{$content->{'command'}})
  1340. {
  1341. goto new_text if (!$content->{'content'});
  1342. push @{$info_state->{'align_stack'}}, {'command' => $content->{'command'}};
  1343. }
  1344. elsif ($content->{'command'} eq 'verbatim' or $content->{'command'} eq 'verbatiminclude')
  1345. {
  1346. # $preformatted cannot be used here since preformatted
  1347. # is closed before a verbatim, $preformatted_format is used
  1348. if (!$preformatted_format and $indent_level != 0)
  1349. {
  1350. if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'})
  1351. {
  1352. $text_added .= "\n";
  1353. }
  1354. my $verb_text = $content->{'text'};
  1355. my ($line_passed, $end_of_line, $last_line, $text_indented, $blank_line) = info_default_count_lines($verb_text);
  1356. $content->{'text'} .= "\n" unless ($blank_line or ($last_line =~ /^\s*$/));
  1357. }
  1358. }
  1359. # other raw commands
  1360. elsif ($content->{'raw_command'})
  1361. {
  1362. # not considered as in a paragraph even if in a paragraph
  1363. $text_added .= $content->{'text'};
  1364. goto new_text;
  1365. }
  1366. elsif ($content->{'command'} eq 'multitable' and $content->{'content'})
  1367. {
  1368. my $indent_length_kept = $indent_level * $info_default_indent_length;
  1369. my $multitable = {
  1370. 'offset_in_file_kept' => $info_state->{'offset_in_file'},
  1371. 'line_count_kept' => $info_state->{'line_count'},
  1372. 'columns_size' => [ @{$content->{'columns_size'}} ],
  1373. 'result' => '',
  1374. 'length' => 0,
  1375. 'line_count' => 0,
  1376. 'result_kept' => $result,
  1377. 'length_kept' => $length,
  1378. 'all_line_passed_kept' => $all_line_passed,
  1379. 'line_char_counter_kept' => $line_char_counter,
  1380. 'max_column_kept' => $max_column,
  1381. 'indent_level_kept' => $indent_level,
  1382. 'indent_length_kept' => $indent_length_kept,
  1383. };
  1384. push @{$info_state->{'multitable_stack'}}, $multitable;
  1385. $info_state->{'offset_in_file'} = 0;
  1386. $info_state->{'line_count'} = 0;
  1387. $result = '';
  1388. $length = 0;
  1389. $all_line_passed = 0;
  1390. $line_char_counter = 0;
  1391. $indent_level = 0;
  1392. $indent_length = 0;
  1393. }
  1394. elsif ($content->{'command'} eq 'multitable_row')
  1395. {
  1396. my $multitable = $info_state->{'multitable_stack'}->[-1];
  1397. if (!defined($multitable->{'cells'}) and ($result ne ''))
  1398. {
  1399. $multitable->{'result'} .= $result;
  1400. $multitable->{'length'} += $length;
  1401. $multitable->{'line_count'} += $all_line_passed;
  1402. $multitable->{'cells'} = [];
  1403. }
  1404. $multitable->{'cell_index'} = -1;
  1405. }
  1406. elsif ($content->{'command'} eq 'multitable_cell')
  1407. {
  1408. my $multitable = $info_state->{'multitable_stack'}->[-1];
  1409. $multitable->{'cell_index'}++;
  1410. my $cell_width = $content->{'parent'}->{'parent'}->{'columns_size'}->[$multitable->{'cell_index'}];
  1411. #$max_column = $cell_width-1;
  1412. $max_column = $cell_width -2;
  1413. my $cell = {'cell_width' => $cell_width, 'index_entries' => [], 'anchors' => []};
  1414. push @{$multitable->{'cells'}}, $cell;
  1415. $result = '';
  1416. $length = 0;
  1417. $all_line_passed = 0;
  1418. $line_char_counter = 0;
  1419. $indent_level = 0;
  1420. $indent_length = 0;
  1421. if (!$content->{'content'})
  1422. {# empty cell
  1423. $cell->{'result'} = $result;
  1424. $cell->{'length'} = $length;
  1425. $cell->{'line_passed'} = $all_line_passed;
  1426. }
  1427. #info_default_skip_spaces($current, $index, $close);
  1428. }
  1429. if ($info_default_indented_commands{$content->{'command'}})
  1430. {
  1431. if ($content->{'command'} =~ /^deff_item/)
  1432. {
  1433. info_default_skip_spaces($current, $index, $close);
  1434. }
  1435. #elsif (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0) and !$preformatted)
  1436. elsif (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0))
  1437. {
  1438. $text_added .= "\n";
  1439. }
  1440. # there is no close if !$content->{'content'}
  1441. $indent_level++ if ($content->{'content'});
  1442. $indent_length = $indent_level * $info_default_indent_length;
  1443. }
  1444. elsif (($complex_format_map{$content->{'command'}} and $content->{'command'} ne 'menu') or $content->{'command'} eq 'cartouche')
  1445. {
  1446. #if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0) and !$preformatted_format)
  1447. if (!$info_state->{'blank_line'} and $info_state->{'only_spaces'} and ($indent_level != 0))
  1448. {
  1449. $text_added .= "\n";
  1450. }
  1451. }
  1452. if ($complex_format_map{$content->{'command'}} and $content->{'content'})
  1453. {
  1454. $preformatted_format++;
  1455. }
  1456. }
  1457. if (defined($content->{'text'}))
  1458. {
  1459. if ($in_para and !$in_exdent)
  1460. {
  1461. #print STDERR "IN_PARA text\n";
  1462. my $new_text = $content->{'text'};
  1463. # first find if in a context of no puncutation related
  1464. # modification: code style command or @var, @cite, @math
  1465. # acceptable for punctuation related modifications:
  1466. # asis b dfn emph i slanted sansserif r sc strong t w
  1467. my $current_tested = $content;
  1468. my $no_punctation_munging_command;
  1469. while ($current_tested)
  1470. {
  1471. if (defined($current_tested->{'command'}) and (($style_map{$current_tested->{'command'}} and $style_map{$current_tested->{'command'}}->{'args'} and $style_map{$current_tested->{'command'}}->{'args'}->[0] and $style_map{$current_tested->{'command'}}->{'args'}->[0] eq 'code') or $current_tested->{'command'} eq 'var' or $current_tested->{'command'} eq 'cite' or $current_tested->{'command'} eq 'math'))
  1472. {
  1473. $no_punctation_munging_command = 1;
  1474. last;
  1475. }
  1476. $current_tested = $current_tested->{'parent'};
  1477. }
  1478. # a punctuation at the end of line in a command is treated
  1479. # like a punctuation in plain text, except for @:,
  1480. # accent commands, @dots, 'simple_style' command, and if in
  1481. # a command as found out just above.
  1482. if (!$no_punctation_munging_command and (!defined($content->{'command'}) or ($content->{'command'} ne ':' and $content->{'command'} ne 'accents_commands' and $content->{'command'} ne 'dots') and !$info_default_leaf_command{$content->{'command'}}) and get_conf('frenchspacing') ne 'on' and $new_text =~ /([$info_default_end_sentence_character])([$info_default_after_punctuation_characters]*)(\s*)$/)
  1483. {
  1484. my $spaces = $3;
  1485. if (chomp($new_text))
  1486. {
  1487. $new_text =~ s/(\s*)$/ /;
  1488. }
  1489. else
  1490. {
  1491. # these variables hold the place where the end
  1492. # of line characters are normalized.
  1493. my ($current_start_from, $index_start_from, $close_start_from) = ($current, $index, $close);
  1494. my $only_after_punctuation_characters = 1;
  1495. my $spaces_to_normalize = 0;
  1496. # first find whether there are only
  1497. # after_punctuation_characters followed by spaces
  1498. # and find the place where the
  1499. # after_punctuation_characters end
  1500. my ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current, $index, $close);
  1501. # go through the text as long as there are after_punctuation_characters
  1502. if (!$spaces)
  1503. {
  1504. while (1)
  1505. {
  1506. # !defined($text_next) catches many special
  1507. # commands, like anchor, index. Not sure if
  1508. # it is right or wrong.
  1509. # Also a style_map command never stops
  1510. # the search, so that @emph{ or @strong{
  1511. # begin and end are not taken into account
  1512. if (!defined($current_next) or (!defined($text_next)) or (defined($command_next) and $command_next eq '*') or ($text_next !~ /^[$info_default_after_punctuation_characters]*(\s*)$/ and (!defined($command_next) or !$style_map{$command_next})))
  1513. {
  1514. $only_after_punctuation_characters = 0;
  1515. last;
  1516. }
  1517. my $text_next_kept = $text_next;
  1518. # begin normalizing spaces at the last place
  1519. # where there are after_punctuation_characters
  1520. $current_start_from = $current_next;
  1521. $index_start_from = $index_next;
  1522. $index_start_from = $index_next;
  1523. ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current_next, $index_next, $close_next);
  1524. if ($text_next_kept =~ /^[$info_default_after_punctuation_characters]*\s+$/)
  1525. {
  1526. if (chomp($text_next_kept))
  1527. {
  1528. $spaces_to_normalize = 1;
  1529. }
  1530. last;
  1531. }
  1532. }
  1533. }
  1534. # check if there are only spaces until end of line
  1535. if ($only_after_punctuation_characters and !$spaces_to_normalize)
  1536. {
  1537. while (1)
  1538. {
  1539. # !defined($text_next) catches many special
  1540. # commands, like anchor, index. Not sure if
  1541. # it is right or wrong.
  1542. last if (!defined($current_next) or (!defined($text_next)) or (defined($command_next) and $command_next eq '*'));
  1543. if ($text_next =~ /\S/ and (!defined($command_next) or !$style_map{$command_next}))
  1544. {
  1545. last;
  1546. }
  1547. else
  1548. {
  1549. if (chomp($text_next))
  1550. {
  1551. $spaces_to_normalize = 1;
  1552. last;
  1553. }
  1554. }
  1555. ($current_next, $index_next, $close_next, $text_next, $command_next) = info_default_next ($current_next, $index_next, $close_next);
  1556. }
  1557. }
  1558. if ($spaces_to_normalize)
  1559. {
  1560. # now do the spaces normalization
  1561. info_default_skip_spaces($current_start_from, $index_start_from, $close_start_from);
  1562. my $content = $current_start_from->{'content'}->[$index_start_from];
  1563. $content->{'text'} =~ s/(\s*)$/ /;
  1564. }
  1565. }
  1566. }
  1567. elsif (chomp($new_text))
  1568. {
  1569. $new_text =~ s/(\s*)$/ /;
  1570. }
  1571. $text_added .= $new_text;
  1572. } # ignore spaces outside of paragraphs and preformatted
  1573. elsif ($preformatted or $info_state->{'align_stack'}->[-1]->{'command'} ne 'normal')
  1574. {
  1575. #print STDERR "IN_PREFORMATTED or ALIGN text\n";
  1576. $text_added .= $content->{'text'};
  1577. }
  1578. else
  1579. {
  1580. my $chomped_text = $content->{'text'};
  1581. if ($chomped_text !~ /\S/ and chomp($chomped_text) and !$item_pending)
  1582. {
  1583. if ($in_table_item and $info_state->{'only_spaces'})
  1584. {
  1585. # in a blank_line
  1586. #print STDERR "IN_ITEM ignored: `$content->{'text'}'\n";
  1587. }
  1588. elsif (!$info_state->{'blank_line'} or !$info_state->{'only_spaces'})
  1589. {
  1590. #print STDERR "IN_ADDING_BLANK_LINE because no line before or text before\n";
  1591. $text_added .= "\n";
  1592. }
  1593. else
  1594. {
  1595. #print STDERR "IN_NOT_ADDING_BLANK_LINE\n";
  1596. }
  1597. }
  1598. else
  1599. { # exdent, item not in paragraph nor in preformatted
  1600. #print STDERR "NOWHERE and not end of line (or item_pending) `$content->{'text'}'\n";
  1601. $text_added .= $content->{'text'};
  1602. }
  1603. }
  1604. }
  1605. else
  1606. {
  1607. if (defined($content->{'begin'}))
  1608. {
  1609. $text_added .= $content->{'begin'};
  1610. }
  1611. # command that won't be closed, so the end has to be added
  1612. # here. It should mostly happen for empty style @-commands.
  1613. if (defined($content->{'end'}) and !defined($content->{'content'}))
  1614. {
  1615. $text_added .= $content->{'end'};
  1616. }
  1617. }
  1618. }
  1619. if (!$preformatted and !$in_exdent and $info_state->{'align_stack'}->[-1]->{'command'} eq 'normal' and $in_para)
  1620. {
  1621. # the line_passed returned here are not used, since they are computed
  1622. # below.
  1623. $indentation_done = 1;
  1624. my $dummy_line_passed;
  1625. ($line_char_counter, $pending_spaces_word, $dummy_line_passed, $text_added) = info_default_process_para_text($text_added, $line_char_counter, $pending_spaces_word, $indent_length, $max_column, $in_w, $indent_level * $info_default_indent_length) if ($text_added ne '');
  1626. }
  1627. elsif ($info_state->{'align_stack'}->[-1]->{'command'} ne 'center' and $info_state->{'align_stack'}->[-1]->{'command'} ne 'flushright')
  1628. {
  1629. my $dummy_line_passed;
  1630. ($line_char_counter, $dummy_line_passed, $text_added) = info_default_process_line_text($text_added, $line_char_counter, $indent_length);
  1631. #$indentation_done = 1;
  1632. }
  1633. else
  1634. {
  1635. $line_char_counter += t2h_default_string_width($text_added);
  1636. }
  1637. new_text:
  1638. if ($text_added ne '')
  1639. {
  1640. if ($item_pending and !$line_added_before_item)
  1641. {
  1642. #info_default_skip_spaces($current, $index, $close);
  1643. $item_pending = undef;
  1644. }
  1645. }
  1646. if ($text_added =~ /\S/)
  1647. {
  1648. $in_table_item = 0 if ($in_table_item);
  1649. $info_state->{'blank_line'} = 0;
  1650. }
  1651. $text_added = "\n" . $text_added if ($prepend_newline);
  1652. print STDERR "TEXT_ADDED($indent_length) `$text_added'\n" if ($text_added ne '' and get_conf('DEBUG'));
  1653. #print STDERR "TEXT_ADDED($indent_length) `$text_added'\n";
  1654. # from here, the next cmmand is available
  1655. ($current, $index, $close) = info_default_iterator_next($current, $index, $close);
  1656. my ($line_passed, $end_of_line, $last_line, $text_indented, $blank_line) = info_default_count_lines($text_added, $indent_length, ($indentation_done
  1657. or $info_state->{'align_stack'}->[-1]->{'command'} eq 'center'
  1658. or $info_state->{'align_stack'}->[-1]->{'command'} eq 'flushright'));
  1659. $info_state->{'blank_line'} = 1 if ($blank_line);
  1660. print STDERR "ADDING `$text_indented'\n" if ($text_indented ne '' and get_conf('DEBUG'));
  1661. # only_space is set in all the conditionals
  1662. if ($end_of_line)
  1663. {
  1664. $line_char_counter = 0;
  1665. if ($in_exdent)
  1666. {
  1667. $in_exdent--;
  1668. }
  1669. if ($table_item_line)
  1670. {
  1671. $table_item_line--;
  1672. $in_table_item = 1;
  1673. }
  1674. if (!$table_item_line and !$in_exdent and !$item_pending)
  1675. {
  1676. $indent_length = $indent_level * $info_default_indent_length;
  1677. }
  1678. $info_state->{'blank_line'} = 1 if ($info_state->{'only_spaces'} and ($last_line !~ /\S/));
  1679. $info_state->{'only_spaces'} = 1;
  1680. }
  1681. else
  1682. {
  1683. if ($line_passed)
  1684. {# in that case we added more than one line, the $line_char_counter
  1685. # is reset to the last line length.
  1686. $line_char_counter = t2h_default_string_width($last_line);
  1687. $in_exdent = 0;
  1688. $indent_length = $indent_level * $info_default_indent_length;
  1689. if ($last_line !~ /\S/)
  1690. {
  1691. $info_state->{'only_spaces'} = 1;
  1692. }
  1693. else
  1694. {
  1695. $info_state->{'only_spaces'} = 0;
  1696. }
  1697. }
  1698. else
  1699. {
  1700. $info_state->{'only_spaces'} = 0 if ($last_line =~ /\S/);
  1701. }
  1702. }
  1703. if ($info_state->{'align_stack'}->[-1]->{'command'} eq 'center'
  1704. or $info_state->{'align_stack'}->[-1]->{'command'} eq 'flushright')
  1705. {
  1706. if (defined($current_line))
  1707. {
  1708. $text_added = $current_line . $text_added;
  1709. }
  1710. $text_indented = '';
  1711. $current_line = undef;
  1712. my $spaces_prepended = undef;
  1713. foreach my $line (split /^/, $text_added)
  1714. {
  1715. my $chomped_line = $line;
  1716. if (chomp($chomped_line))
  1717. {
  1718. $line =~ s/^\s*//;
  1719. $line =~ s/\s*$//;
  1720. if (t2h_default_string_width($line) eq 0)
  1721. {
  1722. $spaces_prepended = 0;
  1723. $text_indented .= "\n";
  1724. }
  1725. else
  1726. {
  1727. my $line_width = t2h_default_string_width($line);
  1728. if ($line_width > $max_column)
  1729. {
  1730. $spaces_prepended = 0;
  1731. }
  1732. elsif ($info_state->{'align_stack'}->[-1]->{'command'} eq 'center')
  1733. {
  1734. $spaces_prepended = (($max_column -1 - $line_width) /2);
  1735. }
  1736. else
  1737. {
  1738. $spaces_prepended = ($max_column -1 - $line_width);
  1739. }
  1740. $text_indented .= ' ' x$spaces_prepended . $line ."\n";
  1741. }
  1742. }
  1743. else
  1744. {
  1745. $current_line = $line;
  1746. }
  1747. }
  1748. if (defined ($spaces_prepended) and defined($info_state->{'align_stack'}->[-1]->{'anchors'}))
  1749. {
  1750. while (@{$info_state->{'align_stack'}->[-1]->{'anchors'}})
  1751. {
  1752. my $anchor = shift @{$info_state->{'align_stack'}->[-1]->{'anchors'}};
  1753. $anchor->{'info_offset'} += info_default_byte_count(' ' x$spaces_prepended);
  1754. }
  1755. }
  1756. }
  1757. if ($direntry)
  1758. {
  1759. $info_default_dir_specification .= $text_indented;
  1760. }
  1761. else
  1762. {
  1763. $result .= $text_indented;
  1764. $length += info_default_byte_count($text_indented);
  1765. $all_line_passed += $line_passed;
  1766. }
  1767. }
  1768. return ($length, $result, $all_line_passed);
  1769. }
  1770. sub info_default_open_command($$;$)
  1771. {
  1772. my $state = shift;
  1773. my $command = shift;
  1774. my $additional_entries = shift;
  1775. my $index = 0;
  1776. my $info_state = info_default_get_state($state);
  1777. # index in the parent content list
  1778. $index = scalar(@{$info_state->{'current'}->{'content'}})
  1779. if (defined($info_state->{'current'}->{'content'}));
  1780. my $new_command = {'command' => $command, 'parent' => $info_state->{'current'}, 'index_in_parent' => $index };
  1781. if (defined($additional_entries))
  1782. {
  1783. foreach my $key (keys(%$additional_entries))
  1784. {
  1785. $new_command->{$key} = $additional_entries->{$key};
  1786. }
  1787. }
  1788. push @{$info_state->{'current'}->{'content'}}, $new_command;
  1789. $info_state->{'current'} = $new_command;
  1790. print STDERR "TREE($info_state->{'nr'}): Opened $command\n" if (get_conf('DEBUG'));
  1791. }
  1792. sub info_default_close_command($$;$$$)
  1793. {
  1794. my $state = shift;
  1795. my $command = shift;
  1796. my $begin = shift;
  1797. my $end = shift;
  1798. my $command_entries = shift;
  1799. $state = $Texi2HTML::THISDOC{'state'} if (!defined($state));
  1800. my $info_state = info_default_get_state($state);
  1801. print STDERR "TREE($info_state->{'nr'}): Closing $command\n" if (get_conf('DEBUG'));
  1802. if (!defined($info_state->{'current'}))
  1803. {
  1804. print STDERR "info_state->{'current'} not defined (closing $command)\n";
  1805. }
  1806. elsif (!defined($info_state->{'current'}->{'command'}))
  1807. {
  1808. print STDERR "info_state->{'current'}->{'command'} not defined (closing $command)\n";
  1809. }
  1810. elsif ($command ne $info_state->{'current'}->{'command'})
  1811. {
  1812. print STDERR "Was waiting for $info_state->{'current'}->{'command'} (closing $command)\n";
  1813. }
  1814. #return if $no_close;
  1815. $command_entries->{'begin'} = $begin;
  1816. $command_entries->{'end'} = $end;
  1817. $command_entries->{'line_nr'} = $Texi2HTML::THISDOC{'line_nr'};
  1818. foreach my $key (keys(%$command_entries))
  1819. {
  1820. $info_state->{'current'}->{$key} = $command_entries->{$key}
  1821. if (defined($command_entries->{$key}));
  1822. }
  1823. $info_state->{'current'} = $info_state->{'current'}->{'parent'};
  1824. return info_default_output($info_state)
  1825. if (!defined($info_state->{'current'}->{'command'}));
  1826. return '';
  1827. }
  1828. sub info_default_store_text($$;$$)
  1829. {
  1830. my $state = shift;
  1831. my $text = shift;
  1832. my $command = shift;
  1833. my $text_entries = shift;
  1834. $state = $Texi2HTML::THISDOC{'state'} if (!defined($state));
  1835. my $info_state = info_default_get_state($state);
  1836. return '' if ((!defined($text) or $text eq '') and !defined($command));
  1837. ################################## debug
  1838. my $command_text = '';
  1839. $command_text = "\[$command\]" if (defined($command));
  1840. $command_text .= $text if (defined($text));
  1841. print STDERR "TREE($info_state->{'nr'}) Storing: ${command_text}\n" if (get_conf('DEBUG'));
  1842. ################################## end debug
  1843. $text_entries->{'text'} = $text if (defined($text));
  1844. $text_entries->{'command'} = $command if (defined($command));
  1845. $text_entries->{'parent'} = $info_state->{'current'};
  1846. $text_entries->{'line_nr'} = $Texi2HTML::THISDOC{'line_nr'};
  1847. push @{$info_state->{'current'}->{'content'}}, $text_entries;
  1848. return info_default_output($info_state)
  1849. if (!defined($info_state->{'current'}->{'command'}));
  1850. return '';
  1851. }
  1852. sub info_default_increment_paragraph ($$$;$)
  1853. {
  1854. my $in_format = shift;
  1855. my $parent_format = shift;
  1856. my $info_state = shift;
  1857. my $command = shift;
  1858. if ($in_format)
  1859. {
  1860. $parent_format->{'paragraph_in_format_nr'} = 0 if (!defined($parent_format->{'paragraph_in_format_nr'}));
  1861. $parent_format->{'paragraph_in_format_nr'}++;
  1862. }
  1863. else
  1864. {
  1865. $info_state->{'paragraph_in_element_nr'}++;
  1866. }
  1867. ####################### debug
  1868. $command = 'PARA' if (!defined($command));
  1869. if (0)
  1870. #if (1)
  1871. {
  1872. my $format_info = '';
  1873. if ($in_format)
  1874. {
  1875. $format_info = "format: [$parent_format->{'command'}],$parent_format->{'paragraph_in_format_nr'}"
  1876. }
  1877. print STDERR "INCREMENT_PARA($command) $info_state->{'paragraph_in_element_nr'} $format_info\n";
  1878. }
  1879. ####################### end debug
  1880. }
  1881. sub info_default_begin_format_texi($$$)
  1882. {
  1883. my $command = shift;
  1884. my $line = shift;
  1885. my $state = shift;
  1886. my $info_state = info_default_get_state ($state);
  1887. my ($parent_format, $in_format);
  1888. ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'});
  1889. info_default_increment_paragraph ($in_format, $parent_format, $info_state, $command);
  1890. # remove space in front of center, unless it removes the end of line!
  1891. $line =~ s/^\s*// if ($command eq 'center' and $line =~ /\S/);
  1892. # don't open a format if it is a @def*x command and we are already in the
  1893. # corresponding @def* command
  1894. info_default_open_command($state,$command) unless ($def_map{$command} and $command =~ /x$/ and defined($info_state->{'current'}->{'command'}) and "$info_state->{'current'}->{'command'}x" eq $command);
  1895. return $line;
  1896. }
  1897. sub info_default_begin_style_texi($$$$$)
  1898. {
  1899. my $command = shift;
  1900. my $state = shift;
  1901. my $stack = shift;
  1902. my $real_style_command = shift;
  1903. my $remove_texi = shift;
  1904. info_default_open_command($state,$command)
  1905. unless ($info_default_accent_commands{$command} or exists $things_map{$command}
  1906. or $command =~ /^special_(\w+)_(\d+)$/);
  1907. # if ($real_style_command);
  1908. }
  1909. sub info_default_begin_paragraph_texi($$$)
  1910. {
  1911. my $command = shift;
  1912. my $paragraph_macros = shift;
  1913. my $paragraph_command = shift;
  1914. #print STDERR "begin_paragraph $command\n";
  1915. my $state = shift;
  1916. my $stack = shift;
  1917. info_default_open_command($state,$command);
  1918. foreach my $style_command (@$paragraph_macros)
  1919. {
  1920. #print STDERR "para stack: $style_command->{'style'}\n";
  1921. info_default_open_command($state,$style_command->{'style'});
  1922. }
  1923. }
  1924. sub info_default_simple_command($$$$$)
  1925. {
  1926. my $command = shift;
  1927. my $in_preformatted = shift;
  1928. my $in_math = shift;
  1929. my $line_nr = shift;
  1930. my $state = shift;
  1931. my $result = $simple_map{$command};
  1932. $result = $simple_map_math{$command} if ($in_math and defined($simple_map_math{$command}));
  1933. # discards '-' '|' '/' and ':'. If ':' is associated with a punctuation
  1934. # character it is added to the tree in info_default_colon_command
  1935. return info_default_store_text($state,$result,$command) if ($result ne '');
  1936. return '';
  1937. }
  1938. sub info_default_colon_command($)
  1939. {
  1940. my $punctuation_character = shift;
  1941. if (defined($colon_command_punctuation_characters{$punctuation_character})
  1942. and $punctuation_character =~ /^[$punctuation_characters]$/)
  1943. {
  1944. return info_default_store_text(undef,$colon_command_punctuation_characters{$punctuation_character}, ':');
  1945. }
  1946. else
  1947. {
  1948. return info_default_store_text(undef,$punctuation_character);
  1949. }
  1950. }
  1951. sub info_default_thing_command($$$$$$)
  1952. {
  1953. my $command = shift;
  1954. my $text = shift;
  1955. my $in_preformatted = shift;
  1956. my $in_math = shift;
  1957. my $line_nr = shift;
  1958. my $state = shift;
  1959. my $result = $things_map{$command};
  1960. #return info_default_close_command($state, $command, $result, $text, '');
  1961. return info_default_store_text($state, $result, $command);
  1962. # return $result . $text;
  1963. }
  1964. sub info_default_style($$$$$$$$$$)
  1965. {
  1966. my $style = shift;
  1967. my $command = shift;
  1968. my $text = shift;
  1969. my $args = shift;
  1970. my $no_close = shift;
  1971. my $no_open = shift;
  1972. my $line_nr = shift;
  1973. my $state = shift;
  1974. my $command_stack = shift;
  1975. my $kept_line_nrs = shift;
  1976. my $begin = '';
  1977. my $end = '';
  1978. # note that the $text is always discarded for closed commands
  1979. # the formatting is done right here, and the result is entered as text below.
  1980. if ($info_default_leaf_command{$command})
  1981. {
  1982. my $style_index = 0;
  1983. my @formatted_args = ();
  1984. foreach my $arg (@$args)
  1985. {
  1986. # we don't use style, since we only set 'orig_args' in style_map
  1987. # and not in style_map_pre.
  1988. my $arg_style = $style_map{$command}->{'orig_args'}->[$style_index];
  1989. my $new_state = main::duplicate_formatting_state($state);
  1990. if ($arg_style eq 'normal')
  1991. {
  1992. push @formatted_args, main::substitute_line($arg, "\@$command", $new_state);
  1993. }
  1994. elsif ($arg_style eq 'code')
  1995. {
  1996. $new_state->{'code_style'} = 1;
  1997. push @formatted_args, main::substitute_line($arg, "\@$command", $new_state);
  1998. }
  1999. else
  2000. {
  2001. print STDERR "Unknown arg style($style_index) $arg_style for $command, $state->{'remove_texi'}\n";
  2002. }
  2003. $style_index++;
  2004. }
  2005. $args = \@formatted_args;
  2006. }
  2007. if (defined($style->{'function'}))
  2008. { # in case of an accent, some text is returned here if there are still
  2009. # more accents on the command_stack, otherwise it is put in the tree.
  2010. # Other commands text results are put in the tree below.
  2011. $text = &{$style->{'function'}}($command, $args, $command_stack, $state, $line_nr, $kept_line_nrs);
  2012. }
  2013. elsif ($info_default_leaf_command{$command})
  2014. { # no formatting function but a leaf command, it is just replaced
  2015. # by the formatted argument, and put in the tree below.
  2016. $text = $args->[0];
  2017. }
  2018. if (defined($style->{'begin'}) and !$no_open)
  2019. {
  2020. $begin = $style->{'begin'};
  2021. }
  2022. if (defined($style->{'end'}) and !$no_close)
  2023. {
  2024. $end = $style->{'end'};
  2025. }
  2026. # normal style commands
  2027. unless($special_style{$command} or $info_default_accent_commands{$command} or ($command eq 'hyphenation') or $info_default_leaf_command{$command})
  2028. {
  2029. return info_default_close_command($state, $command, $begin, $end);
  2030. }
  2031. # this is for *ref, images and footnotes text registering and putting
  2032. # in the tree.
  2033. # anchor is already in the tree, from anchor_label.
  2034. if (($special_style{$command} or $info_default_leaf_command{$command}) and $command ne 'anchor')
  2035. {
  2036. return info_default_store_text ($state, $begin.$text.$end, $command);
  2037. }
  2038. # for accents, hyphenation and anchor
  2039. # (though the result for anchor is always an empty string).
  2040. return $begin.$text.$end;
  2041. }
  2042. sub info_default_header ()
  2043. {
  2044. return $Texi2HTML::THISDOC{'info_header'} if (defined($Texi2HTML::THISDOC{'info_header'}));
  2045. # $Texi2HTML::THISDOC{'program'}
  2046. my $input_basename = $Texi2HTML::THISDOC{'input_file_name'};
  2047. $input_basename =~ s/^.*\///;
  2048. $input_basename = $STDIN_DOCU_NAME if ($input_basename eq '-');
  2049. my $output_basename = $Texi2HTML::THISDOC{'filename'}->{'top'};
  2050. $output_basename =~ s/^.*\///;
  2051. my $result = "This is $output_basename, produced by makeinfo version 4.13 from $input_basename. ";
  2052. my $dummy;
  2053. ($dummy, $dummy, $dummy, $result) = info_default_process_para_text($result, 0, {'spaces' => ''}, undef, get_conf('FILLCOLUMN'));
  2054. $result .= "\n\n";
  2055. $result .= "$Texi2HTML::THISDOC{'copying_comment'}";
  2056. if ($info_default_dir_specification)
  2057. {
  2058. $result .= "$info_default_dir_specification\n";
  2059. }
  2060. $Texi2HTML::THISDOC{'info_header'} = $result;
  2061. return $result;
  2062. }
  2063. sub info_default_print_page_head($)
  2064. {
  2065. my $fh = shift;
  2066. my $header = info_default_header();
  2067. print $fh "".$header;
  2068. my $state = $Texi2HTML::THISDOC{'state'};
  2069. my $info_state = info_default_get_state ($state);
  2070. $info_state->{'offset_in_file'} += info_default_byte_count($header);
  2071. $info_state->{'blank_line'} = 1 if ($Texi2HTML::THISDOC{'copying_comment'} eq '');
  2072. }
  2073. sub info_default_parent_format($)
  2074. {
  2075. my $parent_format = shift;
  2076. my $in_format = 0;
  2077. while (1)
  2078. {
  2079. if (defined($parent_format->{'command'}) and $info_default_format{$parent_format->{'command'}})
  2080. {
  2081. $in_format = 1;
  2082. last;
  2083. }
  2084. last if (!defined($parent_format->{'parent'}));
  2085. $parent_format = $parent_format->{'parent'};
  2086. }
  2087. return ($parent_format, $in_format);
  2088. }
  2089. sub info_default_paragraph($$$$$$$$$$$$)
  2090. {
  2091. my $text = shift;
  2092. my $align = shift;
  2093. my $indent = shift;
  2094. my $paragraph_command = shift;
  2095. my $paragraph_command_formatted = shift;
  2096. my $paragraph_number = shift;
  2097. my $format = shift;
  2098. my $item_nr = shift;
  2099. my $enumerate_style = shift;
  2100. my $number = shift;
  2101. my $command_stack_at_end = shift;
  2102. my $command_stack_at_begin = shift;
  2103. my $top_stack = '';
  2104. $top_stack = $command_stack_at_begin->[-1] if (scalar (@$command_stack_at_begin));
  2105. my $state = $Texi2HTML::THISDOC{'state'};
  2106. my $info_state = info_default_get_state ($state);
  2107. my ($parent_format, $in_format);
  2108. ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'}->{'parent'});
  2109. info_default_increment_paragraph ($in_format, $parent_format, $info_state);
  2110. my $additional_args = {'top_stack' => $top_stack, 'parent_format' => $parent_format};
  2111. $additional_args->{'paragraph_in_element_nr'} = ($info_state->{'paragraph_in_element_nr'} - 1) if (!$in_format);
  2112. return info_default_close_command(undef, 'paragraph', undef, undef, $additional_args);
  2113. }
  2114. # currently not used, but could be used if info_default_preformatted
  2115. # return something that is not 'false', for example spaces, though we
  2116. # want the preformatted to be ignored. Though it is not sure that if there
  2117. # are spaces we want to ignore the preformatted.
  2118. sub info_default_empty_preformatted($)
  2119. {
  2120. my $text = shift;
  2121. my $result = info_default_preformatted($text, undef, undef, undef, undef,
  2122. undef, undef, undef, undef, undef, undef, undef);
  2123. return 0;
  2124. }
  2125. sub info_default_preformatted($$$$$$$$$$$$)
  2126. {
  2127. my $text = shift;
  2128. my $pre_style = shift;
  2129. my $class = shift;
  2130. my $leading_command = shift;
  2131. my $leading_command_formatted = shift;
  2132. my $preformatted_number = shift;
  2133. my $format = shift;
  2134. my $item_nr = shift;
  2135. my $enumerate_style = shift;
  2136. my $number = shift;
  2137. my $command_stack_at_end = shift;
  2138. my $command_stack_at_begin = shift;
  2139. return info_default_close_command(undef, 'preformatted');
  2140. }
  2141. sub info_default_node_line($$)
  2142. {
  2143. my $element = shift;
  2144. my $info_state = shift;
  2145. my $outfile = $Texi2HTML::THISDOC{'filename'}->{'top'};
  2146. $outfile = $STDOUT_DOCU_NAME if ($outfile eq '-');
  2147. my $result = "\x{1F}\nFile: $outfile, Node: $element->{'text'}";
  2148. if (defined($element->{'NodeNext'}))
  2149. { # This is not translatable
  2150. $result .= ", Next: $element->{'NodeNext'}->{'text'}";
  2151. }
  2152. if (defined($element->{'NodePrev'}))
  2153. {
  2154. $result .= ", Prev: $element->{'NodePrev'}->{'text'}";
  2155. }
  2156. if (defined($element->{'NodeUp'}))
  2157. {
  2158. $result .= ", Up: $element->{'NodeUp'}->{'text'}";
  2159. }
  2160. $result .= "\n\n";
  2161. # the line_count is ahead from the number of lines by one.
  2162. $info_state->{'line_count'} = 3;
  2163. $info_state->{'offset_in_file'} += info_default_byte_count($result);
  2164. $info_state->{'blank_line'} = 1;
  2165. return $result;
  2166. }
  2167. sub info_default_element_heading($$$$$$$$$$$$)
  2168. {
  2169. my $element = shift;
  2170. my $command = shift;
  2171. my $texi_line = shift;
  2172. my $line = shift;
  2173. my $in_preformatted = shift;
  2174. my $one_section = shift;
  2175. my $element_heading = shift;
  2176. my $first_in_page = shift;
  2177. my $is_top = shift;
  2178. my $previous_is_top = shift;
  2179. my $command_line = shift;
  2180. my $element_id = shift;
  2181. my $new_element = shift;
  2182. my $state = $Texi2HTML::THISDOC{'state'};
  2183. my $info_state = info_default_get_state ($state);
  2184. # FIXME use $element or $Texi2HTML::THIS_ELEMENT? Main program should
  2185. # ensure they are the same.
  2186. if ($new_element and ($element ne $new_element and $element->{'node'}))
  2187. {
  2188. die "There is a new element, but element `$element->{'texi'}' is not the new element\n";
  2189. }
  2190. # FIXME
  2191. # non node element may appear if the element appears before the first
  2192. # node/section element. For example `element not associated with a node'
  2193. # won't be associated with a node.
  2194. # @unnumbered element not associated with a node
  2195. # @node Top
  2196. # @top Top element
  2197. if (!$element->{'node'})
  2198. {
  2199. return &$heading($element, $command, $texi_line, $line, $in_preformatted, $one_section, $element_heading);
  2200. }
  2201. my $before = '';
  2202. $element->{'info_offset'} = $info_state->{'offset_in_file'};
  2203. push @{$info_state->{'pending_tags'}}, $element;
  2204. my $result = info_default_node_line($element, $info_state);
  2205. $info_default_footnote_index = 0;
  2206. $info_default_current_node = $element;
  2207. return $before.$result;
  2208. }
  2209. sub info_default_heading($$$$$;$$)
  2210. {
  2211. my $element = shift;
  2212. my $command = shift;
  2213. my $texi_line = shift;
  2214. my $line = shift;
  2215. my $in_preformatted = shift;
  2216. my $one_section = shift;
  2217. my $element_heading = shift;
  2218. die "Heading called for a node\n" if ($element->{'node'});
  2219. my $state = $Texi2HTML::THISDOC{'state'};
  2220. my $info_state = info_default_get_state ($state);
  2221. $info_state->{'paragraph_in_element_nr'} = 0;
  2222. if (!defined($element->{'texi'}))
  2223. {
  2224. main::msg_debug("for $element, element->{'texi'} not defined, texi_line: $texi_line");
  2225. }
  2226. elsif (!defined($element->{'text'}))
  2227. {
  2228. main::msg_debug("for $element, $element->{'texi'}, element->{'text'} not defined");
  2229. }
  2230. return '' if ($element->{'tag'} eq 'part');
  2231. my $text = "$element->{'text'}";
  2232. # when @top is empty, use settitle
  2233. $text = $Texi2HTML::THISDOC{'settitle'} if (!length($text) and $element->{'tag'} eq 'top' and defined ($Texi2HTML::THISDOC{'settitle'}) and length($Texi2HTML::THISDOC{'settitle'}));
  2234. my $result = &$heading_text ("\@$command", $text, $element->{'level'});
  2235. $result .= "\n";
  2236. return info_default_store_text($state, $result, $command, {'heading_command' => 1});
  2237. }
  2238. sub info_default_normal_text($$$$$$$;$)
  2239. {
  2240. my @initial_args = @_;
  2241. my $text = shift;
  2242. my $in_raw_text = shift; # remove_texi
  2243. my $in_preformatted = shift;
  2244. my $in_code = shift;
  2245. my $in_math = shift;
  2246. my $in_simple = shift;
  2247. my $style_stack = shift;
  2248. my $state = shift;
  2249. # This is always done here since it is not done in t2h_utf8_normal_text
  2250. $text = uc($text) if (in_cmd($style_stack, 'var'));
  2251. # ENCODING_NAME should be defined, but maybe
  2252. # not when parsing commands in first or second pass, and removing texi
  2253. # like what is done for @setfilename.
  2254. if (get_conf('ENABLE_ENCODING') and defined(get_conf('ENCODING_NAME')) and (get_conf('ENCODING_NAME') eq 'utf-8') and get_conf('USE_UNICODE'))
  2255. {
  2256. $text = &t2h_utf8_normal_text(@initial_args);
  2257. }
  2258. else
  2259. {
  2260. #print STDERR "info_default_normal_text $text $in_preformatted $in_code \n";
  2261. $text = uc($text) if (in_cmd($style_stack, 'sc'));
  2262. if (! $in_code and !$in_preformatted)
  2263. {
  2264. $text =~ s/---/\x{1F}/g;
  2265. $text =~ s/--/-/g;
  2266. $text =~ s/\x{1F}/--/g;
  2267. $text =~ s/``/"/g;
  2268. $text =~ s/\'\'/"/g;
  2269. }
  2270. }
  2271. # accented characters are not handled as normal text, but when the last
  2272. # accent command on the stack is closed.
  2273. if ($style_stack and @$style_stack and $info_default_accent_commands{$style_stack->[-1]})
  2274. {
  2275. return $text;
  2276. }
  2277. #print STDERR "NORMAL\n";
  2278. return info_default_store_text($state,$text);
  2279. }
  2280. # this is not called in preformatted
  2281. sub info_default_empty_line($$)
  2282. {
  2283. my $text = shift;
  2284. my $state = shift;
  2285. #ignore the line if it just follows a deff
  2286. #return '' if ($state->{'deff_line'});
  2287. return info_default_store_text($state,$text);
  2288. # return '';
  2289. }
  2290. # change interface?
  2291. sub info_default_anchor_label($$$$)
  2292. {
  2293. my $id = shift;
  2294. my $anchor_text = shift;
  2295. my $anchor_reference = shift;
  2296. my $in_special_region = shift;
  2297. return '' if ($in_special_region);
  2298. #print STDERR "Storing anchor $anchor_reference->{'text'}\n";
  2299. main::line_warn(__("anchor outside of any node, it won't be registered"), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node));
  2300. return info_default_store_text(undef,undef,'anchor',{'anchor_reference' => $anchor_reference});
  2301. }
  2302. sub info_default_acronym_like($$$$$$)
  2303. {
  2304. my $command = shift;
  2305. my $acronym_texi = shift;
  2306. my $acronym_text = shift;
  2307. my $with_explanation = shift;
  2308. my $explanation_lines = shift;
  2309. my $explanation_text = shift;
  2310. my $explanation_simply_formatted = shift;
  2311. if ($with_explanation)
  2312. {
  2313. return "$acronym_text ($explanation_text)";
  2314. }
  2315. else
  2316. {
  2317. return "$acronym_text";
  2318. }
  2319. }
  2320. sub info_default_print_page_foot($)
  2321. {
  2322. my $fh = shift;
  2323. my $state = $Texi2HTML::THISDOC{'state'};
  2324. my $info_state = info_default_get_state ($state);
  2325. my $indirect = 0;
  2326. if (!defined ($info_state->{'pending_tags'}))
  2327. { # i18n
  2328. main::document_warn ("Document without nodes.");
  2329. }
  2330. else
  2331. {
  2332. $indirect = 1 if ($info_default_out_file_nr > 1);
  2333. if ($indirect)
  2334. {
  2335. close ($Texi2HTML::THISDOC{'FH'});
  2336. unless (rename ("$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'}", "$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'}-1"))
  2337. {
  2338. main::document_warn ("Rename $Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'} failed: $!");
  2339. }
  2340. my $INDIRECT = main::open_out("$Texi2HTML::THISDOC{'destination_directory'}$Texi2HTML::THISDOC{'filename'}->{'top'}");
  2341. print $INDIRECT "".info_default_header();
  2342. print $INDIRECT "\x{1F}\nIndirect:";
  2343. foreach my $indirect (@info_default_pending_indirect)
  2344. {
  2345. print $INDIRECT "\n$indirect->{'file'}: $indirect->{'offset'}";
  2346. }
  2347. $fh = $INDIRECT;
  2348. }
  2349. # makeinfo seems to add systematically an additional \n, done just below
  2350. print $fh "\n\x{1F}\nTag Table:\n";
  2351. if ($indirect)
  2352. {
  2353. print $fh "(Indirect)\n";
  2354. }
  2355. my $Top_seen;
  2356. foreach my $element (@{$info_state->{'pending_tags'}})
  2357. {
  2358. my $prefix;
  2359. $prefix = 'Node' if ($element->{'node'});
  2360. $prefix = 'Ref' if ($element->{'anchor'} or $element->{'float'});
  2361. print $fh "$prefix: $element->{'text'}\x{7F}$element->{'info_offset'}\n";
  2362. $Top_seen = 1 if ($element->{'text'} =~ /^top$/i);
  2363. }
  2364. if (!$Top_seen)
  2365. {# i18n
  2366. main::document_warn ("Document without Top node.");
  2367. }
  2368. print $fh "\x{1F}\nEnd Tag Table\n";
  2369. }
  2370. # IN_ENCODING is the documentencoding transformed to the encoding names
  2371. # usually seen in html. This is what the info readers should understand.
  2372. my $coding = get_conf('IN_ENCODING');
  2373. $coding = get_conf('documentencoding') if (!defined($coding));
  2374. if (defined($coding))
  2375. {
  2376. print $fh "\n\x{1F}\nLocal Variables:\ncoding: $coding\nEnd:\n";
  2377. }
  2378. }
  2379. sub info_default_print_Top_footer($$$)
  2380. {
  2381. my $fh = shift;
  2382. my $end_page = shift;
  2383. my $element = shift;
  2384. if ($end_page)
  2385. {
  2386. &$print_page_foot($fh);
  2387. }
  2388. info_default_end_section($fh, $end_page, $element);
  2389. }
  2390. sub info_default_footnote_texi($$$)
  2391. {
  2392. my $text = shift;
  2393. my $state = shift;
  2394. my $style_stack = shift;
  2395. unless ($state->{'outside_document'} or (defined($state->{'multiple_pass'}) and $state->{'multiple_pass'} > 0))
  2396. {
  2397. $info_default_footnote_index++;
  2398. }
  2399. my $footnote_number = $info_default_footnote_index;
  2400. $footnote_number = $NO_NUMBER_FOOTNOTE_SYMBOL if (!get_conf('NUMBER_FOOTNOTES'));
  2401. return "($footnote_number) $text";
  2402. #return undef;
  2403. }
  2404. sub info_default_print_section
  2405. {
  2406. my $fh = shift;
  2407. my $first_in_page = shift;
  2408. my $previous_is_top = shift;
  2409. my $element = shift;
  2410. my $nw = main::print_lines($fh);
  2411. my $state = $Texi2HTML::THISDOC{'state'};
  2412. my $info_state = info_default_get_state ($state);
  2413. if (!$info_state->{'blank_line'})
  2414. {
  2415. my $end = "\n";
  2416. $info_state->{'offset_in_file'} += info_default_byte_count($end);
  2417. $info_state->{'line_count'}++;
  2418. print $fh "$end";
  2419. }
  2420. if (@info_default_pending_footnotes)
  2421. {
  2422. my $footnote_text;
  2423. my $footnote_element;
  2424. if (get_conf('footnotestyle') eq 'separate')
  2425. {
  2426. my $node_ref = $info_default_current_node;
  2427. # thee is a warning when processing the footnote, like
  2428. # "Footnote defined without parent node"
  2429. $node_ref = {'text' => 'no node', 'file' => ''} if (!defined($node_ref));
  2430. $footnote_element = { 'NodeUp' => $node_ref,
  2431. 'text' => $node_ref->{'text'} . "-Footnotes",
  2432. 'file' => $node_ref->{'file'},
  2433. 'info_offset' => $info_state->{'offset_in_file'},
  2434. 'node' => 1,
  2435. };
  2436. $footnote_element->{'element_ref'} = $footnote_element;
  2437. push @{$info_state->{'pending_tags'}}, $footnote_element;
  2438. $footnote_text = info_default_node_line($footnote_element, $info_state);
  2439. }
  2440. else
  2441. { # FIXME i18n?
  2442. $footnote_text = " ---------- Footnotes ----------\n\n";
  2443. $info_state->{'offset_in_file'} += info_default_byte_count($footnote_text);
  2444. $info_state->{'line_count'} += 2;
  2445. #print STDERR "MMMMMMMMMMMMMMMMMM $info_state->{'line_count'}\n";
  2446. }
  2447. while (@info_default_pending_footnotes)
  2448. {
  2449. #push @info_default_pending_footnotes, [$lines, $footnote_text, ${info_default_footnote_index}, $node_name, $footnote_info_state];
  2450. my $footnote = shift @info_default_pending_footnotes;
  2451. my $foot_nr = $footnote->{'footnote_index'};
  2452. my $node_name = $footnote->{'node_name'};
  2453. my $lines = $footnote->{'lines'};
  2454. push @{$info_state->{'pending_tags'}}, {'anchor' => 1, 'text' => "${node_name}-Footnote-${foot_nr}", 'info_offset' => $info_state->{'offset_in_file'} };
  2455. my $footnote_info_state = $footnote->{'footnote_info_state'};
  2456. my $footnote_result = shift @{$lines};
  2457. # this is used to keep track of the size when there were
  2458. # leading spaces that will be removed below. This is only used
  2459. # to get the difference, the value itself is not of use.
  2460. my $initial_length = info_default_byte_count($footnote_result);
  2461. $footnote_result =~ s/^\s*//;
  2462. #$footnote_result = " ($foot_nr) " . $footnote_result;
  2463. $footnote_result = ' ' x get_conf('paragraphindent') . $footnote_result;
  2464. foreach my $footnote_pending_tags(@{$footnote_info_state->{'pending_tags'}})
  2465. {
  2466. $footnote_pending_tags->{'info_offset'} += $info_state->{'offset_in_file'} + info_default_byte_count($footnote_result) - $initial_length;
  2467. push @{$info_state->{'pending_tags'}}, $footnote_pending_tags;
  2468. }
  2469. foreach my $footnote_pending_index_entry(@{$footnote_info_state->{'pending_index_entries'}})
  2470. {
  2471. #print STDERR "TTTTTTTTTTT($footnote_pending_index_entry->{'index_entry_reference'}->{'entry'}) $footnote_pending_index_entry->{'line_nr'} $info_state->{'line_count'}\n";
  2472. $footnote_pending_index_entry->{'line_nr'} += $info_state->{'line_count'};
  2473. $footnote_pending_index_entry->{'index_entry_reference'}->{'real_element'} = $footnote_element if (get_conf('footnotestyle') eq 'separate');
  2474. }
  2475. my $line;
  2476. while (@$lines)
  2477. {
  2478. $line = shift @$lines;
  2479. $footnote_result .= $line;
  2480. }
  2481. my ($line_passed, $end_of_line, $last_line, $text_indented, $blank_line) = info_default_count_lines($footnote_result);
  2482. if ($line_passed == 0)
  2483. {# certainly out of paragraph commands
  2484. $footnote_result =~ s/\s*$//;
  2485. $footnote_result .= "\n";
  2486. $line_passed = 1;
  2487. }
  2488. unless (($last_line !~ /\S/ and $end_of_line) or ($blank_line))
  2489. {
  2490. $footnote_result .= "\n";
  2491. $line_passed += 1;
  2492. }
  2493. $info_state->{'offset_in_file'} += info_default_byte_count($footnote_result);
  2494. $info_state->{'line_count'} += $line_passed;
  2495. $footnote_text .= $footnote_result;
  2496. }
  2497. print $fh "$footnote_text";
  2498. }
  2499. }
  2500. sub info_default_end_section($$$)
  2501. {
  2502. my $fh = shift;
  2503. my $end_foot_navigation = shift;
  2504. my $element = shift;
  2505. my $state = $Texi2HTML::THISDOC{'state'};
  2506. my $info_state = info_default_get_state ($state);
  2507. if (defined(get_conf('SPLIT_SIZE')) and
  2508. $info_state->{'offset_in_file'} > ($info_default_out_file_nr) * get_conf('SPLIT_SIZE'))
  2509. {
  2510. if ($info_default_out_file_nr == 1)
  2511. { # push also the first node, which is always the first pending_tags
  2512. push @info_default_pending_indirect, {'file'=>"$Texi2HTML::THISDOC{'filename'}->{'top'}-$info_default_out_file_nr", 'offset' => $info_state->{'pending_tags'}->[0]->{'info_offset'} };
  2513. }
  2514. $info_default_out_file_nr++;
  2515. # these file descriptors leak, but this allows the user to write a
  2516. # foot navigation himself, otherwise he would write on a closed file
  2517. # descriptor
  2518. #close($Texi2HTML::THISDOC{'FH'});
  2519. if (!$end_foot_navigation)
  2520. {
  2521. main::open_out_file("$Texi2HTML::THISDOC{'filename'}->{'top'}-$info_default_out_file_nr");
  2522. #print STDERR "X-$info_default_out_file_nr: $info_state->{'offset_in_file'}\n";
  2523. &$print_page_head($Texi2HTML::THISDOC{'FH'});
  2524. push @info_default_pending_indirect, {'file'=>"$Texi2HTML::THISDOC{'filename'}->{'top'}-$info_default_out_file_nr", 'offset' => $info_state->{'offset_in_file'}};
  2525. }
  2526. }
  2527. }
  2528. sub info_default_one_section($$)
  2529. {
  2530. my $fh = shift;
  2531. my $element = shift;
  2532. &$print_section($fh, 1, 0, $element);
  2533. &$print_page_foot($fh);
  2534. }
  2535. sub info_default_begin_special_region($$$)
  2536. {
  2537. my $region = shift;
  2538. my $state = shift;
  2539. my $lines = shift;
  2540. my $info_state = info_default_get_state ($state);
  2541. # reset paragraph_in_element_nr if out ofdocument formatting
  2542. if ($state->{'outside_document'})
  2543. {
  2544. $info_state->{'paragraph_in_element_nr'} = 0;
  2545. }
  2546. }
  2547. sub info_default_end_special_region($$$)
  2548. {
  2549. my $region = shift;
  2550. my $state = shift;
  2551. my $text = shift;
  2552. my $info_state = info_default_get_state ($state);
  2553. my $end = '';
  2554. if (!$info_state->{'blank_line'})
  2555. {
  2556. $end = "\n";
  2557. $info_state->{'offset_in_file'} += info_default_byte_count($end);
  2558. }
  2559. return $text.$end;
  2560. }
  2561. sub info_default_menu_link($$$$$$$$)
  2562. {
  2563. my $entry = shift;
  2564. my $state = shift;
  2565. my $href = shift;
  2566. my $node = shift;
  2567. my $title = shift;
  2568. my $ending = shift;
  2569. my $has_title = shift;
  2570. my $command_stack = shift;
  2571. my $preformatted = shift;
  2572. $title = '' unless ($has_title);
  2573. $title .= ':' if ($title ne '');
  2574. my $result = "$MENU_SYMBOL$title$node$ending";
  2575. return info_default_store_text($state,$result,'menu_entry');
  2576. }
  2577. # not used, menu is a normal preformatted command
  2578. #sub info_default_menu_command($$$)
  2579. #{
  2580. # my $format = shift;
  2581. # my $text = shift;
  2582. # my $in_preformatted = shift;
  2583. # return info_default_close_command(undef, $format, "* Menu:\n", undef, "\n");
  2584. #}
  2585. sub info_default_complex_format($$)
  2586. {
  2587. my $name = shift;
  2588. my $text = shift;
  2589. my ($begin, $end);
  2590. if ($name eq 'menu')
  2591. {
  2592. main::line_warn(__("\@menu before first node"), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node));
  2593. $begin = "* Menu:\n\n";
  2594. }
  2595. elsif ($name eq 'direntry')
  2596. {
  2597. main::line_warn(__("\@direntry after first node"), $Texi2HTML::THISDOC{'line_nr'}) if (defined($info_default_current_node));
  2598. $begin = "START-INFO-DIR-ENTRY\n";
  2599. $end = "END-INFO-DIR-ENTRY\n";
  2600. }
  2601. return info_default_close_command(undef, $name, $begin, $end);
  2602. }
  2603. sub info_default_quotation($$$$$)
  2604. {
  2605. my $command = shift;
  2606. my $text = shift;
  2607. my $argument_text = shift;
  2608. my $argument_text_texi = shift;
  2609. my $authors = shift;
  2610. my $attribution;
  2611. if ($authors)
  2612. {
  2613. $attribution = '';
  2614. foreach my $author (@$authors)
  2615. {
  2616. my $author_texi = $author->{'author_texi'};
  2617. chomp($author_texi);
  2618. $attribution .= gdt("\@center --- \@emph{{author}}\n", {'author' => $author_texi}, {'duplicate' => 1, 'allow_paragraph' => 1});
  2619. }
  2620. }
  2621. return info_default_close_command(undef, $command, undef, $attribution);
  2622. }
  2623. sub info_default_misc_commands($$$$$)
  2624. {
  2625. my $command = shift;
  2626. my $line = shift;
  2627. my $args = shift;
  2628. my $stack = shift;
  2629. my $state = shift;
  2630. info_default_store_text($state,undef,$command) if ($command eq 'exdent' or $command eq 'noindent' or $command eq 'indent');
  2631. return ($command, $line, undef);
  2632. }
  2633. sub info_default_external_ref($$$$$$$$$)
  2634. {
  2635. my $type = shift;
  2636. my $section = shift;
  2637. my $book = shift;
  2638. my $file = shift;
  2639. my $href = shift;
  2640. my $cross_ref = shift;
  2641. my $args_texi = shift;
  2642. my $formatted_args = shift;
  2643. my $node = shift;
  2644. return info_default_inforef($formatted_args) if ($type eq 'inforef');
  2645. return info_default_normal_reference($type, $formatted_args);
  2646. }
  2647. sub info_default_internal_ref($$$$$$$$)
  2648. {
  2649. my $type = shift;
  2650. my $href = shift;
  2651. my $short_name = shift;
  2652. my $name = shift;
  2653. my $is_section = shift;
  2654. my $args_texi = shift;
  2655. my $formatted_args = shift;
  2656. my $element = shift;
  2657. $formatted_args->[1] = $name if ($element->{'float'} and (!defined($formatted_args->[1]) or $formatted_args->[1] eq ''));
  2658. return info_default_inforef($formatted_args) if ($type eq 'inforef');
  2659. return info_default_normal_reference($type, $formatted_args);
  2660. }
  2661. sub info_default_normal_reference($$)
  2662. {
  2663. my $command = shift;
  2664. my $formatted_args = shift;
  2665. for (my $i = 0; $i < scalar(@$formatted_args); $i++)
  2666. {
  2667. $formatted_args->[$i] = undef if (defined($formatted_args->[$i]) and
  2668. $formatted_args->[$i] =~ /^\s*$/);
  2669. }
  2670. my $node = $formatted_args->[0];
  2671. # an error, should trigger the message: Undefined node `' in @ref.
  2672. # avoid undef value and use an empty string instead.
  2673. $node = '' if (!defined($node));
  2674. my $name = $formatted_args->[1];
  2675. $name = $formatted_args->[2] if (!defined($name));
  2676. my $file = $formatted_args->[3];
  2677. $file = '' if (!defined($file) and defined($formatted_args->[4]));
  2678. $name = $node if (!defined($name) and defined($file));
  2679. my $result = '*note ';
  2680. $result = '*Note ' if ($command eq 'xref');
  2681. if (defined($name))
  2682. {
  2683. $result .= "${name}: ";
  2684. $result .= "($file)" if (defined($file));
  2685. $result .= "$node";
  2686. $result .= '.' if ($command eq 'pxref');
  2687. }
  2688. else
  2689. {
  2690. $result .= "${node}::";
  2691. }
  2692. return $result;
  2693. }
  2694. sub info_default_inforef($)
  2695. {
  2696. my $formatted_args = shift;
  2697. return info_default_normal_reference('ref', [$formatted_args->[0], $formatted_args->[1], undef, $formatted_args->[2], 'dumb manual name']);
  2698. }
  2699. sub info_default_image_files($$$$)
  2700. {
  2701. my $base = shift;
  2702. my $extension = shift;
  2703. my $texi_base = shift;
  2704. my $texi_extension = shift;
  2705. my @files = ();
  2706. return @files if (!defined($base) or ($base eq ''));
  2707. if (defined($extension) and ($extension ne ''))
  2708. {
  2709. push @files, ["${base}$extension", "${texi_base}$extension"];
  2710. push @files, ["$base.$extension", "$texi_base.$extension"];
  2711. }
  2712. foreach my $ext (@IMAGE_EXTENSIONS)
  2713. {
  2714. push @files, ["$base.$ext", "$texi_base.$ext"];
  2715. }
  2716. return @files;
  2717. }
  2718. sub info_default_image($$$$$$$$$$$$$$$$$)
  2719. {
  2720. my $file = shift;
  2721. my $base = shift;
  2722. my $preformatted = shift;
  2723. my $file_name = shift;
  2724. my $alt = shift;
  2725. my $width = shift;
  2726. my $height = shift;
  2727. my $raw_alt = shift;
  2728. my $extension = shift;
  2729. my $working_dir = shift;
  2730. my $file_path = shift;
  2731. my $in_paragraph = shift;
  2732. my $file_locations = shift;
  2733. my $base_simple_format = shift;
  2734. my $extension_simple_format = shift;
  2735. my $file_name_simple_format = shift;
  2736. my $line_nr = shift;
  2737. my $txt_path;
  2738. my $found_file;
  2739. my @extensions = @IMAGE_EXTENSIONS;
  2740. if (defined($extension) and ($extension ne ''))
  2741. {
  2742. unshift @extensions, ".$extension";
  2743. unshift @extensions, "$extension";
  2744. }
  2745. else
  2746. {
  2747. $extension = undef;
  2748. }
  2749. my $file_found_index = undef;
  2750. my $file_index = 0;
  2751. foreach my $file_location (@$file_locations)
  2752. {
  2753. my ($file_located, $path, $file_simple_format) = @$file_location;
  2754. my $extension = shift @extensions;
  2755. if (defined($path))
  2756. {
  2757. if ($extension eq 'txt' and !defined($txt_path))
  2758. {
  2759. $txt_path = $path;
  2760. }
  2761. elsif (!defined($found_file))
  2762. {
  2763. $found_file = [$file_located, $extension, $file_simple_format];
  2764. $file_found_index = $file_index;
  2765. }
  2766. }
  2767. $file_index++;
  2768. }
  2769. my $text;
  2770. if (defined($txt_path))
  2771. {
  2772. if (open(TXT, "<$txt_path"))
  2773. {
  2774. my $in_encoding = get_conf('IN_ENCODING');
  2775. if (defined($in_encoding) and get_conf('USE_UNICODE'))
  2776. {
  2777. binmode(TXT, ":encoding($in_encoding)");
  2778. }
  2779. $text='[' if ($in_paragraph or $preformatted);
  2780. while (my $img_txt = <TXT>)
  2781. {
  2782. $text .= $img_txt;
  2783. }
  2784. # remove last end of line
  2785. chomp ($text);
  2786. $text .= ']' if ($in_paragraph or $preformatted);
  2787. close(TXT);
  2788. }
  2789. else
  2790. {
  2791. main::line_warn (sprintf(__("\@image file `%s' unreadable: %s"), $txt_path, $!), $line_nr);
  2792. }
  2793. }
  2794. elsif (!defined($found_file))
  2795. {
  2796. main::line_warn (sprintf(__("Cannot find \@image file `%s.txt'"), $base), $line_nr);
  2797. }
  2798. if (defined($found_file) and (!defined($extension) or $file_found_index <= 1))
  2799. {
  2800. my $filename = $found_file->[2];
  2801. $filename =~ s/\\/\\\\/g;
  2802. $filename =~ s/\"/\\\"/g;
  2803. my $result = "\x{00}\x{08}[image src=\"$filename\"";
  2804. if (defined($alt))
  2805. {
  2806. $alt =~ s/\\/\\\\/g;
  2807. $alt =~ s/\"/\\\"/g;
  2808. $result .= " alt=\"$alt\"";
  2809. }
  2810. if (defined($text))
  2811. {
  2812. $text =~ s/\\/\\\\/g;
  2813. $text =~ s/\"/\\\"/g;
  2814. $result .= " text=\"$text\"";
  2815. }
  2816. $result .= "\x{00}\x{08}]";
  2817. return $result;
  2818. }
  2819. return $text if (defined($text));
  2820. return '';
  2821. }
  2822. sub info_default_printindex($$)
  2823. {
  2824. my $index_name = shift;
  2825. my $printindex = shift;
  2826. %info_default_index_entries_counts = ();
  2827. return info_default_store_text(undef,t2h_GPL_default_printindex($index_name,$printindex),'printindex');
  2828. }
  2829. sub info_default_print_index($$)
  2830. {
  2831. my $text = shift;
  2832. my $name = shift;
  2833. my $state = $Texi2HTML::THISDOC{'state'};
  2834. my $info_state = info_default_get_state ($state);
  2835. my $before = '';
  2836. if (!$info_state->{'blank_line'})
  2837. {
  2838. $before = "\n";
  2839. }
  2840. return $before if (!defined($text));
  2841. my $result = "\x{00}\x{08}[index\x{00}\x{08}]\n* Menu:\n\n" .$text."\n";
  2842. return $before.$result;
  2843. }
  2844. sub info_default_index_letter($$$)
  2845. {
  2846. my $letter = shift;
  2847. my $id = shift;
  2848. my $text = shift;
  2849. return $text;
  2850. }
  2851. sub info_default_index_entry_label($$$$$$$$$)
  2852. {
  2853. my $identifier = shift;
  2854. my $preformatted = shift;
  2855. my $entry = shift;
  2856. my $index_name = shift;
  2857. my $index_command = shift;
  2858. my $texi_entry = shift;
  2859. my $formatted_entry = shift;
  2860. my $in_region_not_in_output = shift;
  2861. my $index_entry_ref = shift;
  2862. #return '' if ($index_entry_ref->{'hidden'});
  2863. #return '' if (!$index_entry_ref->{'seen_in_output'} and defined($index_entry_ref->{'region'}));
  2864. return '' if ($in_region_not_in_output or !defined($index_entry_ref->{'index_name'}));
  2865. main::line_warn(sprintf(__("Entry for index `%s' outside of any node"), $index_entry_ref->{'index_name'}), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node) and !$Texi2HTML::THISDOC{'state'}->{'outside_document'});
  2866. my $index_entry_stored = {'index_entry_reference' => $index_entry_ref, 'index_command' => $index_command, 'texi_entry' => $texi_entry};
  2867. return info_default_store_text(undef, undef, 'index_label', $index_entry_stored);
  2868. }
  2869. sub info_default_index_entry($$$$$$$$$$)
  2870. {
  2871. my $text_href = shift;
  2872. my $entry = shift;
  2873. my $element_href = shift;
  2874. my $element_text = shift;
  2875. my $entry_file = shift;
  2876. my $current_element_file = shift;
  2877. my $entry_target = shift;
  2878. my $entry_element_target = shift;
  2879. my $in_region_not_in_output = shift;
  2880. my $index_entry_ref = shift;
  2881. #return '' if ($index_entry_ref->{'hidden'});
  2882. #return '' if (!$index_entry_ref->{'seen_in_output'} and defined($index_entry_ref->{'region'}));
  2883. return '' if ($in_region_not_in_output);
  2884. my $state = {};
  2885. $state = { 'code_style' => 1 } if ($index_entry_ref->{'in_code'});
  2886. $entry = main::substitute_line($index_entry_ref->{'texi'}, "index entry in \@printindex", $state);
  2887. return '' if ($entry =~ /^\s*$/);
  2888. my $entry_nr = '';
  2889. if (!defined($info_default_index_entries_counts{$entry}))
  2890. {
  2891. $info_default_index_entries_counts{$entry} = 0;
  2892. }
  2893. else
  2894. {
  2895. $info_default_index_entries_counts{$entry} ++;
  2896. $entry_nr = ' <'.$info_default_index_entries_counts{$entry}.'>';
  2897. }
  2898. my $result = "* $entry${entry_nr}: ";
  2899. if (t2h_default_string_width($result) < $info_default_index_length_to_node)
  2900. {
  2901. $result .= ' ' x($info_default_index_length_to_node - t2h_default_string_width($result));
  2902. }
  2903. #print STDERR "DDDDDDDDDDD $index_entry_ref `$index_entry_ref->{'texi'}'\n";
  2904. my $info_index_entry_ref = $info_default_index_entries{$index_entry_ref};
  2905. my $line_nr = $info_index_entry_ref->{'line_nr'};
  2906. my $real_element_text;
  2907. my $element = $index_entry_ref->{'real_element'};
  2908. # in case $element->{'text'} is not defined, it certainly means that we
  2909. # are n a special elemet, most likely the virtual element appearing
  2910. # before anything else
  2911. if (!defined($element->{'text'}))
  2912. {
  2913. $real_element_text = gdt('(outside of any node)');
  2914. $line_nr = 0;
  2915. }
  2916. else
  2917. {
  2918. $element = $element->{'element_ref'} if ($element->{'element_ref'});
  2919. $real_element_text = $element->{'text'};
  2920. # this happens for index entries appearing after @printindex. In that case
  2921. # it is considered that they are at the beginning of the node.
  2922. $line_nr = 3 if (defined($line_nr) and $line_nr < 3);
  2923. $line_nr = 4 if (!defined($line_nr));
  2924. }
  2925. $result .= $real_element_text . '.';
  2926. my $max_len = $info_default_index_line_string_length{$index_entry_ref->{'index_name'}};
  2927. $max_len = t2h_default_string_width($line_nr) if (!defined($max_len));
  2928. my $line_nr_spaces = sprintf("%${max_len}d", $line_nr);
  2929. my $line_part = "(line ${line_nr_spaces})";
  2930. #print STDERR "GGGGGGGGGG name: $index_entry_ref->{'index_name'} max: ${max_len} line_nr: `$line_nr' line_nr_spaces `$line_nr_spaces' $line_part \n";
  2931. if (t2h_default_string_width($result)+t2h_default_string_width($line_part) +1 > get_conf('FILLCOLUMN'))
  2932. {
  2933. $result .= "\n" . ' ' x (get_conf('FILLCOLUMN') - t2h_default_string_width($line_part)) ;
  2934. }
  2935. else
  2936. {
  2937. $result .= ' ' x (get_conf('FILLCOLUMN') - t2h_default_string_width($line_part) - t2h_default_string_width($result));
  2938. }
  2939. $result .= "$line_part\n";
  2940. return $result;
  2941. }
  2942. sub info_default_index_summary($$)
  2943. {
  2944. my $alpha = shift;
  2945. my $nonalpha = shift;
  2946. return '';
  2947. }
  2948. sub info_default_summary_letter
  2949. {
  2950. return '';
  2951. }
  2952. sub info_default_foot_line_and_ref($$$$$$$$)
  2953. {
  2954. my $foot_num = shift;
  2955. my $relative_num = shift;
  2956. my $footid = shift;
  2957. my $docid = shift;
  2958. my $from_file = shift;
  2959. my $footnote_file = shift;
  2960. my $lines = shift;
  2961. my $state = shift;
  2962. my $footnote_state = $Texi2HTML::THISDOC{'state'};
  2963. my $footnote_info_state = info_default_get_state ($footnote_state);
  2964. my $footnote_text = "($info_default_footnote_index)";
  2965. $footnote_text = "($NO_NUMBER_FOOTNOTE_SYMBOL)" if (!get_conf('NUMBER_FOOTNOTES'));
  2966. my $node_name;
  2967. $node_name = '';
  2968. if (defined($info_default_current_node))
  2969. {
  2970. $node_name = $info_default_current_node->{'text'};
  2971. }
  2972. else
  2973. { # i18n
  2974. # no warning when outside of document, for footnotes in
  2975. # titlepage and copying
  2976. main::line_error(__("Footnote defined without parent node"), $Texi2HTML::THISDOC{'line_nr'}) unless ($footnote_state->{'outside_document'});
  2977. #print STDERR "".main::context_string()."\n";
  2978. }
  2979. if (get_conf('footnotestyle') eq 'separate')
  2980. {
  2981. $footnote_text .= ' (' . info_default_normal_reference('pxref', ["${node_name}-Footnote-${info_default_footnote_index}"]) . ')';
  2982. }
  2983. push @info_default_pending_footnotes, {'lines' => $lines,
  2984. 'footnote_text' => $footnote_text,
  2985. 'footnote_index' => ${info_default_footnote_index},
  2986. 'node_name' => $node_name,
  2987. 'footnote_info_state' => $footnote_info_state}
  2988. unless ($state->{'outside_document'} or (defined($state->{'multiple_pass'}) and $state->{'multiple_pass'} > 0));
  2989. return ([], $footnote_text);
  2990. }
  2991. sub info_default_foot_lines($)
  2992. {
  2993. my $lines = shift;
  2994. #my $state = $Texi2HTML::THISDOC{'state'};
  2995. #my $info_state = info_default_get_state ($state);
  2996. @$lines = ();
  2997. }
  2998. # remark: table_item is the html one, but it gets added to the table text
  2999. # on the stack, and is ignored there (in info_default_format).
  3000. sub info_default_format_list_item_texi($$$$)
  3001. {
  3002. my $format = shift;
  3003. my $line = shift;
  3004. my $prepended = shift;
  3005. my $command = shift;
  3006. my $number = shift;
  3007. my $open_command = 0;
  3008. my $result_line;
  3009. $command = 'bullet' if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize');
  3010. $prepended = "\@$command\{\}" if (defined($command) and $command ne '');
  3011. $prepended = "$number." if (defined($number) and $number ne '');
  3012. $line =~ s/^\s*//;
  3013. if (defined($command) and $command ne '' and $format ne 'itemize')
  3014. {
  3015. #@*table
  3016. $line =~ s/\s*$//;
  3017. if (exists ($style_map{$command}))
  3018. {
  3019. $result_line = "\@$command\{$line\}\n";
  3020. }
  3021. elsif (exists ($things_map{$command}))
  3022. {
  3023. $result_line = "\@$command\{\} $line\n";
  3024. }
  3025. else
  3026. {
  3027. $result_line = "\@$command $line\n";
  3028. }
  3029. }
  3030. # elsif (defined($prepended) and $prepended ne '')
  3031. # { # @enumerate and @itemize
  3032. # $prepended =~ s/^\s*//;
  3033. # $prepended =~ s/\s*$//;
  3034. # $result_line = $prepended . ' ' . $line;
  3035. # }
  3036. return ($result_line, $open_command);
  3037. }
  3038. sub info_default_list_item($$$$$$$$$$$$)
  3039. {
  3040. my $text = shift;
  3041. my $format = shift;
  3042. my $command = shift;
  3043. my $formatted_command = shift;
  3044. my $item_nr = shift;
  3045. my $enumerate_style = shift;
  3046. my $number = shift;
  3047. my $prepended = shift;
  3048. my $prepended_formatted = shift;
  3049. my $only_inter_item_commands = shift;
  3050. my $before_items = shift;
  3051. my $item_command = shift;
  3052. # my $prepend = '';
  3053. # if (defined($formatted_command) and $formatted_command ne '')
  3054. # {
  3055. # $prepend = $formatted_command;
  3056. # }
  3057. # return $prepend . $text;
  3058. # $command = 'bullet' if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize');
  3059. $formatted_command = $things_map{'bullet'} if ((!defined($command) or $command eq '') and (!defined($prepended) or $prepended eq '') and $format eq 'itemize');
  3060. if ($format !~ /table$/)
  3061. {
  3062. my $result = '';
  3063. if ($format eq 'enumerate')
  3064. {
  3065. $result = $number.'.';
  3066. }
  3067. elsif ($format eq 'itemize')
  3068. {
  3069. if (defined($formatted_command) and $formatted_command ne '')
  3070. {
  3071. $result = $formatted_command;
  3072. }
  3073. elsif (defined ($prepended_formatted) and $prepended_formatted ne '')
  3074. {
  3075. $prepended_formatted =~ s/^\s*//;
  3076. $prepended_formatted =~ s/\s*$//;
  3077. $result = $prepended_formatted;
  3078. }
  3079. }
  3080. else
  3081. {
  3082. $result = '';
  3083. }
  3084. $result .= ' ' if ($result ne '');
  3085. return info_default_close_command (undef, $item_command, $result);
  3086. }
  3087. return $text;
  3088. }
  3089. sub info_default_format($$$)
  3090. {
  3091. my $tag = shift;
  3092. my $element = shift;
  3093. my $text = shift;
  3094. # currently no command has something else than '' as $element.
  3095. # notice that any text is discarded
  3096. $element = undef if ($element eq '');
  3097. my $element_end = $element;
  3098. if (defined($element) and $element =~ /^(\w+)(\s+)(.+)/)
  3099. {
  3100. $element = $1;
  3101. $element_end = $2;
  3102. }
  3103. return info_default_close_command(undef, $tag, $element, $element_end);
  3104. }
  3105. sub info_default_tab_item_texi($$$$$$)
  3106. {
  3107. my $command = shift;
  3108. my $commands_stack = shift;
  3109. my $stack = shift;
  3110. my $state = shift;
  3111. my $line = shift;
  3112. my $line_nr = shift;
  3113. $line =~ s/^\s*//;
  3114. my $format;
  3115. my $info_state = info_default_get_state ($state);
  3116. #$format = $commands_stack->[-1] if (defined($commands_stack) and @$commands_stack and $commands_stack->[-1]);
  3117. my ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'});
  3118. print STDERR "Not in_format in info_default_tab_item_texi\n" if (!$in_format);
  3119. $format = $parent_format->{'command'};
  3120. # in case of an @item or @tab outside of any format $format will be
  3121. # undefined, or not multitable for a @tab.
  3122. # however the main program still do as if something was opened, plus
  3123. # it is checked there that the nesting is correct
  3124. #return $line if (!defined($format) or $command eq 'tab' and $format ne 'multitable');
  3125. #print STDERR "tab_item_texi $format $command $commands_stack, $stack, $state, $line, ".main::format_line_number($line_nr)."\n";
  3126. if ($format eq 'multitable')
  3127. { # even if it is a tab, if it is not already in a multitable_row, one
  3128. # should be started
  3129. if ($command ne 'tab' or $info_state->{'current'}->{'command'} ne 'multitable_row')
  3130. {
  3131. info_default_open_command($state, 'multitable_row');
  3132. }
  3133. info_default_open_command($state, 'multitable_cell');
  3134. }
  3135. elsif ($format =~ /table$/)
  3136. {
  3137. info_default_store_text ($state, undef, $command, {'format_name' => $format});
  3138. }
  3139. else
  3140. {
  3141. info_default_open_command ($state, $command, {'format_name' => $format});
  3142. }
  3143. # this allows removing blank space in front of the item or tab argument
  3144. return $line;
  3145. }
  3146. sub info_default_sp($$)
  3147. {
  3148. my $number = shift;
  3149. my $preformatted = shift;
  3150. my $result = "\n" x $number;
  3151. return info_default_store_text(undef,$result,'sp');
  3152. }
  3153. sub info_default_paragraph_style_command($$)
  3154. {
  3155. my $format = shift;
  3156. my $text = shift;
  3157. return info_default_close_command(undef, $format);
  3158. }
  3159. sub info_default_row($$$$$$$$)
  3160. {
  3161. my $text = shift;
  3162. my $macro = shift;
  3163. my $columnfractions = shift;
  3164. my $prototype_row = shift;
  3165. my $prototype_lengths = shift;
  3166. my $column_number = shift;
  3167. my $only_inter_item_commands = shift;
  3168. my $before_items = shift;
  3169. #print STDERR "info_default_row: $text\n";
  3170. return info_default_close_command(undef, 'multitable_row', undef, undef, {'item_command' => $macro});
  3171. }
  3172. sub info_default_cell($$$$$$$$)
  3173. {
  3174. my $text = shift;
  3175. my $row_macro = shift;
  3176. my $columnfractions = shift;
  3177. my $prototype_row = shift;
  3178. my $prototype_lengths = shift;
  3179. my $column_number = shift;
  3180. my $only_inter_item_commands = shift;
  3181. my $before_items = shift;
  3182. # in general, when before_items, there will be no call to the function
  3183. # since there should never be a text sent back, so that this
  3184. # function will not be called for the first row (the multitable title).
  3185. # However, if there is a @tab before the first @item, the main program
  3186. # is less careful and closes the cell in any case, so before_items
  3187. # has to be checked for that case.
  3188. return info_default_close_command(undef, 'multitable_cell') unless ($before_items);
  3189. }
  3190. sub info_default_table_list($$$$$$$$$)
  3191. {
  3192. my $format_command = shift;
  3193. my $text = shift;
  3194. my $command = shift;
  3195. my $formatted_command = shift;
  3196. # enumerate
  3197. my $item_nr = shift;
  3198. my $enumerate_style = shift;
  3199. # itemize
  3200. my $prepended = shift;
  3201. my $prepended_formatted = shift;
  3202. # multitable
  3203. my $columnfractions = shift;
  3204. my $prototype_row = shift;
  3205. my $prototype_lengths = shift;
  3206. my $column_number = shift;
  3207. die "BUG: $format_command item_nr undef\n" if (!defined($item_nr));
  3208. return info_default_close_command(undef, $format_command, undef, undef, {'total_item_nr' => $item_nr}) if ($format_command ne 'multitable');
  3209. my $columnsize = [];
  3210. if (defined($prototype_lengths) and @$prototype_lengths)
  3211. {
  3212. $columnsize = [ @$prototype_lengths ];
  3213. }
  3214. elsif (defined($columnfractions) and @$columnfractions)
  3215. {
  3216. foreach my $fraction (@$columnfractions)
  3217. {
  3218. push @$columnsize, int($fraction * get_conf('FILLCOLUMN') +0.5);
  3219. }
  3220. }
  3221. else
  3222. { # empty multitable
  3223. #print STDERR "Empty multitable?\n";
  3224. }
  3225. return info_default_close_command(undef, $format_command, undef, undef, {'columns_size' => $columnsize, 'total_item_nr' => $item_nr});
  3226. }
  3227. sub info_default_def_item($$$)
  3228. {
  3229. my $text = shift;
  3230. my $only_inter_item_commands = shift;
  3231. my $command = shift;
  3232. my $format = 'deff_item';
  3233. $format = 'deff_itemx' if ($command =~ /x$/);
  3234. return info_default_close_command(undef, $format);
  3235. }
  3236. sub info_default_def_line($$$$$$$$$$$$$$$$)
  3237. {
  3238. my $category_prepared = shift;
  3239. my $name = shift;
  3240. my $type = shift;
  3241. my $arguments = shift;
  3242. my $index_label = shift;
  3243. my $arguments_array = shift;
  3244. my $arguments_type_array = shift;
  3245. my $unformatted_arguments_array = shift;
  3246. my $command = shift;
  3247. my $class_name = shift;
  3248. my $category = shift;
  3249. my $class = shift;
  3250. my $style = shift;
  3251. my $original_command = shift;
  3252. $name = '' if (!defined($name) or ($name =~ /^\s*$/));
  3253. $type = '' if (!defined($type) or $type =~ /^\s*$/);
  3254. $arguments = '' if (!defined($arguments) or $arguments =~ /^\s*$/);
  3255. my $type_name = '';
  3256. $type_name .= "$type " if ($type ne '');
  3257. $type_name .= $name if ($name ne '');
  3258. my $result = " -- $category_prepared: ${type_name}$arguments";
  3259. $result =~ s/\s*$//;
  3260. $result .= "\n";
  3261. my $state = $Texi2HTML::THISDOC{'state'};
  3262. info_default_store_text(undef,$result,"${command}_line",{'definition_line' => 1});
  3263. my $format = 'deff_item';
  3264. $format = 'deff_itemx' if ($original_command =~ /x$/);
  3265. return info_default_open_command($state, $format);
  3266. }
  3267. sub info_default_def($$)
  3268. {
  3269. my $text = shift;
  3270. my $command = shift;
  3271. return info_default_close_command(undef, $command);
  3272. }
  3273. sub info_default_float($$$$$)
  3274. {
  3275. my $text = shift;
  3276. my $float = shift;
  3277. my $caption = shift;
  3278. my $shortcaption = shift;
  3279. my $additional_arguments;
  3280. if (exists($float->{'id'}))
  3281. {
  3282. $additional_arguments->{'anchor_reference'} = $float;
  3283. main::line_warn(__("float reference outside of any node, it won't be registered"), $Texi2HTML::THISDOC{'line_nr'}) if (!defined($info_default_current_node) and !$Texi2HTML::THISDOC{'state'}->{'outside_document'});
  3284. }
  3285. my $caption_text = '';
  3286. if (defined($float->{'caption_texi'}))
  3287. {
  3288. $caption_text = $caption;
  3289. }
  3290. elsif (defined($float->{'shortcaption_texi'}))
  3291. {
  3292. $caption_text = $shortcaption;
  3293. }
  3294. elsif (defined($caption))
  3295. {
  3296. $caption_text = $caption;
  3297. }
  3298. #return $caption_text;
  3299. return info_default_close_command(undef, 'float', undef, $caption_text, $additional_arguments);
  3300. }
  3301. sub info_default_listoffloats_entry($$$$)
  3302. {
  3303. my $style_texi = shift;
  3304. my $float = shift;
  3305. my $float_style = shift;
  3306. my $caption = shift;
  3307. my $href = shift;
  3308. my @lines = split /^/, $caption;
  3309. $caption = $lines[0];
  3310. $caption = '' if (!defined($caption));
  3311. chomp ($caption);
  3312. my $result = '';
  3313. #$caption .= ':' if ($caption ne '');
  3314. my $caption_entry = "* $float_style: $float->{'text'}.";
  3315. if (t2h_default_string_width($caption_entry) > $info_default_listoffloat_caption_entry_length)
  3316. {
  3317. $caption_entry .= "\n" . ' ' x $info_default_listoffloat_caption_entry_length;
  3318. }
  3319. else
  3320. {
  3321. $caption_entry .= ' ' x ($info_default_listoffloat_caption_entry_length - length($caption_entry));
  3322. }
  3323. my $width = $info_default_listoffloat_caption_entry_length;
  3324. while ($caption =~ s/^(\S+\s*)//)
  3325. {
  3326. my $new_word = $1;
  3327. if ((t2h_default_string_width($new_word) + $width) > get_conf('FILLCOLUMN') - 3)
  3328. {
  3329. $caption_entry .= $info_default_listoffloat_append;
  3330. last;
  3331. }
  3332. else
  3333. {
  3334. $caption_entry .= $new_word;
  3335. $width += t2h_default_string_width($new_word);
  3336. }
  3337. }
  3338. return $caption_entry. "\n";
  3339. }
  3340. sub info_default_listoffloats($$$)
  3341. {
  3342. my $style_texi = shift;
  3343. my $style = shift;
  3344. my $float_entries = shift;
  3345. my $state = $Texi2HTML::THISDOC{'state'};
  3346. my $info_state = info_default_get_state ($state);
  3347. my $result = "* Menu:\n\n";
  3348. foreach my $float_entry (@$float_entries)
  3349. {
  3350. $result .= $float_entry;
  3351. }
  3352. my ($parent_format, $in_format);
  3353. ($parent_format, $in_format) = info_default_parent_format($info_state->{'current'});
  3354. #print STDERR "\@listoffloats not at top level\n" if ($in_format);
  3355. info_default_increment_paragraph ($in_format, $parent_format, $info_state, 'listoffloats');
  3356. return info_default_store_text($state,$result,'listoffloats');
  3357. }
  3358. sub info_default_raw($$)
  3359. {
  3360. my $style = shift;
  3361. my $text = shift;
  3362. my $expanded = 1 if (grep {$style eq $_} @EXPAND);
  3363. # no warning for unknown raw formats
  3364. if ($style eq 'verbatim' or $style eq 'verbatiminclude' or $expanded)
  3365. {
  3366. return info_default_store_text(undef, $text, $style, {'raw_command' => 1});
  3367. }
  3368. return '';
  3369. }
  3370. sub info_default_line_command($$$$)
  3371. {
  3372. my $command = shift;
  3373. my $arg_text = shift;
  3374. my $arg_texi = shift;
  3375. my $state = shift;
  3376. main::line_warn(__("\@dircategory after first node"), $Texi2HTML::THISDOC{'line_nr'}) if (defined($info_default_current_node));
  3377. return '' if ($arg_text eq '');
  3378. $info_default_dir_specification .= "INFO-DIR-SECTION $arg_text\n";
  3379. return '';
  3380. }
  3381. sub info_default_unknown_style($$$$$)
  3382. {
  3383. my $command = shift;
  3384. my $text = shift;
  3385. my $state = shift;
  3386. my $no_close = shift;
  3387. my $no_open = shift;
  3388. my ($result, $result_text, $message);
  3389. $result_text = info_default_close_command(undef, $command, undef, undef, undef);
  3390. $message = "Unknown command with braces `\@$command'" if (!$no_open);
  3391. return (1, $result_text, $message);
  3392. }
  3393. 1;