123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812 |
- # $Id$
- # HTML.pm: output tree as HTML.
- #
- # Copyright 2011, 2012, 2013, 2014, 2015,
- # 2016 Free Software Foundation, Inc.
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 3 of the License,
- # or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
- #
- # Original author: Patrice Dumas <pertusus@free.fr>
- package Texinfo::Convert::HTML;
- use 5.00405;
- # See 'The "Unicode Bug"' under 'perlunicode' man page. This means
- # that regular expressions will treat characters 128-255 in a Perl string
- # the same regardless of whether the string is using a UTF-8 encoding.
- # For older Perls, you can use utf8::upgrade on the strings, where the
- # difference matters.
- use if $] >= 5.012, feature => 'unicode_strings';
- use strict;
- use Texinfo::Convert::Converter;
- use Texinfo::Common;
- use Texinfo::Convert::Texinfo;
- use Texinfo::Convert::Text;
- use Texinfo::Convert::Unicode;
- use Texinfo::Convert::NodeNameNormalization;
- use Carp qw(cluck);
- require Exporter;
- use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
- @ISA = qw(Exporter Texinfo::Convert::Converter);
- # Items to export into callers namespace by default. Note: do not export
- # names by default without a very good reason. Use EXPORT_OK instead.
- # Do not simply export all your public functions/methods/constants.
- # This allows declaration use Texinfo::Convert::HTML ':all';
- # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
- # will save memory.
- %EXPORT_TAGS = ( 'all' => [ qw(
- convert
- convert_tree
- output
- output_internal_links
- ) ] );
- @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
- @EXPORT = qw(
- );
- $VERSION = '6.3.90';
- # misc commands that are of use for formatting.
- my %formatting_misc_commands = %Texinfo::Convert::Text::formatting_misc_commands;
- my %no_brace_commands = %Texinfo::Common::no_brace_commands;
- my %accent_commands = %Texinfo::Common::accent_commands;
- my %misc_commands = %Texinfo::Common::misc_commands;
- my %sectioning_commands = %Texinfo::Common::sectioning_commands;
- my %def_commands = %Texinfo::Common::def_commands;
- my %ref_commands = %Texinfo::Common::ref_commands;
- my %brace_commands = %Texinfo::Common::brace_commands;
- my %block_commands = %Texinfo::Common::block_commands;
- my %menu_commands = %Texinfo::Common::menu_commands;
- my %root_commands = %Texinfo::Common::root_commands;
- my %preformatted_commands = %Texinfo::Common::preformatted_commands;
- my %explained_commands = %Texinfo::Common::explained_commands;
- my %item_container_commands = %Texinfo::Common::item_container_commands;
- my %raw_commands = %Texinfo::Common::raw_commands;
- my %format_raw_commands = %Texinfo::Common::format_raw_commands;
- my %inline_commands = %Texinfo::Common::inline_commands;
- my %inline_format_commands = %Texinfo::Common::inline_format_commands;
- my %code_style_commands = %Texinfo::Common::code_style_commands;
- my %regular_font_style_commands = %Texinfo::Common::regular_font_style_commands;
- my %preformatted_code_commands = %Texinfo::Common::preformatted_code_commands;
- my %default_index_commands = %Texinfo::Common::default_index_commands;
- my %style_commands = %Texinfo::Common::style_commands;
- my %align_commands = %Texinfo::Common::align_commands;
- my %region_commands = %Texinfo::Common::region_commands;
- my %context_brace_commands = %Texinfo::Common::context_brace_commands;
- my %letter_no_arg_commands = %Texinfo::Common::letter_no_arg_commands;
- foreach my $def_command (keys(%def_commands)) {
- $formatting_misc_commands{$def_command} = 1 if ($misc_commands{$def_command});
- }
- # FIXME remove raw commands?
- my %format_context_commands = (%block_commands, %root_commands);
- foreach my $misc_context_command('tab', 'item', 'itemx', 'headitem') {
- $format_context_commands{$misc_context_command} = 1;
- }
- my %composition_context_commands = (%preformatted_commands, %root_commands,
- %menu_commands, %align_commands);
- $composition_context_commands{'float'} = 1;
- my %pre_class_types;
- # FIXME allow customization? (also in DocBook)
- my %upper_case_commands = ( 'sc' => 1 );
- sub in_math($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'math'};
- }
- # set if in menu or preformatted command
- sub in_preformatted($)
- {
- my $self = shift;
- my $context = $self->{'document_context'}->[-1]->{'composition_context'}->[-1];
- if ($preformatted_commands{$context}
- or $pre_class_types{$context}
- or ($menu_commands{$context} and $self->_in_preformatted_in_menu())) {
- return $context;
- } else {
- return undef;
- }
- }
- sub in_upper_case($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'upper_case'};
- }
- sub in_space_protected($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'space_protected'};
- }
- sub in_code($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'monospace'}->[-1];
- }
- sub in_string($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'string'};
- }
- sub in_verbatim($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'verbatim'};
- }
- sub in_raw($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'raw'};
- }
- sub paragraph_number($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'paragraph_number'};
- }
- sub preformatted_number($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'preformatted_number'};
- }
- sub top_format($)
- {
- my $self = shift;
- return $self->{'document_context'}->[-1]->{'formats'}->[-1];
- }
- sub commands_stack($)
- {
- my $self = shift;
- return @{$self->{'document_context'}->[-1]->{'commands'}};
- }
- sub preformatted_classes_stack($)
- {
- my $self = shift;
- return @{$self->{'document_context'}->[-1]->{'preformatted_classes'}};
- }
- sub in_align($)
- {
- my $self = shift;
- my $context
- = $self->{'document_context'}->[-1]->{'composition_context'}->[-1];
- if ($align_commands{$context}) {
- return $context;
- } else {
- return undef;
- }
- }
- # $COMMAND should be a tree element which is a possible target of a link.
- #
- # Returns a hash that may have these keys set:
- # 'target': A unique string representing the target. Used as argument to
- # 'name' attribute inside <a>.
- # 'node_filename', 'section_filename',
- # 'misc_filename', 'filename'. Possibly others.
- #
- # Some functions cache their results in these hashes.
- sub _get_target($$)
- {
- my $self = shift;
- my $command = shift;
- my $target;
- if (!defined($command)) {
- cluck("_get_target command not defined");
- }
- if ($self->{'targets'}->{$command}) {
- $target = $self->{'targets'}->{$command};
- } elsif ($command->{'cmdname'}
- # This should only happen for @*heading*, root_commands targets should
- # already be set.
- and $sectioning_commands{$command->{'cmdname'}}
- and !$root_commands{$command->{'cmdname'}}) {
- $target = $self->_new_sectioning_command_target($command);
- }
- return $target;
- }
- # API for the elements formatting
- sub command_id($$)
- {
- my $self = shift;
- my $command = shift;
- my $target = $self->_get_target($command);
- if ($target) {
- return $target->{'target'};
- } else {
- return undef;
- }
- }
- sub command_contents_target($$$)
- {
- my $self = shift;
- my $command = shift;
- my $contents_or_shortcontents = shift;
- $contents_or_shortcontents = 'shortcontents'
- if ($contents_or_shortcontents eq 'summarycontents');
- my $target = $self->_get_target($command);
- if ($target) {
- return $target->{$contents_or_shortcontents .'_target'};
- } else {
- return undef;
- }
- }
- # Return href target for linking to this command
- sub command_target($$)
- {
- my $self = shift;
- my $command = shift;
- if ($command->{'extra'}
- and $command->{'extra'}->{'associated_node'}) {
- $command = $command->{'extra'}->{'associated_node'};
- }
- my $target = $self->_get_target($command);
- if ($target) {
- return $target->{'target'};
- } else {
- return undef;
- }
- }
- sub command_filename($$)
- {
- my $self = shift;
- my $command = shift;
- my $target = $self->_get_target($command);
- if ($target) {
- if (defined($target->{'filename'})) {
- return $target->{'filename'};
- }
- my ($element, $root_command) = $self->_get_element($command, 1);
- if (defined($root_command)) {
- $target->{'root_command'} = $root_command;
- }
- if (defined($element)) {
- $target->{'element'} = $element;
- $target->{'filename'} = $element->{'filename'};
- return $element->{'filename'};
- }
- }
- return undef;
- }
- sub command_element($$)
- {
- my $self = shift;
- my $command = shift;
- my $target = $self->_get_target($command);
- if ($target) {
- $self->command_filename($command);
- return $target->{'element'};
- }
- return undef;
- }
- sub command_element_command($$)
- {
- my $self = shift;
- my $command = shift;
- my ($element, $root_command) = $self->_get_element($command);
- #my $element = $self->command_element($command);
- if ($element and $element->{'extra'}) {
- return $element->{'extra'}->{'element_command'};
- }
- return undef;
- }
- sub element_command($$)
- {
- my $self = shift;
- my $element = shift;
- if ($element and $element->{'extra'}) {
- if ($element->{'extra'}->{'element_command'}) {
- return $element->{'extra'}->{'element_command'};
- } elsif ($element->{'extra'}->{'special_element'}) {
- return $element;
- }
- }
- return undef;
- }
- sub command_node($$)
- {
- my $self = shift;
- my $command = shift;
- my $target = $self->_get_target($command);
- if ($target) {
- $self->command_filename($command);
- my $root_command = $target->{'root_command'};
- if (defined($root_command)) {
- if ($root_command->{'cmdname'} and $root_command->{'cmdname'} eq 'node') {
- return $root_command;
- }
- if ($root_command->{'extra'} and $root_command->{'extra'}->{'associated_node'}) {
- return $root_command->{'extra'}->{'associated_node'};
- }
- }
- }
- return undef;
- }
- # Return string for linking to $COMMAND with <a href>
- sub command_href($$;$$)
- {
- my $self = shift;
- my $command = shift;
- my $filename = shift;
- my $link_command = shift;
- $filename = $self->{'current_filename'} if (!defined($filename));
- if ($command->{'manual_content'} or $command->{'top_node_up'}) {
- return $self->_external_node_href($command, $filename, $link_command);
- }
- my $target = $self->command_target($command);
- return '' if (!defined($target));
- my $href = '';
- my $target_filename = $self->command_filename($command);
- if (!defined($target_filename)) {
- # Happens if there are no pages, for example if OUTPUT is set to ''
- # as in the test cases. Also for things in @titlepage when
- # titlepage is not output.
- if ($self->{'elements'} and $self->{'elements'}->[0]
- and defined($self->{'elements'}->[0]->{'filename'})) {
- # In that case use the first page.
- $target_filename = $self->{'elements'}->[0]->{'filename'};
- }
- }
- if (defined($target_filename)) {
- if (!defined($filename)
- or $filename ne $target_filename) {
- $href .= $target_filename;
- }
- }
- $href .= '#' . $target if ($target ne '');
- return $href;
- }
- my %contents_command_element_name = (
- 'contents' => 'Contents',
- 'shortcontents' => 'Overview',
- 'summarycontents' => 'Overview',
- );
- sub command_contents_href($$$$)
- {
- my $self = shift;
- my $command = shift;
- my $contents_or_shortcontents = shift;
- my $filename = shift;
- my $href;
- my $name = $contents_command_element_name{$contents_or_shortcontents};
-
- my $target = $self->command_contents_target($command, $contents_or_shortcontents);
- my $target_element = $self->special_element($name);
- my $target_filename;
- # !defined happens when called as convert() and not output()
- if (defined($target_element)) {
- $target_filename = $self->command_filename($target_element);
- }
- if (defined($target_filename) and
- (!defined($filename)
- or $filename ne $target_filename)) {
- $href .= $target_filename;
- }
- $href .= '#' . $target if ($target ne '');
- return $href;
- }
- # Return text to be used for a hyperlink to $COMMAND.
- # $TYPE refers to the type of value returned from this function:
- # 'text' - return text
- # 'tree' - return a tree
- # 'tree_nonumber' - return tree representing text without a chapter number
- # being included.
- # 'string'
- sub command_text($$;$)
- {
- my $self = shift;
- my $command = shift;
- my $type = shift;
- if (!defined($type)) {
- $type = 'text';
- }
- if (!defined($command)) {
- cluck "in command_text($type) command not defined";
- }
- if ($command->{'manual_content'} or $command->{'top_node_up'}) {
- my $node_content = [];
- $node_content = $command->{'node_content'}
- if (defined($command->{'node_content'}));
- my $tree;
- if ($command->{'manual_content'}) {
- $tree = {'type' => '_code',
- 'contents' => [{'text' => '('}, @{$command->{'manual_content'}},
- {'text' => ')'}, @$node_content]};
- } else {
- $tree = {'type' => '_code',
- 'contents' => $node_content};
- }
- if ($type eq 'tree') {
- return $tree;
- } else {
- if ($type eq 'string') {
- $tree = {'type' => '_string',
- 'contents' => [$tree]};
- }
- my $result = $self->convert_tree_new_formatting_context(
- $tree, $command->{'cmdname'});
- return $result;
- }
- }
- my $target = $self->_get_target($command);
- if ($target) {
- my $explanation;
- $explanation = "command_text \@$command->{'cmdname'}"
- if ($command->{'cmdname'});
- if (defined($target->{$type})) {
- return $target->{$type};
- }
- my $tree;
- if (!$target->{'tree'}) {
- if ($command->{'extra'}
- and $command->{'extra'}->{'special_element'}) {
- my $special_element = $command->{'extra'}->{'special_element'};
- $tree = $self->get_conf('SPECIAL_ELEMENTS_NAME')->{$special_element};
- $explanation = "command_text $special_element";
- } elsif ($command->{'cmdname'} and ($command->{'cmdname'} eq 'node'
- or $command->{'cmdname'} eq 'anchor')) {
- $tree = {'type' => '_code',
- 'contents' => $command->{'extra'}->{'node_content'}};
- } elsif ($command->{'cmdname'} and ($command->{'cmdname'} eq 'float')) {
- $tree = $self->_float_type_number($command);
- } elsif ($command->{'extra'}->{'missing_argument'}) {
- if ($type eq 'tree' or $type eq 'tree_nonumber') {
- return {};
- } else {
- return '';
- }
- } else {
- if (!$command->{'extra'}->{'misc_content'}) {
- cluck "No misc_content: "
- .Texinfo::Common::_print_current($command);
- }
- if (defined($command->{'number'})
- and ($self->get_conf('NUMBER_SECTIONS')
- or !defined($self->get_conf('NUMBER_SECTIONS')))) {
- if ($command->{'cmdname'} eq 'appendix' and $command->{'level'} == 1) {
- $tree = $self->gdt('Appendix {number} {section_title}',
- {'number' => {'text' => $command->{'number'}},
- 'section_title'
- => {'contents'
- => $command->{'extra'}->{'misc_content'}}});
- } else {
- $tree = $self->gdt('{number} {section_title}',
- {'number' => {'text' => $command->{'number'}},
- 'section_title'
- => {'contents'
- => $command->{'extra'}->{'misc_content'}}});
- }
- } else {
- $tree = {'contents' => [@{$command->{'extra'}->{'misc_content'}}]};
- }
- $target->{'tree_nonumber'}
- = {'contents' => $command->{'extra'}->{'misc_content'}};
- }
- $target->{'tree'} = $tree;
- } else {
- $tree = $target->{'tree'};
- }
- return $target->{'tree_nonumber'} if ($type eq 'tree_nonumber'
- and $target->{'tree_nonumber'});
- return $tree if ($type eq 'tree' or $type eq 'tree_nonumber');
-
- $self->_new_document_context($command->{'cmdname'});
- if ($type eq 'string') {
- $tree = {'type' => '_string',
- 'contents' => [$tree]};
- }
-
- if ($type =~ /^(.*)_nonumber$/) {
- $tree = $target->{'tree_nonumber'}
- if (defined($target->{'tree_nonumber'}));
- }
- $self->{'ignore_notice'}++;
- $target->{$type} = $self->_convert($tree, $explanation);
- $self->{'ignore_notice'}--;
- pop @{$self->{'document_context'}};
- return $target->{$type};
- }
- return undef;
- }
- # Return the element in the tree that $LABEL refers to.
- sub label_command($$)
- {
- my $self = shift;
- my $label = shift;
- return $self->{'labels'}->{$label};
- }
- sub special_element($$)
- {
- my $self = shift;
- my $type = shift;
- return $self->{'special_elements_types'}->{$type};
- }
- sub global_element($$)
- {
- my $self = shift;
- my $type = shift;
- return $self->{'global_target_elements'}->{$type};
- }
- # it is considered 'top' only if element corresponds to @top or
- # element is a node
- sub element_is_top($$)
- {
- my $self = shift;
- my $element = shift;
- return ($self->{'global_target_elements'}->{'Top'}
- and $self->{'global_target_elements'}->{'Top'} eq $element
- and $element->{'extra'}
- and (($element->{'extra'}->{'section'}
- and $element->{'extra'}->{'section'}->{'cmdname'} eq 'top')
- or ($element->{'extra'}->{'element_command'}
- and $element->{'extra'}->{'element_command'}->{'cmdname'} eq 'node')));
- }
- sub default_formatting_function($$)
- {
- my $self = shift;
- my $format = shift;
- return $self->{'default_formatting_functions'}->{$format};
- }
- sub get_value($$)
- {
- my $self = shift;
- my $value = shift;
- if (defined($self->{'parser'})
- and exists ($self->{'parser'}->{'values'}->{$value})) {
- return $self->{'parser'}->{'values'}->{$value};
- } else {
- return undef;
- }
- }
- sub convert_tree_new_formatting_context($$;$$)
- {
- my $self = shift;
- my $tree = shift;
- my $context_string = shift;
- my $multiple_pass = shift;
- if (defined($context_string)) {
- $self->_new_document_context($context_string);
- }
- if ($multiple_pass) {
- $self->{'ignore_notice'}++;
- push @{$self->{'multiple_pass'}}, $multiple_pass;
- }
- my $result = $self->convert_tree($tree);
- if (defined($context_string)) {
- pop @{$self->{'document_context'}};
- }
- if ($multiple_pass) {
- $self->{'ignore_notice'}--;
- pop @{$self->{'multiple_pass'}};
- }
- return $result;
- }
- # see http://www.w3.org/TR/REC-html40/types.html#type-links
- my %BUTTONS_REL =
- (
- 'Top', 'start',
- 'Contents', 'contents',
- 'Overview', '',
- 'Index', 'index',
- 'This', '',
- 'Back', 'prev',
- 'FastBack', '',
- 'Prev', 'prev',
- 'Up', 'up',
- 'Next', 'next',
- 'NodeUp', 'up',
- 'NodeNext', 'next',
- 'NodePrev', 'prev',
- 'NodeForward', '',
- 'NodeBack', '',
- 'Forward', 'next',
- 'FastForward', '',
- 'About' , 'help',
- 'First', '',
- 'Last', '',
- 'NextFile', 'next',
- 'PrevFile', 'prev',
- );
- my %BUTTONS_ACCESSKEY =
- (
- 'Top', '',
- 'Contents', '',
- 'Overview', '',
- 'Index', '',
- 'This', '',
- 'Back', 'p',
- 'FastBack', '',
- 'Prev', 'p',
- 'Up', 'u',
- 'Next', 'n',
- 'NodeUp', 'u',
- 'NodeNext', 'n',
- 'NodePrev', 'p',
- 'NodeForward', '',
- 'NodeBack', '',
- 'Forward', 'n',
- 'FastForward', '',
- 'About' , '',
- 'First', '',
- 'Last', '',
- 'NextFile', '',
- 'PrevFile', '',
- );
- my %BUTTONS_EXAMPLE =
- (
- 'Top', ' ',
- 'Contents', ' ',
- 'Overview', ' ',
- 'Index', ' ',
- 'This', '1.2.3',
- 'Back', '1.2.2',
- 'FastBack', '1',
- 'Prev', '1.2.2',
- 'Up', '1.2',
- 'Next', '1.2.4',
- 'NodeUp', '1.2',
- 'NodeNext', '1.2.4',
- 'NodePrev', '1.2.2',
- 'NodeForward', '1.2.4',
- 'NodeBack', '1.2.2',
- 'Forward', '1.2.4',
- 'FastForward', '2',
- 'About', ' ',
- 'First', '1.',
- 'Last', '1.2.4',
- 'NextFile', ' ',
- 'PrevFile', ' ',
- );
- my (%BUTTONS_TEXT, %BUTTONS_GOTO, %BUTTONS_NAME, %SPECIAL_ELEMENTS_NAME);
- sub _translate_names($)
- {
- my $self = shift;
- #print STDERR "encoding_name: ".$self->get_conf('OUTPUT_ENCODING_NAME')." documentlanguage: ".$self->get_conf('documentlanguage')."\n";
- %BUTTONS_TEXT = (
- 'Top', $self->gdt('Top'),
- 'Contents', $self->gdt('Contents'),
- 'Overview', $self->gdt('Overview'),
- 'Index', $self->gdt('Index'),
- ' ', ' ',
- 'This', $self->gdt('current'),
- 'Back', ' < ',
- 'FastBack', ' << ',
- 'Prev', $self->gdt('Prev'),
- 'Up', $self->gdt(' Up '),
- 'Next', $self->gdt('Next'),
- #'NodeUp', $self->gdt('Node up'),
- 'NodeUp', $self->gdt('Up'),
- #'NodeNext', $self->gdt('Next node'),
- 'NodeNext', $self->gdt('Next'),
- #'NodePrev', $self->gdt('Previous node'),
- 'NodePrev', $self->gdt('Previous'),
- 'NodeForward', $self->gdt('Forward node'),
- 'NodeBack', $self->gdt('Back node'),
- 'Forward', ' > ',
- 'FastForward', ' >> ',
- 'About', ' ? ',
- 'First', ' |< ',
- 'Last', ' >| ',
- 'NextFile', $self->gdt('Next file'),
- 'PrevFile', $self->gdt('Previous file'),
- );
- #%BUTTONS_TEXT = %NAVIGATION_TEXT;
- %BUTTONS_GOTO = (
- 'Top', $self->gdt('Cover (top) of document'),
- 'Contents', $self->gdt('Table of contents'),
- 'Overview', $self->gdt('Short table of contents'),
- 'Index', $self->gdt('Index'),
- 'This', $self->gdt('Current section'),
- 'Back', $self->gdt('Previous section in reading order'),
- 'FastBack', $self->gdt('Beginning of this chapter or previous chapter'),
- 'Prev', $self->gdt('Previous section on same level'),
- 'Up', $self->gdt('Up section'),
- 'Next', $self->gdt('Next section on same level'),
- 'NodeUp', $self->gdt('Up node'),
- 'NodeNext', $self->gdt('Next node'),
- 'NodePrev', $self->gdt('Previous node'),
- 'NodeForward', $self->gdt('Next node in node reading order'),
- 'NodeBack', $self->gdt('Previous node in node reading order'),
- 'Forward', $self->gdt('Next section in reading order'),
- 'FastForward', $self->gdt('Next chapter'),
- 'About' , $self->gdt('About (help)'),
- 'First', $self->gdt('First section in reading order'),
- 'Last', $self->gdt('Last section in reading order'),
- 'NextFile', $self->gdt('Forward section in next file'),
- 'PrevFile', $self->gdt('Back section in previous file'),
- );
- %BUTTONS_NAME = (
- 'Top', $self->gdt('Top'),
- 'Contents', $self->gdt('Contents'),
- 'Overview', $self->gdt('Overview'),
- 'Index', $self->gdt('Index'),
- ' ', ' ',
- 'This', $self->gdt('This'),
- 'Back', $self->gdt('Back'),
- 'FastBack', $self->gdt('FastBack'),
- 'Prev', $self->gdt('Prev'),
- 'Up', $self->gdt('Up'),
- 'Next', $self->gdt('Next'),
- 'NodeUp', $self->gdt('NodeUp'),
- 'NodeNext', $self->gdt('NodeNext'),
- 'NodePrev', $self->gdt('NodePrev'),
- 'NodeForward', $self->gdt('NodeForward'),
- 'NodeBack', $self->gdt('NodeBack'),
- 'Forward', $self->gdt('Forward'),
- 'FastForward', $self->gdt('FastForward'),
- 'About', $self->gdt('About'),
- 'First', $self->gdt('First'),
- 'Last', $self->gdt('Last'),
- 'NextFile', $self->gdt('NextFile'),
- 'PrevFile', $self->gdt('PrevFile'),
- );
- %SPECIAL_ELEMENTS_NAME = (
- 'About' => $self->gdt('About This Document'),
- 'Contents' => $self->gdt('Table of Contents'),
- 'Overview' => $self->gdt('Short Table of Contents'),
- 'Footnotes' => $self->gdt('Footnotes'),
- );
- # delete the tree and formatted results for special elements
- # such that they are redone with the new tree when needed.
- foreach my $special_element (keys (%SPECIAL_ELEMENTS_NAME)) {
- if ($self->{'special_elements_types'}->{$special_element} and
- $self->{'targets'}->{$self->{'special_elements_types'}->{$special_element}}) {
- my $target
- = $self->{'targets'}->{$self->{'special_elements_types'}->{$special_element}};
- foreach my $key ('text', 'string', 'tree') {
- delete $target->{$key};
- }
- }
- }
-
- foreach my $hash (\%BUTTONS_TEXT, \%BUTTONS_GOTO, \%BUTTONS_NAME) {
- foreach my $button (keys (%$hash)) {
- if (ref($hash->{$button})) {
- $hash->{$button} = $self->convert_tree_new_formatting_context(
- $hash->{$button}, "button $button");
- }
- }
- }
- if ($self->{'commands_translation'}) {
- my %translated_commands;
- foreach my $context ('normal', 'preformatted', 'string') {
- foreach my $command (keys(%{$self->{'commands_translation'}->{$context}})) {
- $translated_commands{$command} = 1;
- delete $self->{'commands_formatting'}->{$context}->{$command};
- if (defined($self->{'commands_translation'}->{$context}->{$command})) {
- $self->{'commands_formatting'}->{$context}->{$command}
- = $self->gdt($self->{'commands_translation'}->{$context}->{$command},
- undef, 'translated_text');
- }
- }
- }
- foreach my $command(keys(%translated_commands)) {
- $self->_complete_commands_formatting($command);
- }
- }
- }
- # insert here name of icon images for buttons
- # Icons are used, if ICONS and resp. value are set
- my %ACTIVE_ICONS = (
- 'Top', '',
- 'Contents', '',
- 'Overview', '',
- 'Index', '',
- 'This', '',
- 'Back', '',
- 'FastBack', '',
- 'Prev', '',
- 'Up', '',
- 'Next', '',
- 'NodeUp', '',
- 'NodeNext', '',
- 'NodePrev', '',
- 'NodeForward', '',
- 'NodeBack', '',
- 'Forward', '',
- 'FastForward', '',
- 'About' , '',
- 'First', '',
- 'Last', '',
- 'NextFile', '',
- 'PrevFile', '',
- ' ', '',
- );
- # insert here name of icon images for these, if button is inactive
- my %PASSIVE_ICONS = (
- 'Top', '',
- 'Contents', '',
- 'Overview', '',
- 'Index', '',
- 'This', '',
- 'Back', '',
- 'FastBack', '',
- 'Prev', '',
- 'Up', '',
- 'Next', '',
- 'NodeUp', '',
- 'NodeNext', '',
- 'NodePrev', '',
- 'NodeForward', '',
- 'NodeBack', '',
- 'Forward', '',
- 'FastForward', '',
- 'About', '',
- 'First', '',
- 'Last', '',
- 'NextFile', '',
- 'PrevFile', '',
- );
- my %defaults = (
- 'ENABLE_ENCODING' => 0,
- 'SHOW_MENU' => 1,
- 'OUTPUT_ENCODING_NAME' => 'utf-8',
- #'encoding_name' => undef,
- #'perl_encoding' => undef,
- 'OUTFILE' => undef,
- 'SUBDIR' => undef,
- 'USE_NODES' => 1,
- 'INLINE_CONTENTS' => 1,
- 'SPLIT' => 'node',
- # if set style is added in attribute.
- 'INLINE_CSS_STYLE' => 0,
- # if set, no css is used.
- 'NO_CSS' => 0,
- # if set, use node anchors for sections targets
- 'USE_NODE_TARGET' => 1,
- 'OPEN_QUOTE_SYMBOL' => '‘',
- 'CLOSE_QUOTE_SYMBOL' => '’',
- 'USE_ISO' => 1,
- # file name used for Top node when NODE_FILENAMES is true
- 'TOP_NODE_FILE' => 'index',
- 'NODE_FILE_EXTENSION' => 'html',
- 'EXTENSION' => 'html',
- 'TOP_NODE_FILE_TARGET' => 'index',
- 'TRANSLITERATE_FILE_NAMES' => 1,
- 'USE_LINKS' => 1,
- 'USE_NUMERIC_ENTITY' => 1,
- 'ENABLE_ENCODING_USE_ENTITY' => 1,
- 'DATE_IN_HEADER' => 0,
- 'AVOID_MENU_REDUNDANCY' => 0,
- 'HEADERS' => 1,
- 'DO_ABOUT' => 0,
- 'USE_ACCESSKEY' => 1,
- 'USE_REL_REV' => 1,
- 'NODE_NAME_IN_MENU' => 1,
- 'NODE_NAME_IN_INDEX' => 1,
- 'XREF_USE_NODE_NAME_ARG' => undef,
- 'XREF_USE_FLOAT_LABEL' => 0,
- 'OVERVIEW_LINK_TO_TOC' => 1,
- 'COMPLEX_FORMAT_IN_TABLE' => 0,
- 'WORDS_IN_PAGE' => 300,
- 'SECTION_BUTTONS' => [[ 'NodeNext', \&_default_node_direction ],
- [ 'NodePrev', \&_default_node_direction ],
- [ 'NodeUp', \&_default_node_direction ], ' ',
- 'Contents', 'Index'],
- 'LINKS_BUTTONS' => ['Top', 'Index', 'Contents', 'About',
- 'NodeUp', 'NextFile', 'PrevFile'],
- # 'TOP_BUTTONS' => ['Back', 'Forward', ' ',
- # 'Contents', 'Index', 'About'],
- #
- # 'MISC_BUTTONS' => [ 'Top', 'Contents', 'Index', 'About' ],
- # 'CHAPTER_BUTTONS' => [ 'FastBack', 'FastForward', ' ',
- # ' ', ' ', ' ', ' ',
- # 'Top', 'Contents', 'Index', 'About', ],
- # 'SECTION_FOOTER_BUTTONS' => [ 'FastBack', 'Back', 'Up', 'Forward', 'FastForward' ],
- # 'NODE_FOOTER_BUTTONS' => [ 'FastBack', 'Back', 'Up', 'Forward', 'FastForward' ],
- 'misc_elements_targets' => {
- 'Overview' => 'SEC_Overview',
- 'Contents' => 'SEC_Contents',
- 'Footnotes' => 'SEC_Foot',
- 'About' => 'SEC_About',
- 'Top' => 'SEC_Top',
- },
- 'misc_pages_file_string' => {
- 'Contents' => '_toc',
- 'Overview' => '_ovr',
- 'Footnotes' => '_fot',
- 'About' => '_abt',
- },
- 'frame_pages_file_string' => {
- 'Frame' => '_frame',
- 'Toc_Frame' => '_toc_frame',
- },
- 'misc_elements_order' => ['Footnotes', 'Contents', 'Overview', 'About'],
- 'DOCTYPE' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
- 'FRAMESET_DOCTYPE' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
- 'DEFAULT_RULE' => '<hr>',
- 'BIG_RULE' => '<hr>',
- 'MENU_SYMBOL' => '•',
- 'MENU_ENTRY_COLON' => ':',
- 'INDEX_ENTRY_COLON' => ':',
- 'BODYTEXT' => undef,
- 'documentlanguage' => 'en',
- 'xrefautomaticsectiontitle' => 'off',
- 'SHOW_TITLE' => 1,
- 'USE_TITLEPAGE_FOR_TITLE' => 0,
- 'MONOLITHIC' => 1,
- 'CHAPTER_HEADER_LEVEL' => 2,
- 'MAX_HEADER_LEVEL' => 4,
- 'FOOTNOTE_END_HEADER_LEVEL' => 4,
- 'FOOTNOTE_SEPARATE_HEADER_LEVEL' => 4,
-
- 'BUTTONS_REL' => \%BUTTONS_REL,
- 'BUTTONS_ACCESSKEY' => \%BUTTONS_ACCESSKEY,
- 'BUTTONS_EXAMPLE' => \%BUTTONS_EXAMPLE,
- 'BUTTONS_GOTO' => \%BUTTONS_GOTO,
- 'BUTTONS_NAME' => \%BUTTONS_NAME,
- 'BUTTONS_TEXT' => \%BUTTONS_TEXT,
- 'ACTIVE_ICONS' => \%ACTIVE_ICONS,
- 'PASSIVE_ICONS' => \%PASSIVE_ICONS,
- 'SPECIAL_ELEMENTS_NAME' => \%SPECIAL_ELEMENTS_NAME,
- 'SPECIAL_ELEMENTS_CLASS' => {
- 'About' => 'about',
- 'Contents' => 'contents',
- 'Overview' => 'shortcontents',
- 'Footnotes' => 'footnotes',
- },
-
- 'output_format' => 'html',
- );
- foreach my $buttons ('CHAPTER_BUTTONS', 'SECTION_FOOTER_BUTTONS', 'NODE_FOOTER_BUTTONS',
- 'MISC_BUTTONS', 'TOP_BUTTONS') {
- $defaults{$buttons} = [@{$defaults{'SECTION_BUTTONS'}}];
- }
- sub converter_defaults($$)
- {
- my $self = shift;
- my $conf = shift;
- if (defined($conf->{'TEXI2HTML'})) {
- _set_variables_texi2html();
- }
- return %defaults;
- }
- my $NO_BULLET_LIST_STYLE = 'list-style: none';
- my $NO_BULLET_LIST_CLASS = 'no-bullet';
- my $NO_BULLET_LIST_ATTRIBUTE = ' class="'.$NO_BULLET_LIST_CLASS.'"';
- my $MENU_PRE_STYLE = 'font-family: serif';
- my %css_map = (
- "ul.$NO_BULLET_LIST_CLASS" => "$NO_BULLET_LIST_STYLE",
- 'pre.menu-comment' => "$MENU_PRE_STYLE",
- 'pre.menu-preformatted' => "$MENU_PRE_STYLE",
- 'a.summary-letter' => 'text-decoration: none',
- 'blockquote.smallquotation' => 'font-size: smaller',
- 'pre.display' => 'font-family: inherit',
- 'pre.smalldisplay' => 'font-family: inherit; font-size: smaller',
- 'pre.smallexample' => 'font-size: smaller',
- 'span.sansserif' => 'font-family: sans-serif; font-weight: normal',
- 'span.roman' => 'font-family: initial; font-weight: normal',
- 'span.nolinebreak' => 'white-space: nowrap',
- 'kbd' => 'font-style: oblique',
- );
- $css_map{'pre.format'} = $css_map{'pre.display'};
- $css_map{'pre.smallformat'} = $css_map{'pre.smalldisplay'};
- $css_map{'pre.smalllisp'} = $css_map{'pre.smallexample'};
- my %preformatted_commands_context = %preformatted_commands;
- $preformatted_commands_context{'verbatim'} = 1;
- my %pre_class_commands;
- foreach my $preformatted_command (keys(%preformatted_commands_context)) {
- $pre_class_commands{$preformatted_command} = $preformatted_command;
- }
- $pre_class_commands{'menu'} = 'menu-preformatted';
- $pre_class_types{'menu_comment'} = 'menu-comment';
- my %indented_preformatted_commands;
- foreach my $indented_format ('example', 'display', 'lisp') {
- $indented_preformatted_commands{$indented_format} = 1;
- $indented_preformatted_commands{"small$indented_format"} = 1;
- $css_map{"div.$indented_format"} = 'margin-left: 3.2em';
- $css_map{"div.small$indented_format"} = 'margin-left: 3.2em';
- }
- $css_map{"blockquote.indentedblock"} = 'margin-right: 0em';
- $css_map{"blockquote.smallindentedblock"}
- = 'margin-right: 0em; font-size: smaller';
- # types that are in code style in the default case
- my %default_code_types = (
- '_code' => 1,
- );
- # default specification of arguments formatting
- my %default_commands_args = (
- 'email' => [['monospace', 'monospacestring'], ['normal']],
- 'anchor' => [['monospacestring']],
- 'uref' => [['monospacestring'], ['normal'], ['normal']],
- 'url' => [['monospacestring'], ['normal'], ['normal']],
- 'printindex' => [[]],
- 'sp' => [[]],
- 'inforef' => [['monospace'],['normal'],['monospacetext']],
- 'xref' => [['monospace'],['normal'],['normal'],['monospacetext'],['normal']],
- 'pxref' => [['monospace'],['normal'],['normal'],['monospacetext'],['normal']],
- 'ref' => [['monospace'],['normal'],['normal'],['monospacetext'],['normal']],
- 'image' => [['monospacetext'],['monospacetext'],['monospacetext'],['string', 'normal'],['monospacetext']],
- # FIXME shouldn't it better not to convert if later ignored?
- 'inlinefmt' => [['monospacetext'],['normal']],
- 'inlinefmtifelse' => [['monospacetext'],['normal'],['normal']],
- 'inlineraw' => [['monospacetext'],['raw']],
- 'inlineifclear' => [['monospacetext'],['normal']],
- 'inlineifset' => [['monospacetext'],['normal']],
- 'item' => [[]],
- 'itemx' => [[]],
- );
- foreach my $explained_command (keys(%explained_commands)) {
- $default_commands_args{$explained_command}
- = [['normal'], ['string']];
- }
- # Default for the function references used for the formatting
- # of commands.
- my %default_commands_conversion;
- sub default_commands_conversion($$)
- {
- my $self = shift;
- my $command = shift;
- return $default_commands_conversion{$command};
- }
- my %kept_misc_commands;
- my @informative_global_commands = ('contents', 'shortcontents',
- 'summarycontents', 'allowcodebreaks', 'documentlanguage',
- 'footnotestyle', 'documentencoding',
- 'xrefautomaticsectiontitle', 'deftypefnnewline');
- # taken from global
- # 'documentencoding'
- # 'novalidate'
- foreach my $misc_command(@informative_global_commands,
- 'verbatiminclude', 'insertcopying', 'printindex', 'listoffloats',
- 'author', 'subtitle',
- 'title', keys(%default_index_commands),
- keys(%formatting_misc_commands)) {
- $kept_misc_commands{$misc_command} = 1;
- }
- sub converter_global_commands($)
- {
- return @informative_global_commands;
- }
- my %contents_commands = (
- 'contents' => 1,
- 'shortcontents' => 1,
- 'summarycontents' => 1,
- );
- #my %ignored_misc_commands;
- foreach my $misc_command (keys(%misc_commands)) {
- # $ignored_misc_commands{$misc_command} = 1
- $default_commands_conversion{$misc_command} = undef
- unless ($kept_misc_commands{$misc_command});
- }
- foreach my $ignored_brace_commands ('caption', 'shortcaption',
- 'hyphenation', 'sortas') {
- #$ignored_commands{$ignored_brace_commands} = 1;
- $default_commands_conversion{$ignored_brace_commands} = undef;
- }
- # commands that leads to advancing the paragraph number. This is mostly
- #used to determine the first line, in fact.
- my %advance_paragraph_count_commands;
- foreach my $command (keys(%block_commands)) {
- next if ($menu_commands{$command}
- or $block_commands{$command} eq 'raw');
- $advance_paragraph_count_commands{$command} = 1;
- }
- foreach my $ignored_block_commands ('ignore', 'macro', 'rmacro', 'copying',
- 'documentdescription', 'titlepage', 'direntry') {
- #$ignored_commands{$ignored_block_commands} = 1;
- $default_commands_conversion{$ignored_block_commands} = undef;
- };
- # Formatting of commands without args
- # The hash holding the defaults for the formatting of
- # most commands without args
- my %default_commands_formatting;
- foreach my $command (keys(%{$Texinfo::Convert::Converter::default_xml_commands_formatting{'normal'}})) {
- $default_commands_formatting{'normal'}->{$command} =
- $Texinfo::Convert::Converter::default_xml_commands_formatting{'normal'}->{$command};
- }
- $default_commands_formatting{'normal'}->{' '} = ' ';
- $default_commands_formatting{'normal'}->{"\t"} = ' ';
- $default_commands_formatting{'normal'}->{"\n"} = ' ';
- my %default_commands_translation;
- # possible example of use, right now not used, as the generic
- # translated command with gdt tree is used.
- #$default_commands_translation{'normal'}->{'error'} = 'error-->';
- ## This is used to have gettext pick up the chain to be translated
- #if (0) {
- # my $not_existing;
- # $not_existing->gdt('error-->');
- #}
- #foreach my $command (keys(%{$default_commands_formatting{'normal'}})) {
- # $default_commands_formatting{'preformatted'}->{$command} =
- # $default_commands_formatting{'normal'}->{$command};
- # $default_commands_formatting{'string'}->{$command} =
- # $default_commands_formatting{'normal'}->{$command};
- #}
- $default_commands_formatting{'normal'}->{'enddots'}
- = '<small class="enddots">...</small>';
- $default_commands_formatting{'preformatted'}->{'enddots'} = '...';
- $default_commands_formatting{'normal'}->{'*'} = '<br>';
- $default_commands_formatting{'preformatted'}->{'*'} = "\n";
- sub _convert_no_arg_command($$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- if ($cmdname eq 'click' and $command->{'extra'}
- and exists($command->{'extra'}->{'clickstyle'})) {
- my $click_cmdname = $command->{'extra'}->{'clickstyle'};
- if (($self->in_preformatted() or $self->in_math()
- and $self->{'commands_formatting'}->{'preformatted'}->{$click_cmdname})
- or ($self->in_string() and
- $self->{'commands_formatting'}->{'string'}->{$click_cmdname})
- or ($self->{'commands_formatting'}->{'normal'}->{$click_cmdname})) {
- $cmdname = $click_cmdname;
- }
- }
- if ($self->in_upper_case() and $letter_no_arg_commands{$cmdname}
- and $self->{'commands_formatting'}->{'normal'}->{uc($cmdname)}) {
- $cmdname = uc($cmdname);
- }
- my $result;
- if ($self->{'translated_commands'}->{$cmdname}) {
- return $self->convert_tree(
- $self->gdt($self->{'translated_commands'}->{$cmdname}));
- }
- if ($self->in_preformatted() or $self->in_math()) {
- $result = $self->{'commands_formatting'}->{'preformatted'}->{$cmdname};
- } elsif ($self->in_string()) {
- $result = $self->{'commands_formatting'}->{'string'}->{$cmdname};
- } else {
- $result = $self->{'commands_formatting'}->{'normal'}->{$cmdname};
- }
- return $result;
- }
- foreach my $command(keys(%{$default_commands_formatting{'normal'}})) {
- $default_commands_conversion{$command} = \&_convert_no_arg_command;
- }
- sub _convert_today_command($$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $tree = $self->Texinfo::Common::expand_today();
- return $self->convert_tree($tree);
- }
- $default_commands_conversion{'today'} = \&_convert_today_command;
- # style commands
- my %quoted_style_commands;
- foreach my $quoted_command ('samp') {
- $quoted_style_commands{$quoted_command} = 1;
- }
- my %style_attribute_commands;
- $style_attribute_commands{'normal'} = {
- 'b' => 'b',
- 'cite' => 'cite',
- 'code' => 'code',
- 'command' => 'code',
- 'dfn' => 'em',
- 'emph' => 'em',
- 'env' => 'code',
- 'file' => 'samp',
- 'headitemfont' => 'b', # not really that, in fact it is
- # in <th> rather than <td>
- 'i' => 'i',
- 'slanted' => 'i',
- 'sansserif' => 'span class="sansserif"',
- 'kbd' => 'kbd',
- 'option' => 'samp',
- 'r' => 'span class="roman"',
- 'samp' => 'samp',
- 'sc' => 'small',
- 'strong' => 'strong',
- 'sub' => 'sub',
- 'sup' => 'sup',
- 't' => 'tt',
- 'var' => 'var',
- 'verb' => 'tt',
- 'math' => 'em',
- };
- my %style_commands_formatting;
- # this weird construct does like uniq, it avoids duplicates.
- # it is required since math is not in the %style_commands as it is
- # in context command.
- my @all_style_commands = keys %{{ map { $_ => 1 }
- (keys(%style_commands), keys(%{$style_attribute_commands{'normal'}}),
- 'dmn') }};
- foreach my $command(@all_style_commands) {
- # default is no attribute.
- if ($style_attribute_commands{'normal'}->{$command}) {
- $style_commands_formatting{'normal'}->{$command}->{'attribute'}
- = $style_attribute_commands{'normal'}->{$command};
- $style_commands_formatting{'preformatted'}->{$command}->{'attribute'}
- = $style_attribute_commands{'normal'}->{$command};
- }
- if ($style_attribute_commands{'preformatted'}->{$command}) {
- $style_commands_formatting{'preformatted'}->{$command}->{'attribute'} =
- $style_attribute_commands{'preformatted'}->{$command};
- }
- if ($quoted_style_commands{$command}) {
- foreach my $context ('normal', 'string', 'preformatted') {
- $style_commands_formatting{$context}->{$command}->{'quote'} = 1;
- }
- }
- $default_commands_conversion{$command} = \&_convert_style_command;
- }
- delete $style_commands_formatting{'preformatted'}->{'sc'}->{'attribute'};
- delete $style_commands_formatting{'preformatted'}->{'sc'};
- sub _parse_attribute($)
- {
- my $element = shift;
- return ('', '', '') if (!defined($element));
- my ($class, $attributes) = ('', '');
- if ($element =~ /^(\w+)(\s+.*)/)
- {
- $element = $1;
- $attributes = $2;
- if ($attributes =~ s/^\s+class=\"([^\"]+)\"//) {
- $class = $1;
- }
- }
- return ($element, $class, $attributes);
- }
- sub _convert_style_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $text = $args->[0]->{'normal'};
- if (!defined($text)) {
- # happens with bogus @-commands without argument, like @strong something
- #cluck "text not defined in _convert_style_command";
- return '';
- }
- # handle the effect of kbdinputstyle
- if ($cmdname eq 'kbd' and $command->{'extra'}
- and $command->{'extra'}->{'code'}) {
- $cmdname = 'code';
- }
- my $attribute_hash = {};
- if ($self->in_preformatted()) {
- $attribute_hash = $self->{'style_commands_formatting'}->{'preformatted'};
- } elsif (!$self->in_string()) {
- $attribute_hash = $self->{'style_commands_formatting'}->{'normal'};
- }
- if (defined($attribute_hash->{$cmdname})) {
- if (defined($attribute_hash->{$cmdname}->{'attribute'})) {
- my ($style, $class, $attribute_text)
- = _parse_attribute ($attribute_hash->{$cmdname}->{'attribute'});
- my $open = $self->_attribute_class($style, $class);
- if ($open ne '') {
- $text = $open . "$attribute_text>"
- . $text . "</$style>";
- } elsif ($attribute_text ne '') {
- $text = "<$style $attribute_text>". $text . "</$style>";
- }
- }
- if (defined($attribute_hash->{$cmdname}->{'quote'})) {
- $text = $self->get_conf('OPEN_QUOTE_SYMBOL') . $text
- . $self->get_conf('CLOSE_QUOTE_SYMBOL');
- }
- }
- return $text;
- }
- sub _convert_w_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $text = $args->[0]->{'normal'};
- if (!defined($text)) {
- $text = '';
- }
- if ($self->in_string) {
- return $text;
- } else {
- return $text . '<!-- /@w -->';
- }
- }
- $default_commands_conversion{'w'} = \&_convert_w_command;
- sub _convert_value_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- return $self->convert_tree($self->gdt('@{No value for `{value}\'@}',
- {'value' => $command->{'type'}}));
- }
- $default_commands_conversion{'value'} = \&_convert_value_command;
- sub _convert_email_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $mail_arg = shift @$args;
- my $text_arg = shift @$args;
- my $mail = '';
- my $mail_string = '';
- if (defined($mail_arg)) {
- $mail = $mail_arg->{'monospace'};
- $mail_string = $mail_arg->{'monospacestring'};
- }
- my $text = '';
- if (defined($text_arg)) {
- $text = $text_arg->{'normal'};
- }
- $text = $mail unless ($text ne '');
- return $text if ($mail eq '');
- if ($self->in_string()) {
- return "$mail_string ($text)";
- } else {
- return "<a href=\"mailto:$mail_string\">$text</a>";
- }
- }
- $default_commands_conversion{'email'} = \&_convert_email_command;
- sub _convert_explained_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $with_explanation;
- my $explanation_result;
- my $explanation_string;
- my $normalized_type
- = Texinfo::Convert::NodeNameNormalization::normalize_node(
- {'contents' =>
- $command->{'extra'}->{'brace_command_contents'}->[0]});
- if ($args->[1] and defined($args->[1]->{'string'})
- and $args->[1]->{'string'} =~ /\S/) {
- $with_explanation = 1;
- $explanation_string = $args->[1]->{'string'};
- # Convert the expanation of the acronym. Must do this before we save
- # the explanation for the future, otherwise we get infinite recursion
- # for recursively-defined acronyms.
- $explanation_result = $self->convert_tree( $args->[1]->{'tree'} );
- $self->{'explained_commands'}->{$cmdname}->{$normalized_type} =
- $command->{'extra'}->{'brace_command_contents'}->[1];
- } elsif ($command->{'extra'}->{'explanation_contents'}) {
- if (@{$command->{'extra'}->{'explanation_contents'}}) {
- $explanation_string = $self->convert_tree_new_formatting_context(
- {'type' => '_string',
- 'contents' => $command->{'extra'}->{'explanation_contents'}},
- $cmdname, $cmdname);
- }
- } elsif ($self->{'explained_commands'}->{$cmdname}->{$normalized_type}) {
- $explanation_string = $self->convert_tree_new_formatting_context(
- {'type' => '_string',
- 'contents' => $self->{'explained_commands'}
- ->{$cmdname}->{$normalized_type}},
- $cmdname, $cmdname);
- $command->{'extra'}->{'explanation_contents'}
- = $self->{'explained_commands'}->{$cmdname}->{$normalized_type};
- } else {
- # Avoid ever giving an explanation for this element. This prevents
- # infinite recursion for a recursively-defined acronym, when an
- # @acronym within the explanation could end up referring to the
- # containing @acronym.
- $command->{'extra'}->{'explanation_contents'} = [];
- }
- my $result = $args->[0]->{'normal'};
- if (!$self->in_string()) {
- if (defined($explanation_string)) {
- $result = "<$cmdname title=\"$explanation_string\">".$result;
- } else {
- $result = "<$cmdname>".$result;
- }
- $result .= "</$cmdname>";
- }
- if ($with_explanation) {
- $result = $self->convert_tree($self->gdt('{explained_string} ({explanation})',
- {'explained_string' => {'type' => '_converted',
- 'text' => $result},
- 'explanation' => {'type' => '_converted',
- 'text' => $explanation_result}}));
- }
- return $result;
- }
- foreach my $explained_command (keys(%explained_commands)) {
- $default_commands_conversion{$explained_command}
- = \&_convert_explained_command;
- }
- sub _convert_anchor_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $id = $self->command_id($command);
- if (defined($id) and $id ne '' and !@{$self->{'multiple_pass'}}
- and !$self->in_string()) {
- return "<a name=\"$id\"></a>";
- }
- return '';
- }
- $default_commands_conversion{'anchor'} = \&_convert_anchor_command;
- my $foot_num;
- my $foot_lines;
- my $NO_NUMBER_FOOTNOTE_SYMBOL = '*';
- my $footid_base = 'FOOT';
- my $docid_base = 'DOCF';
- # to avoid duplicate names, use a prefix that cannot happen in anchors
- my $target_prefix = "t_h";
- my %footnote_id_numbers;
- sub _convert_footnote_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $number_in_doc;
- $foot_num++;
- if ($self->get_conf('NUMBER_FOOTNOTES')) {
- $number_in_doc = $foot_num;
- } else {
- $number_in_doc = $NO_NUMBER_FOOTNOTE_SYMBOL;
- }
-
- return "($number_in_doc)" if ($self->in_string());
- #print STDERR "FOOTNOTE $command\n";
- my $footid = $self->command_target($command);
- # happens for bogus footnotes
- if (!defined($footid)) {
- return '';
- }
- # ID for linking back to the main text from the footnote.
- my $docid = $footid;
- $docid =~ s/^$footid_base/$docid_base/;
- my $document_filename;
- my $footnote_filename;
- if ($self->get_conf('footnotestyle') eq 'separate') {
- $footnote_filename = $self->command_filename($command);
- $document_filename = $self->{'current_filename'};
- $footnote_filename = '' if (!defined($footnote_filename));
- $document_filename = '' if (!defined($document_filename));
- if ($document_filename eq $footnote_filename) {
- $document_filename = $footnote_filename = '';
- }
- } else {
- $document_filename = $footnote_filename = '';
- }
- my $footnote_text;
- if ($args->[0]) {
- $footnote_text = $args->[0]->{'normal'};
- } else {
- $footnote_text = '';
- }
- chomp ($footnote_text);
- $footnote_text .= "\n";
- if (@{$self->{'multiple_pass'}}) {
- $footid = $target_prefix.$self->{'multiple_pass'}->[-1].'_'.$footid.'_'.$foot_num;
- $docid = $target_prefix.$self->{'multiple_pass'}->[-1].'_'.$docid.'_'.$foot_num;
- } else {
- if (!defined($footnote_id_numbers{$footid})) {
- $footnote_id_numbers{$footid} = $foot_num;
- } else {
- # This should rarely happen, except for @footnote is @copying and
- # multiple @insertcopying...
- # Here it is not checked that there is no clash with another anchor.
- # However, unless there are more than 1000 footnotes this should not
- # happen.
- $footid .= '_'.$foot_num;
- $docid .= '_'.$foot_num;
- }
- }
- $foot_lines .= '<h3>' .
- "<a name=\"$footid\" href=\"$document_filename#$docid\">($number_in_doc)</a></h3>\n"
- . $footnote_text;
- my $footnote_number_text;
- if ($self->in_preformatted()) {
- $footnote_number_text = "($number_in_doc)";
- } else {
- $footnote_number_text = "<sup>$number_in_doc</sup>";
- }
- return "<a name=\"$docid\" href=\"$footnote_filename#$footid\">$footnote_number_text</a>";
- }
- $default_commands_conversion{'footnote'} = \&_convert_footnote_command;
- sub _convert_uref_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my @args = @$args;
- my $url_arg = shift @args;
- my $text_arg = shift @args;
- my $replacement_arg = shift @args;
- my ($url, $text, $replacement);
- $url = $url_arg->{'monospacestring'} if defined($url_arg);
- $text = $text_arg->{'normal'} if defined($text_arg);
- $replacement = $replacement_arg->{'normal'} if defined($replacement_arg);
- $text = $replacement if (defined($replacement) and $replacement ne '');
- $text = $url if (!defined($text) or $text eq '');
- return $text if (!defined($url) or $url eq '');
- return "$text ($url)" if ($self->in_string());
- return "<a href=\"$url\">$text</a>";
- }
- $default_commands_conversion{'uref'} = \&_convert_uref_command;
- $default_commands_conversion{'url'} = \&_convert_uref_command;
- my @image_files_extensions = ('.png', '.jpg', '.jpeg', '.gif');
- sub _convert_image_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my @extensions = @image_files_extensions;
- if (defined($args->[0]->{'monospacetext'}) and $args->[0]->{'monospacetext'} ne '') {
- my $basefile = $args->[0]->{'monospacetext'};
- return $basefile if ($self->in_string());
- my $extension;
- if (defined($args->[4]) and defined($args->[4]->{'monospacetext'})) {
- $extension = $args->[4]->{'monospacetext'};
- unshift @extensions, ("$extension", ".$extension");
- }
- my $image_file;
- foreach my $extension (@extensions) {
- if ($self->Texinfo::Common::locate_include_file ($basefile.$extension)) {
- # use the basename and not the file found. It is agreed that it is
- # better, since in any case the files are moved.
- $image_file = $basefile.$extension;
- last;
- }
- }
- if (!defined($image_file) or $image_file eq '') {
- if (defined($extension) and $extension ne '') {
- $image_file = "$basefile.$extension";
- } else {
- $image_file = "$basefile.jpg";
- }
- #cluck "err ($self->{'ignore_notice'})";
- $self->line_warn(sprintf(
- $self->__("\@image file `%s' (for HTML) not found, using `%s'"),
- $basefile, $image_file), $command->{'line_nr'});
- }
- if (defined($self->get_conf('IMAGE_LINK_PREFIX'))) {
- $image_file = $self->get_conf('IMAGE_LINK_PREFIX') . $image_file;
- }
- if ($self->in_preformatted()) {
- my $alt_text;
- if (defined($args->[3]) and defined($args->[3]->{'normal'})) {
- $alt_text = $args->[3]->{'normal'};
- }
- if (!defined($alt_text) or ($alt_text eq '')) {
- $alt_text = $self->protect_text($basefile);
- }
- return "[ $alt_text ]";
- } else {
- my $alt_string;
- if (defined($args->[3]) and defined($args->[3]->{'string'})) {
- $alt_string = $args->[3]->{'string'};
- }
- if (!defined($alt_string) or ($alt_string eq '')) {
- $alt_string = $self->protect_text($basefile);
- }
- return "<img src=\"".$self->protect_text($image_file)."\" alt=\"$alt_string\">";
- }
- }
- return '';
- }
- $default_commands_conversion{'image'} = \&_convert_image_command;
- #sub _convert_math_command($$$$)
- #{
- # my $self = shift;
- # my $cmdname = shift;
- # my $command = shift;
- # my $args = shift;
- #
- # return $args->[0]->{'normal'};
- #}
- #$default_commands_conversion{'math'} = \&_convert_math_command;
- sub _convert_accent_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- return $self->xml_accents($command, $self->in_upper_case());
- }
- foreach my $command (keys(%accent_commands)) {
- $default_commands_conversion{$command} = \&_convert_accent_command;
- }
- # key is formatted as code since it is in code_style_commands
- sub _convert_key_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $text = $args->[0]->{'normal'};
- if (!defined($text)) {
- # happens with bogus @-commands without argument, like @strong something
- return '';
- }
- if ($self->in_string()) {
- return $text;
- }
- #return $self->protect_text('<') .$text .$self->protect_text('>');
- my $class = $cmdname;
- if (!$self->in_code()) {
- return $self->_attribute_class('tt', $class).'>'.$text .'</tt>';;
- } else {
- my $open = $self->_attribute_class('span', $class);
- if ($open ne '') {
- return $open.'>'.$text.'</span>';
- } else {
- return $text;
- }
- }
- }
- $default_commands_conversion{'key'} = \&_convert_key_command;
- # argument is formatted as code since indicateurl is in code_style_commands
- sub _convert_indicateurl_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $text = $args->[0]->{'normal'};
- if (!defined($text)) {
- # happens with bogus @-commands without argument, like @strong something
- return '';
- }
- if (!$self->in_string()) {
- return $self->get_conf('OPEN_QUOTE_SYMBOL').'<code>' .$text
- .'</code>'.$self->get_conf('CLOSE_QUOTE_SYMBOL');
- } else {
- return $self->get_conf('OPEN_QUOTE_SYMBOL').$text.
- $self->get_conf('CLOSE_QUOTE_SYMBOL');
- }
- }
- $default_commands_conversion{'indicateurl'} = \&_convert_indicateurl_command;
- sub _convert_ctrl_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $text = $args->[0]->{'normal'};
- if (!defined($text)) {
- # happens with bogus @-commands without argument, like @strong something
- return '';
- }
- return $self->protect_text('^') .$text;
- }
- $default_commands_conversion{'ctrl'} = \&_convert_ctrl_command;
- sub _convert_titlefont_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $text = $args->[0]->{'normal'};
- if (!defined($text)) {
- # happens with bogus @-commands without argument, like @strong something
- return '';
- }
- return &{$self->{'format_heading_text'}}($self, 'titlefont', $text, 0, $command);
- }
- $default_commands_conversion{'titlefont'} = \&_convert_titlefont_command;
- sub _convert_U_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $arg = $args->[0]->{'normal'};
- my $res;
- if (defined($arg) && $arg) {
- # checks on the value already done in Parser, just output it here.
- $res = "&#x$arg;";
- } else {
- $res = '';
- }
- return $res;
- }
- $default_commands_conversion{'U'} = \&_convert_U_command;
- sub _default_comment($$) {
- my $self = shift;
- my $text = shift;
- return $self->xml_comment(' '.$text);
- }
- sub protect_text($$) {
- my $self = shift;
- my $text = shift;
- return &{$self->{'format_protect_text'}}($self, $text);
- }
- sub _default_protect_text($$) {
- my $self = shift;
- my $text = shift;
- my $result = $self->xml_protect_text($text);
- $result =~ s/\f//g;
- return $result;
- }
- sub _default_heading_text($$$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $text = shift;
- my $level = shift;
- my $command = shift;
- return '' if ($text !~ /\S/);
- # This should seldom happen.
- if ($self->in_string()) {
- $text .= "\n" unless ($cmdname eq 'titlefont');
- return $text;
- }
- my $class;
- if ($cmdname eq 'node') {
- $class = 'node-heading';
- } else {
- $class = $cmdname;
- }
- my $align = '';
- $align = ' align="center"' if ($cmdname eq 'centerchap' or $cmdname eq 'settitle');
- if ($level < 1) {
- $level = 1;
- } elsif ($level > $self->get_conf('MAX_HEADER_LEVEL')) {
- $level = $self->get_conf('MAX_HEADER_LEVEL');
- }
- my $result = $self->_attribute_class("h$level", $class) ."$align>$text</h$level>";
- # titlefont appears inline in text, so no end of line is
- # added. The end of line should be added by the user if needed.
- $result .= "\n" unless ($cmdname eq 'titlefont');
- $result .= $self->get_conf('DEFAULT_RULE') . "\n"
- if ($cmdname eq 'part'
- and defined($self->get_conf('DEFAULT_RULE'))
- and $self->get_conf('DEFAULT_RULE') ne '');
- return $result;
- }
- # Associated to a button
- sub _default_node_direction($$)
- {
- my $self = shift;
- my $direction = shift;
-
- my $result = undef;
- my $href = $self->_element_direction($self->{'current_element'},
- $direction, 'href');
- my $node = $self->_element_direction($self->{'current_element'},
- $direction, 'node');
- my $anchor;
- if (defined($href) and defined($node) and $node =~ /\S/) {
- my $anchor_attributes = $self->_direction_href_attributes($direction);
- $anchor = "<a href=\"$href\"${anchor_attributes}>$node</a>";
- #} elsif (defined($node) and $node =~ /\S/) {
- # $anchor = $node;
- #} else {
- }
- if (defined($anchor)) {
- # i18n
- $result = $self->get_conf('BUTTONS_TEXT')->{$direction}.": $anchor";
- }
- return $result;
- }
- # how to create IMG tag
- # this is only used in html, and only if ICONS is set and the button
- # is active.
- sub _default_button_icon_img($$$;$)
- {
- my $self = shift;
- my $button = shift;
- my $icon = shift;
- my $name = shift;
- return '' if (!defined($icon));
- $button = "" if (!defined ($button));
- $name = '' if (!defined($name));
- my $alt = '';
- if ($name ne '') {
- if ($button ne '') {
- $alt = "$button: $name";
- } else {
- $alt = $name;
- }
- } else {
- $alt = $button;
- }
- return qq{<img src="$icon" border="0" alt="$alt" align="middle">};
- }
- sub _direction_href_attributes($$)
- {
- my $self = shift;
- my $direction = shift;
- my $href_attributes = '';
- if ($self->get_conf('USE_ACCESSKEY')
- and $self->get_conf('BUTTONS_ACCESSKEY')) {
- my $accesskey = $self->get_conf('BUTTONS_ACCESSKEY')->{$direction};
- if (defined($accesskey) and ($accesskey ne '')) {
- $href_attributes = " accesskey=\"$accesskey\"";
- }
- }
- if ($self->get_conf('USE_REL_REV') and $self->get_conf('BUTTONS_REL')) {
- my $button_rel = $self->get_conf('BUTTONS_REL')->{$direction};
- if (defined($button_rel) and ($button_rel ne '')) {
- $href_attributes .= " rel=\"$button_rel\"";
- }
- }
- return $href_attributes;
- }
- sub _default_button_formatting($$)
- {
- my $self = shift;
- my $button = shift;
- my ($active, $passive);
- if (ref($button) eq 'CODE') {
- $active = &$button($self);
- } elsif (ref($button) eq 'SCALAR') {
- $active = "$$button" if defined($$button);
- } elsif (ref($button) eq 'ARRAY' and scalar(@$button == 2)) {
- my $text = $button->[1];
- my $button_href = $button->[0];
- # verify that $button_href is simple text and text is a reference
- if (defined($button_href) and !ref($button_href)
- and defined($text) and (ref($text) eq 'SCALAR') and defined($$text)) {
- # use given text
- my $href = $self->_element_direction($self->{'current_element'},
- $button_href, 'href');
- if ($href) {
- my $anchor_attributes = $self->_direction_href_attributes($button_href);
- $active = "<a href=\"$href\"${anchor_attributes}>$$text</a>";
- } else {
- $passive = $$text;
- }
- # button_href is simple text and text is a reference on code
- } elsif (defined($button_href) and !ref($button_href)
- and defined($text) and (ref($text) eq 'CODE')) {
- $active = &$text($self, $button_href);
- # button_href is simple text and text is also a simple text
- } elsif (defined($button_href) and !ref($button_href)
- and defined($text) and !ref($text)) {
- if ($text =~ s/^->\s*//) {
- $active = $self->_element_direction($self->{'current_element'},
- $button_href, $text);
- } else {
- my $href = $self->_element_direction($self->{'current_element'},
- $button_href, 'href');
- my $text_formatted = $self->_element_direction($self->{'current_element'},
- $button_href, $text);
- if ($href) {
- my $anchor_attributes = $self->_direction_href_attributes($button_href);
- $active = "<a href=\"$href\"${anchor_attributes}>$text_formatted</a>";
- } else {
- $passive = $text_formatted;
- }
- }
- }
- } elsif ($button eq ' ') {
- # handle space button
- if ($self->get_conf('ICONS') and $self->get_conf('ACTIVE_ICONS')
- and defined($self->get_conf('ACTIVE_ICONS')->{$button})
- and $self->get_conf('ACTIVE_ICONS')->{$button} ne '') {
- my $button_name = $self->get_conf('BUTTONS_NAME')->{$button};
- $active = &{$self->{'format_button_icon_img'}}($self, $button_name,
- $self->get_conf('ACTIVE_ICONS')->{' '});
- } else {
- $active = $self->get_conf('BUTTONS_TEXT')->{$button};
- }
- } else {
- my $href = $self->_element_direction($self->{'current_element'},
- $button, 'href');
- if ($href) {
- # button is active
- my $btitle = '';
- if ($self->get_conf('BUTTONS_GOTO')
- and defined($self->get_conf('BUTTONS_GOTO')->{$button})) {
- $btitle = ' title="' . $self->get_conf('BUTTONS_GOTO')->{$button} . '"';
- }
- if ($self->get_conf('USE_ACCESSKEY') and $self->get_conf('BUTTONS_ACCESSKEY')) {
- my $accesskey = $self->get_conf('BUTTONS_ACCESSKEY')->{$button};
- if (defined($accesskey) and $accesskey ne '') {
- $btitle .= " accesskey=\"$accesskey\"";
- }
- }
- if ($self->get_conf('USE_REL_REV') and ($self->get_conf('BUTTONS_REL'))) {
- my $button_rel = $self->get_conf('BUTTONS_REL')->{$button};
- if (defined($button_rel) and $button_rel ne '') {
- $btitle .= " rel=\"$button_rel\"";
- }
- }
- my $use_icon;
- if ($self->get_conf('ICONS') and $self->get_conf('ACTIVE_ICONS')
- and $self->get_conf('BUTTONS_NAME')) {
- my $active_icon = $self->get_conf('ACTIVE_ICONS')->{$button};
- my $button_name = $self->get_conf('BUTTONS_NAME')->{$button};
- if (defined($active_icon) and $active_icon ne ''
- and defined($button_name)) {
- # use icon
- $active = "<a href=\"$href\"${btitle}>".
- &{$self->{'format_button_icon_img'}}($self, $button_name, $active_icon,
- $self->_element_direction($self->{'current_element'},
- $button, 'string')) ."</a>";
- $use_icon = 1;
- }
- }
- if (!$use_icon) {
- # use text
- $active = '[' . "<a href=\"$href\"${btitle}>".
- $self->get_conf('BUTTONS_TEXT')->{$button}."</a>" . ']';
- }
- } else {
- # button is passive
- my $use_icon;
- if ($self->get_conf('ICONS') and $self->get_conf('PASSIVE_ICONS')
- and $self->get_conf('BUTTONS_NAME')) {
- my $passive_icon = $self->get_conf('PASSIVE_ICONS')->{$button};
- my $button_name = $self->get_conf('BUTTONS_NAME')->{$button};
- if ($passive_icon and $passive_icon ne '') {
- $passive = &{$self->{'format_button_icon_img'}}($self, $button_name,
- $passive_icon,
- $self->_element_direction($self->{'current_element'},
- $button, 'string'));
- $use_icon = 1;
- }
- }
- if (!$use_icon) {
- $passive = '[' . $self->get_conf('BUTTONS_TEXT')->{$button} . ']';
- }
- }
- }
- return ($active, $passive);
- }
- my %html_default_node_directions;
- foreach my $node_directions ('NodeNext', 'NodePrev', 'NodeUp') {
- $html_default_node_directions{$node_directions} = 1;
- }
- sub _default_navigation_header_panel($$$$;$)
- {
- my $self = shift;
- my $buttons = shift;
- my $cmdname = shift;
- my $command = shift;
- my $vertical = shift;
- # if VERTICAL_HEAD_NAVIGATION, the buttons are in a vertical table which
- # is itself in the first column of a table opened in header_navigation
- #my $vertical = $self->get_conf('VERTICAL_HEAD_NAVIGATION');
- my $first_button = 1;
- my $result = '';
- if ($self->get_conf('HEADER_IN_TABLE')) {
- $result .= $self->_attribute_class('table', 'header')
- .' cellpadding="1" cellspacing="1" border="0">'."\n";
- $result .= "<tr>" unless $vertical;
- } else {
- $result .= $self->_attribute_class('div', 'header').">\n<p>\n";
- }
- foreach my $button (@$buttons) {
- if ($self->get_conf('HEADER_IN_TABLE')) {
- $result .= qq{<tr valign="top" align="left">\n} if $vertical;
- $result .= qq{<td valign="middle" align="left">};
- }
- my $direction;
- if (ref($button) eq 'ARRAY'
- and defined($button->[0]) and !ref($button->[0])) {
- $direction = $button->[0];
- } elsif (defined($button) and !ref($button)) {
- $direction = $button;
- }
- my ($active, $passive) = &{$self->{'format_button'}}($self, $button);
- if ($self->get_conf('HEADER_IN_TABLE')) {
- if (defined($active)) {
- $first_button = 0 if ($first_button);
- $result .= $active;
- } elsif (defined($passive)) {
- $first_button = 0 if ($first_button);
- $result .= $passive;
- }
- $result .= "</td>\n";
- $result .= "</tr>\n" if $vertical;
- } elsif (defined($active)) {
- # only active buttons are print out when not in table
- if (defined($direction)
- and $html_default_node_directions{$direction} and !$first_button) {
- $active = ', ' .$active;
- }
- $result .= $active;
- $first_button = 0 if ($first_button);
- }
- }
- if ($self->get_conf('HEADER_IN_TABLE')) {
- $result .= "</tr>" unless $vertical;
- $result .= "</table>\n";
- } else {
- $result .= "</p>\n</div>\n";
- }
- return $result;
- }
- sub _default_navigation_header($$$$)
- {
- my $self = shift;
- my $buttons = shift;
- my $cmdname = shift;
- my $command = shift;
- my $result = '';
- if ($self->get_conf('VERTICAL_HEAD_NAVIGATION')) {
- $result .= '<table border="0" cellpadding="0" cellspacing="0">
- <tr valign="top">
- <td align="left">
- ';
- }
- $result .= &{$self->{'format_navigation_header_panel'}}($self, $buttons,
- $cmdname, $command,
- $self->get_conf('VERTICAL_HEAD_NAVIGATION'));
- if ($self->get_conf('VERTICAL_HEAD_NAVIGATION')) {
- $result .= '</td>
- <td align="left">
- ';
- } elsif ($self->get_conf('SPLIT') eq 'node') {
- $result .= $self->get_conf('DEFAULT_RULE')."\n";
- }
- return $result;
- }
- sub _default_element_header($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $element = shift;
- my $result = '';
-
- print STDERR "Element $element (@{$element->{'contents'}}) ".
- Texinfo::Structuring::_print_element_command_texi($element) ."\n"
- if ($self->get_conf('DEBUG'));
- # Do the heading if the command is the first command in the element
- if (($element->{'contents'}->[0] eq $command
- or (!$element->{'contents'}->[0]->{'cmdname'}
- and $element->{'contents'}->[1] eq $command))
- # and there is more than one element
- and ($element->{'element_next'} or $element->{'element_prev'})) {
- my $is_top = $self->element_is_top($element);
- my $first_in_page = (defined($element->{'filename'})
- and $self->{'counter_in_file'}->{$element->{'filename'}} == 1);
- my $previous_is_top = ($element->{'element_prev'}
- and $self->element_is_top($element->{'element_prev'}));
- print STDERR "Header ($previous_is_top, $is_top, $first_in_page): "
- .Texinfo::Structuring::_print_root_command_texi($command)."\n"
- if ($self->get_conf('DEBUG'));
- if ($is_top) {
- # use TOP_BUTTONS for top.
- $result .= &{$self->{'format_navigation_header'}}($self,
- $self->get_conf('TOP_BUTTONS'), $cmdname, $command)
- if ($self->get_conf('SPLIT') or $self->get_conf('HEADERS'));
- } else {
- if ($first_in_page and !$self->get_conf('HEADERS')) {
- if ($self->get_conf('SPLIT') eq 'chapter') {
- $result .= &{$self->{'format_navigation_header'}}($self,
- $self->get_conf('CHAPTER_BUTTONS'), $cmdname, $command);
- $result .= $self->get_conf('DEFAULT_RULE') ."\n"
- if (defined($self->get_conf('DEFAULT_RULE'))
- and !$self->get_conf('VERTICAL_HEAD_NAVIGATION'));
- } elsif ($self->get_conf('SPLIT') eq 'section') {
- $result .= &{$self->{'format_navigation_header'}}($self,
- $self->get_conf('SECTION_BUTTONS'), $cmdname, $command);
- }
- }
- if (($first_in_page or $previous_is_top)
- and $self->get_conf('HEADERS')) {
- $result .= &{$self->{'format_navigation_header'}}($self,
- $self->get_conf('SECTION_BUTTONS'), $cmdname, $command);
- } elsif($self->get_conf('HEADERS') or $self->get_conf('SPLIT') eq 'node') {
- # got to do this here, as it isn't done otherwise since
- # navigation_header is not called
- $result .= &{$self->{'format_navigation_header_panel'}}($self,
- $self->get_conf('SECTION_BUTTONS'), $cmdname, $command);
- }
- }
- }
- return $result;
- }
- sub _convert_heading_command($$$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $content = shift;
- my $result = '';
- # not clear that it may really happen
- if ($self->in_string) {
- $result .= $self->command_string($command) ."\n" if ($cmdname ne 'node');
- $result .= $content if (defined($content));
- return $result;
- }
- my $element_id = $self->command_id($command);
- $result .= "<a name=\"$element_id\"></a>\n"
- if (defined($element_id) and $element_id ne '');
- print STDERR "Process $command "
- .Texinfo::Structuring::_print_root_command_texi($command)."\n"
- if ($self->get_conf('DEBUG'));
- my $element;
- if ($Texinfo::Common::root_commands{$command->{'cmdname'}}
- and $command->{'parent'}
- and $command->{'parent'}->{'type'}
- and $command->{'parent'}->{'type'} eq 'element') {
- $element = $command->{'parent'};
- }
- if ($element) {
- $result .= &{$self->{'format_element_header'}}($self, $cmdname,
- $command, $element);
- }
- my $heading_level;
- # node is used as heading if there is nothing else.
- if ($cmdname eq 'node') {
- if (!$element or (!$element->{'extra'}->{'section'}
- and $element->{'extra'}->{'node'}
- and $element->{'extra'}->{'node'} eq $command
- # bogus node may not have been normalized
- and defined($command->{'extra'}->{'normalized'}))) {
- if ($command->{'extra'}->{'normalized'} eq 'Top') {
- $heading_level = 0;
- } else {
- $heading_level = 3;
- }
- }
- } else {
- $heading_level = $command->{'level'};
- }
- my $heading = $self->command_text($command);
- # $heading not defined may happen if the command is a @node, for example
- # if there is an error in the node.
- if (defined($heading) and $heading ne '' and defined($heading_level)) {
- if ($self->get_conf('TOC_LINKS')
- and $Texinfo::Common::root_commands{$cmdname}
- and $Texinfo::Common::sectioning_commands{$cmdname}) {
- my $content_href = $self->command_contents_href($command, 'contents',
- $self->{'current_filename'});
- if ($content_href) {
- $heading = "<a href=\"$content_href\">$heading</a>";
- }
- }
- if ($self->in_preformatted()) {
- $result .= '<strong>'.$heading.'</strong>'."\n";
- } else {
- # if the level was changed, set the command name right
- if ($cmdname ne 'node'
- and $heading_level ne $Texinfo::Common::command_structuring_level{$cmdname}) {
- $cmdname
- = $Texinfo::Common::level_to_structuring_command{$cmdname}->[$heading_level];
- }
- $result .= &{$self->{'format_heading_text'}}($self, $cmdname, $heading,
- $heading_level +$self->get_conf('CHAPTER_HEADER_LEVEL') -1, $command);
- }
- }
- $result .= $content if (defined($content));
- if ($cmdname ne 'node'
- and $self->{'current_node'}
- and !$self->{'seenmenus'}->{$self->{'current_node'}}) {
- $self->{'seenmenus'}->{$self->{'current_node'}} = 1;
- # Generate a menu for this node.
- my $menu_text;
- my $menu_node = Texinfo::Structuring::menu_of_node (undef,
- $command->{'extra'}{'associated_node'});
- if ($menu_node) {
- $menu_text = _convert ($self, $menu_node);
- if ($menu_text) {
- $result .= $menu_text;
- $result .= "\n";
- }
- }
- }
- return $result;
- }
- foreach my $command (keys(%sectioning_commands), 'node') {
- $default_commands_conversion{$command} = \&_convert_heading_command;
- }
- sub _convert_raw_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($cmdname eq $self->{'output_format'}) {
- return $content;
- }
- $self->line_warn(sprintf($self->__("raw format %s is not converted"),
- $cmdname), $command->{'line_nr'});
- return $self->protect_text($content);
- }
- foreach my $command (keys(%format_raw_commands)) {
- $default_commands_conversion{$command} = \&_convert_raw_command;
- }
- sub _convert_inline_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $format_arg = shift @$args;
- my $format;
- if (defined($format_arg)) {
- $format = $format_arg->{'monospacetext'};
- }
- return '' if (!defined($format) or $format eq '');
- my $arg_index = undef;
- if ($inline_format_commands{$cmdname}) {
- if ($cmdname eq 'inlinefmtifelse'
- and ! $self->{'expanded_formats_hash'}->{$format}) {
- $arg_index = 1;
- } elsif ($self->{'expanded_formats_hash'}->{$format}) {
- $arg_index = 0;
- }
- } elsif (defined($command->{'extra'}->{'expand_index'})) {
- $arg_index = 0;
- }
- if (defined($arg_index) and $arg_index < scalar(@$args)) {
- my $text_arg = $args->[$arg_index];
- if ($text_arg) {
- if ($text_arg->{'normal'}) {
- return $text_arg->{'normal'};
- } elsif ($text_arg->{'raw'}) {
- return $text_arg->{'raw'};
- }
- }
- }
- return '';
- }
- foreach my $command (keys(%inline_commands)) {
- $default_commands_conversion{$command} = \&_convert_inline_command;
- }
- sub _indent_with_table ($)
- {
- my $content = shift;
- return '<table><tr><td> </td><td>'.$content."</td></tr></table>\n";
- }
- my $html_menu_entry_index = 0;
- sub _convert_preformatted_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($cmdname eq 'menu') {
- $html_menu_entry_index = 0;
- }
- if ($content ne '' and !$self->in_string()) {
- if ($self->get_conf('COMPLEX_FORMAT_IN_TABLE')) {
- if ($indented_preformatted_commands{$cmdname}) {
- return _indent_with_table ($content);
- } else {
- return $content."\n";
- }
- } else {
- return $self->_attribute_class('div', $cmdname).">\n".$content.'</div>'."\n";
- }
- } else {
- return $content;
- }
- }
- foreach my $preformatted_command (keys(%preformatted_commands)) {
- $default_commands_conversion{$preformatted_command}
- = \&_convert_preformatted_command;
- }
- sub _convert_indented_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($content ne '' and !$self->in_string()) {
- if ($self->get_conf('COMPLEX_FORMAT_IN_TABLE')) {
- return _indent_with_table ($content);
- } else {
- return $self->_attribute_class('blockquote', $cmdname).">\n"
- .$content.'</blockquote>'."\n";
- }
- } else {
- return $content;
- }
- }
- $default_commands_conversion{'indentedblock'} = \&_convert_indented_command;
- $default_commands_conversion{'smallindentedblock'}
- = \&_convert_indented_command;
- sub _convert_verbatim_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if (!$self->in_string) {
- return $self->_attribute_class('pre', $cmdname).'>'
- .$content . '</pre>';
- } else {
- return $content;
- }
- }
- $default_commands_conversion{'verbatim'} = \&_convert_verbatim_command;
- sub _convert_verbatiminclude_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $verbatim_include_verbatim
- = $self->Texinfo::Common::expand_verbatiminclude($command);
- if (defined($verbatim_include_verbatim)) {
- return $self->convert_tree($verbatim_include_verbatim);
- } else {
- return '';
- }
- }
- $default_commands_conversion{'verbatiminclude'}
- = \&_convert_verbatiminclude_command;
- sub _convert_command_noop($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- return $content;
- }
- $default_commands_conversion{'raggedright'} = \&_convert_command_noop;
- $default_commands_conversion{'flushleft'} = \&_convert_command_noop;
- $default_commands_conversion{'flushright'} = \&_convert_command_noop;
- $default_commands_conversion{'group'} = \&_convert_command_noop;
- sub _convert_sp_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- if (defined($command->{'extra'}->{'misc_args'}->[0])) {
- my $sp_nr = $command->{'extra'}->{'misc_args'}->[0];
- if ($self->in_preformatted() or $self->in_string()) {
- return "\n" x $sp_nr;
- } else {
- return "<br>\n" x $sp_nr;
- }
- }
- }
- $default_commands_conversion{'sp'} = \&_convert_sp_command;
- sub _convert_exdent_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- # FIXME do something better with css and span?
- my $preformatted = $self->in_preformatted();
-
- if ($self->in_preformatted() or $self->in_string()) {
- return $self->_convert_preformatted_type($cmdname, $command,
- $args->[0]->{'normal'} ."\n");
- } else {
- # ignore alignment information
- return "<p>".$args->[0]->{'normal'} ."\n</p>";
- }
- }
- $default_commands_conversion{'exdent'} = \&_convert_exdent_command;
- sub _convert_center_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- if ($self->in_string()) {
- return $self->_convert_preformatted_type($cmdname, $command,
- $args->[0]->{'normal'}."\n");
- } else {
- return "<div align=\"center\">".$args->[0]->{'normal'}."\n</div>";
- }
- }
- $default_commands_conversion{'center'} = \&_convert_center_command;
- sub _convert_author_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- return '' if (!$args->[0] or !$command->{'extra'}->{'titlepage'});
- if (!$self->in_string()) {
- return "<strong>$args->[0]->{'normal'}</strong><br>\n";
- } else {
- return $args->[0]->{'normal'}."\n";
- }
- }
- $default_commands_conversion{'author'} = \&_convert_author_command;
- sub _convert_title_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- return '' if (!$args->[0]);
- if (!$self->in_string()) {
- return "<h1>$args->[0]->{'normal'}</h1>\n";
- } else {
- return $args->[0]->{'normal'};
- }
- }
- $default_commands_conversion{'title'} = \&_convert_title_command;
- sub _convert_subtitle_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- return '' if (!$args->[0]);
- if (!$self->in_string()) {
- return "<h3 align=\"right\">$args->[0]->{'normal'}</h3>\n";
- } else {
- return $args->[0]->{'normal'};
- }
- }
- $default_commands_conversion{'subtitle'} = \&_convert_subtitle_command;
- sub _convert_insertcopying_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- if ($self->{'extra'} and $self->{'extra'}->{'copying'}) {
- return $self->convert_tree({'contents'
- => $self->{'extra'}->{'copying'}->{'contents'}});
- }
- return '';
- }
- $default_commands_conversion{'insertcopying'}
- = \&_convert_insertcopying_command;
- sub _convert_listoffloats_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- if (!$self->in_string()
- and $command->{'extra'} and $command->{'extra'}->{'type'}
- and defined($command->{'extra'}->{'type'}->{'normalized'})
- and $self->{'floats'}
- and $self->{'floats'}->{$command->{'extra'}->{'type'}->{'normalized'}}
- and @{$self->{'floats'}->{$command->{'extra'}->{'type'}->{'normalized'}}}) {
- my $listoffloats_name = $command->{'extra'}->{'type'}->{'normalized'};
- my $result = $self->_attribute_class('dl', 'listoffloats').">\n" ;
- foreach my $float (@{$self->{'floats'}->{$listoffloats_name}}) {
- my $float_href = $self->command_href($float);
- next if (!$float_href);
- $result .= '<dt>';
- my $float_text = $self->command_text($float);
- if (defined($float_text) and $float_text ne '') {
- if ($float_href) {
- $result .= "<a href=\"$float_href\">$float_text</a>";
- } else {
- $result .= $float_text;
- }
- }
- $result .= '</dt>';
- my $caption;
- if ($float->{'extra'}->{'shortcaption'}) {
- $caption = $float->{'extra'}->{'shortcaption'};
- } elsif ($float->{'extra'}->{'caption'}) {
- $caption = $float->{'extra'}->{'caption'};
- }
- my $caption_text;
- if ($caption) {
- $caption_text = $self->convert_tree_new_formatting_context(
- $caption->{'args'}->[0], $cmdname, 'listoffloats');
- } else {
- $caption_text = '';
- }
- $result .= '<dd>'.$caption_text.'</dd>'."\n";
- }
- return $result . "</dl>\n";
- } else {
- return '';
- }
- }
- $default_commands_conversion{'listoffloats'} = \&_convert_listoffloats_command;
- sub _in_preformatted_in_menu($)
- {
- my $self = shift;
- return 1 if ($self->get_conf('SIMPLE_MENU'));
- my @pre_classes = $self->preformatted_classes_stack();
- foreach my $pre_class (@pre_classes) {
- return 1 if ($preformatted_commands{$pre_class});
- }
- return 0;
- }
- sub _convert_menu_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- return $content if ($cmdname eq 'detailmenu');
- $html_menu_entry_index = 0;
- if ($content !~ /\S/) {
- return '';
- }
- if ($self->in_string()) {
- return $content;
- }
- my $begin_row = '';
- my $end_row = '';
- if ($self->_in_preformatted_in_menu()) {
- $begin_row = '<tr><td>';
- $end_row = '</td></tr>';
- }
- if ($self->{'current_node'}) {
- $self->{'seenmenus'}->{$self->{'current_node'}} = 1;
- }
- return $self->_attribute_class('table', 'menu')
- ." border=\"0\" cellspacing=\"0\">${begin_row}\n"
- . $content . "${end_row}</table>\n";
- }
- $default_commands_conversion{'menu'} = \&_convert_menu_command;
- $default_commands_conversion{'detailmenu'} = \&_convert_menu_command;
- sub _convert_float_command($$$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $content = shift;
- my ($caption, $prepended) = Texinfo::Common::float_name_caption($self,
- $command);
- my $caption_text = '';
- my $prepended_text;
- if ($self->in_string()) {
- if ($prepended) {
- $prepended_text = $self->convert_tree_new_formatting_context(
- $prepended, 'float prepended');
- } else {
- $prepended_text = '';
- }
- if ($caption) {
- $caption_text = $self->convert_tree_new_formatting_context(
- {'contents' => $caption->{'args'}->[0]->{'contents'}},
- 'float caption');
- }
- return $prepended.$content.$caption_text;
- }
- my $id = $self->command_id($command);
- my $label;
- if (defined($id) and $id ne '') {
- $label = "<a name=\"$id\"></a>";
- } else {
- $label = '';
- }
- if ($prepended) {
- if ($caption) {
- # prepend the prepended tree to the first paragraph
- my @caption_original_contents = @{$caption->{'args'}->[0]->{'contents'}};
- my @caption_contents;
- my $new_paragraph;
- while (@caption_original_contents) {
- my $content = shift @caption_original_contents;
- if ($content->{'type'} and $content->{'type'} eq 'paragraph') {
- %{$new_paragraph} = %{$content};
- $new_paragraph->{'contents'} = [@{$content->{'contents'}}];
- unshift (@{$new_paragraph->{'contents'}}, {'cmdname' => 'strong',
- 'args' => [{'type' => 'brace_command_arg',
- 'contents' => [$prepended]}]});
- push @caption_contents, $new_paragraph;
- last;
- } else {
- push @caption_contents, $content;
- }
- }
- push @caption_contents, @caption_original_contents;
- if ($new_paragraph) {
- $caption_text = $self->convert_tree_new_formatting_context(
- {'contents' => \@caption_contents}, 'float caption');
- $prepended_text = '';
- }
- }
- if ($caption_text eq '') {
- $prepended_text = $self->convert_tree_new_formatting_context(
- $prepended, 'float prepended');
- if ($prepended_text ne '') {
- $prepended_text = '<p><strong>'.$prepended_text.'</strong></p>';
- }
- }
- } else {
- $prepended_text = '';
- }
-
- if ($caption and $caption_text eq '') {
- $caption_text = $self->convert_tree_new_formatting_context(
- $caption->{'args'}->[0], 'float caption');
- }
- if ($prepended_text.$caption_text ne '') {
- $prepended_text = $self->_attribute_class('div','float-caption'). '>'
- . $prepended_text;
- $caption_text .= '</div>';
- }
- return $self->_attribute_class('div','float'). '>' .$label."\n".$content.
- $prepended_text.$caption_text . '</div>';
- }
- $default_commands_conversion{'float'} = \&_convert_float_command;
- sub _convert_quotation_command($$$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $content = shift;
- my $class = '';
- $class = $cmdname if ($cmdname ne 'quotation');
- my $attribution = '';
- if ($command->{'extra'} and $command->{'extra'}->{'authors'}) {
- foreach my $author (@{$command->{'extra'}->{'authors'}}) {
- my $centered_author = $self->gdt("\@center --- \@emph{{author}}\n",
- {'author' => $author->{'extra'}->{'misc_content'}});
- $centered_author->{'parent'} = $command;
- $attribution .= $self->convert_tree($centered_author);
- }
- }
- if (!$self->in_string()) {
- return $self->_attribute_class('blockquote', $class).">\n" .$content
- ."</blockquote>\n" . $attribution;
- } else {
- return $content.$attribution;
- }
- }
- $default_commands_conversion{'quotation'} = \&_convert_quotation_command;
- $default_commands_conversion{'smallquotation'} = \&_convert_quotation_command;
- sub _convert_cartouche_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($content =~ /\S/ and !$self->in_string()) {
- return $self->_attribute_class('table', 'cartouche')
- ." border=\"1\"><tr><td>\n". $content ."</td></tr></table>\n";
- }
- return $content;
- }
- $default_commands_conversion{'cartouche'} = \&_convert_cartouche_command;
- sub _convert_itemize_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($self->in_string()) {
- return $content;
- }
- if ($command->{'extra'}->{'command_as_argument'}
- and $command->{'extra'}->{'command_as_argument'}->{'cmdname'} eq 'bullet') {
- return "<ul>\n" . $content. "</ul>\n";
- } else {
- return $self->_attribute_class('ul',$NO_BULLET_LIST_CLASS).">\n"
- . $content . "</ul>\n";
- }
- }
- $default_commands_conversion{'itemize'} = \&_convert_itemize_command;
- sub _convert_enumerate_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($self->in_string()) {
- return $content;
- }
- if ($content eq '') {
- return '';
- }
- my $specification = $command->{'extra'}{'enumerate_specification'};
- if (defined $specification) {
- my ($start, $type);
- if ($specification =~ /^\d*$/ and $specification ne '1') {
- $start = $specification;
- } elsif ($specification =~ /^[A-Z]$/) {
- $start = 1 + ord($specification) - ord('A');
- $type = 'A';
- } elsif ($specification =~ /^[a-z]$/) {
- $start = 1 + ord($specification) - ord('a');
- $type = 'a';
- }
- if (defined $type and defined $start) {
- return "<ol type=\"$type\" start=\"$start\">\n" . $content . "</ol>\n";
- } elsif (defined $start) {
- return "<ol start=\"$start\">\n" . $content . "</ol>\n";
- }
- }
- return "<ol>\n" . $content . "</ol>\n";
- }
- $default_commands_conversion{'enumerate'} = \&_convert_enumerate_command;
- sub _convert_multitable_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($self->in_string()) {
- return $content;
- }
- if ($content =~ /\S/) {
- return "<table>\n" . $content . "</table>\n";
- } else {
- return '';
- }
- }
- $default_commands_conversion{'multitable'} = \&_convert_multitable_command;
- sub _convert_xtable_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($self->in_string()) {
- return $content;
- }
- if ($content ne '') {
- return "<dl compact=\"compact\">\n" . $content . "</dl>\n";
- } else {
- return '';
- }
- }
- $default_commands_conversion{'table'} = \&_convert_xtable_command;
- $default_commands_conversion{'ftable'} = \&_convert_xtable_command;
- $default_commands_conversion{'vtable'} = \&_convert_xtable_command;
- sub _convert_item_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- if ($self->in_string()) {
- return $content;
- }
- if ($command->{'parent'}->{'cmdname'}
- and $command->{'parent'}->{'cmdname'} eq 'itemize') {
- my $prepend ;
- my $itemize = $command->{'parent'};
- if ($itemize->{'extra'}->{'command_as_argument'}
- and $itemize->{'extra'}->{'command_as_argument'}->{'cmdname'} eq 'bullet') {
- $prepend = '';
- } else {
- # Setting multiple expansion should not be needed, except in
- # case of invalid constructs
- $prepend = $self->convert_tree_new_formatting_context(
- {'contents' => $itemize->{'extra'}->{'block_command_line_contents'}->[0]},
- $command->{'cmdname'}, 'item_prepended');
- }
- if ($content =~ /\S/) {
- return '<li>' . $prepend .' '. $content . '</li>';
- } else {
- return '';
- }
- } elsif ($command->{'parent'}->{'cmdname'}
- and $command->{'parent'}->{'cmdname'} eq 'enumerate') {
- if ($content =~ /\S/) {
- return '<li>' . ' ' . $content . '</li>';
- } else {
- return '';
- }
- } elsif ($command->{'parent'}->{'type'}
- and $command->{'parent'}->{'type'} eq 'table_term') {
- # FIXME instead use the code of Plaintext or DocBook.
- my $args = $content;
- if ($args->[0]) {
- my $tree = $self->_table_item_content_tree($command,
- [$args->[0]->{'tree'}]);
- my $result = $self->convert_tree ($tree);
- foreach my $command_name (reverse($self->commands_stack())) {
- if ($preformatted_code_commands{$command_name}) {
- $result = '<tt>' .$result. '</tt>';
- last;
- }
- }
- my $index_id = $self->command_id ($command);
- if (defined($index_id) and $index_id ne '') {
- $result .= "\n<a name=\"$index_id\"></a>\n";
- }
-
- return '<dt>' .$result. '</dt>' . "\n";
- } else {
- return '';
- }
- } elsif ($command->{'parent'}->{'type'}
- and $command->{'parent'}->{'type'} eq 'row') {
- return $self->_convert_tab_command ($cmdname, $command, $content);
- }
- return '';
- }
- $default_commands_conversion{'item'} = \&_convert_item_command;
- $default_commands_conversion{'headitem'} = \&_convert_item_command;
- $default_commands_conversion{'itemx'} = \&_convert_item_command;
- sub _convert_tab_command ($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
-
- my $cell_nr = $command->{'extra'}->{'cell_number'};
- my $row = $command->{'parent'};
- my $row_cmdname = $row->{'contents'}->[0]->{'cmdname'};
- my $multitable = $row->{'parent'}->{'parent'};
- my $fractions = '';
- if ($multitable->{'extra'}->{'columnfractions'} and
- exists($multitable->{'extra'}->{'columnfractions'}->[$cell_nr-1])) {
- my $fraction = sprintf('%d', 100*$multitable->{'extra'}->{'columnfractions'}->[$cell_nr-1]);
- $fractions = " width=\"$fraction%\"";
- }
- $content =~ s/^\s*//;
- $content =~ s/\s*$//;
- if ($self->in_string()) {
- return $content;
- }
- if ($row_cmdname eq 'headitem') {
- return "<th${fractions}>" . $content . '</th>';
- } else {
- return "<td${fractions}>" . $content . '</td>';
- }
- }
- $default_commands_conversion{'tab'} = \&_convert_tab_command;
- sub _convert_xref_commands($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $root = shift;
- my $args = shift;
- my $tree;
- my $name;
- if ($cmdname ne 'inforef'
- and defined($args->[2]->{'normal'}) and $args->[2]->{'normal'} ne '') {
- $name = $args->[2]->{'normal'};
- } elsif (defined($args->[1]->{'normal'}) and $args->[1]->{'normal'} ne '') {
- $name = $args->[1]->{'normal'}
- }
- if ($cmdname eq 'inforef') {
- $args->[3] = $args->[2];
- $args->[2] = undef;
- }
- my $file_arg_tree;
- my $file = '';
- if (defined($args->[3]->{'monospacetext'})
- and $args->[3]->{'monospacetext'} ne '') {
- $file_arg_tree = $args->[3]->{'tree'};
- $file = $args->[3]->{'monospacetext'};
- }
- my $book = '';
- $book = $args->[4]->{'normal'} if (defined($args->[4]->{'normal'}));
- # internal reference
- if ($cmdname ne 'inforef' and $book eq '' and $file eq ''
- and $root->{'extra'}->{'node_argument'}
- and defined($root->{'extra'}->{'node_argument'}->{'normalized'})
- and !$root->{'extra'}->{'node_argument'}->{'manual_content'}
- and $self->{'labels'}
- and $self->{'labels'}->{$root->{'extra'}->{'node_argument'}->{'normalized'}}) {
- my $node
- = $self->label_command($root->{'extra'}->{'node_argument'}->{'normalized'});
- # This is the node if USE_NODES, otherwise this may be the sectioning
- # command (if the sectioning command is really associated to the node)
- my $command = $self->command_element_command($node);
- $command = $node if (!$node->{'extra'}->{'associated_section'}
- or $node->{'extra'}->{'associated_section'} ne $command);
- my $href = $self->command_href($command, undef, $root);
- if (!defined($name)) {
- if ($self->get_conf('xrefautomaticsectiontitle') eq 'on'
- and $node->{'extra'}->{'associated_section'}) {
- $command = $node->{'extra'}->{'associated_section'};
- $name = $self->command_text($command, 'text_nonumber');
- } elsif ($node->{'cmdname'} eq 'float') {
- if (!$self->get_conf('XREF_USE_FLOAT_LABEL')) {
- $name = $self->command_text($command);
- }
- if (!defined($name) or $name eq '') {
- if (defined($args->[0]->{'monospace'})) {
- $name = $args->[0]->{'monospace'};
- } else {
- $name = '';
- }
- }
- } elsif (!$self->get_conf('XREF_USE_NODE_NAME_ARG')
- and (defined($self->get_conf('XREF_USE_NODE_NAME_ARG'))
- or !$self->in_preformatted())) {
- $name = $self->command_text($command, 'text_nonumber');
- #die "$command $command->{'normalized'}" if (!defined($name));
- } elsif (defined($args->[0]->{'monospace'})) {
- $name = $args->[0]->{'monospace'};
- } else {
- $name = '';
- }
- }
- my $reference = $name;
- $reference = "<a href=\"$href\">$name</a>" if ($href ne ''
- and !$self->in_string());
- # maybe use {'extra'}->{'node_argument'}?
- my $is_section = ($command->{'cmdname'} ne 'node'
- and $command->{'cmdname'} ne 'anchor'
- and $command->{'cmdname'} ne 'float');
- if ($cmdname eq 'pxref') {
- if ($is_section) {
- $tree = $self->gdt('see section {reference_name}',
- { 'reference_name' => {'type' => '_converted', 'text' => $reference} });
- } else {
- $tree = $self->gdt('see {reference_name}',
- { 'reference_name' => {'type' => '_converted', 'text' => $reference} });
- }
- } elsif ($cmdname eq 'xref' or $cmdname eq 'inforef') {
- if ($is_section) {
- $tree = $self->gdt('See section {reference_name}',
- { 'reference_name' => {'type' => '_converted', 'text' => $reference} });
- } else {
- $tree = $self->gdt('See {reference_name}',
- { 'reference_name' => {'type' => '_converted', 'text' => $reference} });
- }
- } elsif ($cmdname eq 'ref') {
- $tree = $self->gdt('{reference_name}',
- { 'reference_name' => {'type' => '_converted', 'text' => $reference} });
- }
- } else {
- # external reference
- my $node_entry = {};
- $node_entry->{'node_content'} = $root->{'extra'}->{'node_argument'}->{'node_content'}
- if ($root->{'extra'}->{'node_argument'}
- and $root->{'extra'}->{'node_argument'}->{'node_content'});
- $node_entry->{'normalized'} = $root->{'extra'}->{'node_argument'}->{'normalized'}
- if ($root->{'extra'}->{'node_argument'}
- and exists($root->{'extra'}->{'node_argument'}->{'normalized'}));
- # file argument takes precedence over the file in the node (file)node entry
- if (defined($file_arg_tree) and $file ne '') {
- $node_entry->{'manual_content'} = $file_arg_tree->{'contents'};
- } elsif ($root->{'extra'}->{'node_argument'}
- and $root->{'extra'}->{'node_argument'}->{'manual_content'}) {
- $node_entry->{'manual_content'}
- = $root->{'extra'}->{'node_argument'}->{'manual_content'};
- my $file_with_node_tree = {'type' => '_code',
- 'contents' => [@{$node_entry->{'manual_content'}}]};
- $file = $self->convert_tree($file_with_node_tree, 'node file in ref');
- }
- my $href = $self->command_href($node_entry, undef, $root);
- if ($book eq '') {
- if (!defined($name)) {
- my $node_name = $self->command_text($node_entry);
- $name = $node_name;
- } elsif ($file ne '') {
- $name = "($file)$name";
- }
- } elsif (!defined($name) and $node_entry->{'node_content'}) {
- my $node_no_file_tree = {'type' => '_code',
- 'contents' => [@{$node_entry->{'node_content'}}]};
- my $node_name = $self->convert_tree($node_no_file_tree, 'node in ref');
- if (defined($node_name) and ($self->get_conf('KEEP_TOP_EXTERNAL_REF')
- or $node_name ne 'Top')) {
- $name = $node_name;
- }
- }
- # not exactly sure when it happens. Something like @ref{(file),,,Manual}?
- $name = $args->[0]->{'monospace'}
- if (!defined($name)
- # FIXME could it really be Top?
- and ($self->get_conf('KEEP_TOP_EXTERNAL_REF')
- or $args->[0]->{'monospace'} ne 'Top'));
-
- $name = '' if (!defined($name));
- my $reference = $name;
- my $book_reference = '';
- if (!$self->in_string() and $href ne '') {
- if ($name ne '') {
- $reference = "<a href=\"$href\">$name</a>";
- } elsif ($book ne '') {
- $book_reference = "<a href=\"$href\">$book</a>";
- }
- }
- if ($cmdname eq 'pxref') {
- if (($book ne '') and ($href ne '') and ($reference ne '')) {
- $tree = $self->gdt('see {reference} in @cite{{book}}',
- { 'reference' => {'type' => '_converted', 'text' => $reference},
- 'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($book_reference ne '') {
- $tree = $self->gdt('see @cite{{book_reference}}',
- { 'book_reference' => {'type' => '_converted',
- 'text' => $book_reference }});
- } elsif (($book ne '') and ($reference ne '')) {
- $tree = $self->gdt('see `{section}\' in @cite{{book}}',
- { 'section' => {'type' => '_converted', 'text' => $reference},
- 'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($book ne '') { # should seldom or even never happen
- $tree = $self->gdt('see @cite{{book}}',
- {'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($href ne '') {
- $tree = $self->gdt('see {reference}',
- { 'reference' => {'type' => '_converted', 'text' => $reference} });
- } elsif ($reference ne '') {
- $tree = $self->gdt('see `{section}\'', {
- 'section' => {'type' => '_converted', 'text' => $reference} });
- }
- } elsif ($cmdname eq 'xref' or $cmdname eq 'inforef') {
- if (($book ne '') and ($href ne '') and ($reference ne '')) {
- $tree = $self->gdt('See {reference} in @cite{{book}}',
- { 'reference' => {'type' => '_converted', 'text' => $reference},
- 'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($book_reference ne '') {
- $tree = $self->gdt('See @cite{{book_reference}}',
- { 'book_reference' => {'type' => '_converted',
- 'text' => $book_reference }});
- } elsif (($book ne '') and ($reference ne '')) {
- $tree = $self->gdt('See `{section}\' in @cite{{book}}',
- { 'section' => {'type' => '_converted', 'text' => $reference},
- 'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($book ne '') { # should seldom or even never happen
- $tree = $self->gdt('See @cite{{book}}',
- {'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($href ne '') {
- $tree = $self->gdt('See {reference}',
- { 'reference' => {'type' => '_converted', 'text' => $reference} });
- } elsif ($reference ne '') {
- $tree = $self->gdt('See `{section}\'', {
- 'section' => {'type' => '_converted', 'text' => $reference} });
- }
- } else {
- if (($book ne '') and ($href ne '') and ($reference ne '')) {
- $tree = $self->gdt('{reference} in @cite{{book}}',
- { 'reference' => {'type' => '_converted', 'text' => $reference},
- 'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($book_reference ne '') {
- $tree = $self->gdt('@cite{{book_reference}}',
- { 'book_reference' => {'type' => '_converted',
- 'text' => $book_reference }});
- } elsif (($book ne '') and ($reference ne '')) {
- $tree = $self->gdt('`{section}\' in @cite{{book}}',
- { 'section' => {'type' => '_converted', 'text' => $reference},
- 'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($book ne '') { # should seldom or even never happen
- $tree = $self->gdt('@cite{{book}}',
- {'book' => {'type' => '_converted', 'text' => $book }});
- } elsif ($href ne '') {
- $tree = $self->gdt('{reference}',
- { 'reference' => {'type' => '_converted', 'text' => $reference} });
- } elsif ($reference ne '') {
- $tree = $self->gdt('`{section}\'', {
- 'section' => {'type' => '_converted', 'text' => $reference} });
- }
- }
- if (!defined($tree)) {
- # May happen if there is no argument
- #die "external: $cmdname, ($args), '$name' '$file' '$book' '$href' '$reference'. tree undef";
- return '';
- }
- }
- return $self->convert_tree($tree);
- }
- foreach my $command(keys(%ref_commands)) {
- $default_commands_conversion{$command} = \&_convert_xref_commands;
- }
- sub _convert_index_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $index_id = $self->command_id($command);
- if (defined($index_id) and $index_id ne ''
- and !@{$self->{'multiple_pass'}}
- and !$self->in_string()) {
- my $result = "<a name=\"$index_id\"></a>";
- $result .= "\n" unless ($self->in_preformatted());
- return $result;
- }
- return '';
- }
- $default_commands_conversion{'cindex'} = \&_convert_index_command;
- my %formatted_index_entries;
- sub _convert_printindex_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $args = shift;
- my $index_name;
- if ($command->{'extra'} and $command->{'extra'}->{'misc_args'}
- and defined($command->{'extra'}->{'misc_args'}->[0])) {
- $index_name = $command->{'extra'}->{'misc_args'}->[0];
- } else {
- return '';
- }
- if (!$self->{'index_entries_by_letter'}
- or !$self->{'index_entries_by_letter'}->{$index_name}
- or !@{$self->{'index_entries_by_letter'}->{$index_name}}) {
- return '';
- }
- #foreach my $letter_entry (@{$self->{'index_entries_by_letter'}->{$index_name}}) {
- # print STDERR "IIIIIII $letter_entry->{'letter'}\n";
- # foreach my $index_entry (@{$letter_entry->{'entries'}}) {
- # print STDERR " ".join('|', keys(%$index_entry))."||| $index_entry->{'key'}\n";
- # }
- #}
- return '' if ($self->in_string());
- $self->_new_document_context($cmdname);
- my $result = '';
- # First do the summary letters linking to the letters done below
- my %letter_id;
- my @non_alpha = ();
- my @alpha = ();
- # collect the links
- my $symbol_idx = 0;
- foreach my $letter_entry (@{$self->{'index_entries_by_letter'}->{$index_name}}) {
- my $letter = $letter_entry->{'letter'};
- my $index_element_id = $self->_element_direction($self->{'current_element'},
- 'This', 'target');
- if (!defined($index_element_id)) {
- $index_element_id = $target_prefix;
- }
- my $is_symbol = $letter !~ /^[[:alpha:]]/;
- my $identifier;
- if ($is_symbol) {
- $symbol_idx++;
- $identifier = $index_element_id . "_${index_name}_symbol-$symbol_idx";
- } else {
- $identifier = $index_element_id . "_${index_name}_letter-${letter}";
- }
- $letter_id{$letter} = $identifier;
-
- my $summary_letter_link = $self->_attribute_class('a', 'summary-letter')
- ." href=\"#$identifier\"><b>".$self->protect_text($letter).'</b></a>';
- if ($is_symbol) {
- push @non_alpha, $summary_letter_link;
- } else {
- push @alpha, $summary_letter_link;
- }
- }
- # Format the summary letters
- my $join = '';
- my $non_alpha_text = '';
- my $alpha_text = '';
- $join = " \n<br>\n" if (@non_alpha and @alpha);
- if (@non_alpha) {
- $non_alpha_text = join("\n \n", @non_alpha) . "\n";
- }
- if (@alpha) {
- $alpha_text = join("\n \n", @alpha) . "\n \n";
- }
- # format the summary
- my $summary = "<table><tr><th valign=\"top\">"
- . $self->convert_tree($self->gdt('Jump to')) .": </th><td>" .
- $non_alpha_text . $join . $alpha_text . "</td></tr></table>\n";
- $result .= $summary;
- # now format the index entries
- $result .= $self->_attribute_class('table', "index-$index_name")
- ." border=\"0\">\n" . "<tr><td></td><th align=\"left\">"
- . $self->convert_tree($self->gdt('Index Entry'))
- . "</th><td> </td><th align=\"left\"> "
- . $self->convert_tree($self->gdt('Section'))
- ."</th></tr>\n" . "<tr><td colspan=\"4\"> ".$self->get_conf('DEFAULT_RULE')
- ."</td></tr>\n";
- foreach my $letter_entry (@{$self->{'index_entries_by_letter'}->{$index_name}}) {
- my $letter = $letter_entry->{'letter'};
- my $entries_text = '';
- foreach my $index_entry_ref (@{$letter_entry->{'entries'}}) {
- # to avoid double error messages set ignore_notice if an entry was
- # already formatted once, for example if there are multiple printindex.
- my $already_formatted;
- if (!$formatted_index_entries{$index_entry_ref}) {
- $formatted_index_entries{$index_entry_ref} = 1;
- } else {
- $already_formatted = 1;
- $self->{'ignore_notice'}++;
- }
- my $entry;
- if ($index_entry_ref->{'in_code'}) {
- $entry = $self->convert_tree({'type' => '_code',
- 'contents' => $index_entry_ref->{'content'}});
- } else {
- $entry = $self->convert_tree({'contents' => $index_entry_ref->{'content'}});
- }
- if ($already_formatted) {
- $self->{'ignore_notice'}--;
- }
- next if ($entry !~ /\S/);
- $entry = '<code>' .$entry .'</code>' if ($index_entry_ref->{'in_code'});
- my $entry_href = $self->command_href($index_entry_ref->{'command'});
- my $associated_command;
- if ($self->get_conf('NODE_NAME_IN_INDEX')) {
- $associated_command = $index_entry_ref->{'node'};
- if (!defined($associated_command)) {
- $associated_command
- = $self->command_node($index_entry_ref->{'command'});
- }
- }
- if (!$associated_command) {
- $associated_command
- = $self->command_element_command($index_entry_ref->{'command'});
- if (!$associated_command) {
- # Use Top if not associated command found
- $associated_command
- = $self->element_command($self->global_element('Top'));
- }
- }
- my ($associated_command_href, $associated_command_text);
- if ($associated_command) {
- $associated_command_href = $self->command_href($associated_command);
- $associated_command_text = $self->command_text($associated_command);
- }
-
- $entries_text .= '<tr><td></td><td valign="top">'
- . "<a href=\"$entry_href\">$entry</a>" .
- $self->get_conf('INDEX_ENTRY_COLON') .
- '</td><td> </td><td valign="top">';
- $entries_text .= "<a href=\"$associated_command_href\">$associated_command_text</a>"
- if ($associated_command_href);
- $entries_text .= "</td></tr>\n";
- }
- # a letter and associated indice entries
- $result .= '<tr><th>' .
- "<a name=\"$letter_id{$letter}\">".$self->protect_text($letter).'</a>'
- . "</th><td></td><td></td></tr>\n" . $entries_text .
- "<tr><td colspan=\"4\"> ".$self->get_conf('DEFAULT_RULE')."</td></tr>\n";
- }
- $result .= "</table>\n";
-
- pop @{$self->{'document_context'}};
-
- return $result .$summary;
- }
- $default_commands_conversion{'printindex'} = \&_convert_printindex_command;
- sub _contents_inline_element($$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = &{$self->{'format_contents'}}($self, $cmdname, $command);
- if ($content) {
- my $result = '';
- my $element_name = $contents_command_element_name{$cmdname};
- my $special_element
- = $self->special_element($element_name);
- my $heading;
- if ($special_element) {
- my $id = $self->command_id($special_element);
- if ($id ne '') {
- $result .= "<a name=\"$id\"></a>\n";
- }
- $heading = $self->command_text($special_element);
- } else {
- # happens when called as convert() and not output()
- #cluck "$cmdname special element not defined";
- $heading
- = $self->convert_tree ($self->get_conf('SPECIAL_ELEMENTS_NAME')->{$element_name});
- }
- my $class = $self->get_conf('SPECIAL_ELEMENTS_CLASS')->{$element_name};
- $result .= &{$self->{'format_heading_text'}}($self, $class.'-heading',
- $heading, $self->get_conf('CHAPTER_HEADER_LEVEL'))."\n";
- $result .= $content . "\n";
- return $result;
- }
- return '';
- }
- sub _convert_informative_command($$$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- return '' if ($self->in_string());
- $cmdname = 'shortcontents' if ($cmdname eq 'summarycontents');
- $self->_informative_command($command);
- if ($self->get_conf('INLINE_CONTENTS')
- and ($cmdname eq 'contents' or $cmdname eq 'shortcontents')
- and $self->get_conf($cmdname)
- and $self->{'structuring'} and $self->{'structuring'}->{'sectioning_root'}
- and scalar(@{$self->{'structuring'}->{'sections_list'}}) > 1) {
- return $self->_contents_inline_element($cmdname, $command);
- }
- if ($cmdname eq 'documentlanguage') {
- $self->_translate_names();
- }
- return '';
- }
- foreach my $informative_command (@informative_global_commands) {
- $default_commands_conversion{$informative_command}
- = \&_convert_informative_command;
- }
- # Keys are tree element types, values are function references to convert
- # elements of that type. Can be overridden with
- # Texinfo::Config::texinfo_types_conversion.
- my %default_types_conversion;
- sub default_types_conversion($$)
- {
- my $self = shift;
- my $type = shift;
- return $default_types_conversion{$type};
- }
- # Ignored commands
- foreach my $type ('empty_line_after_command', 'preamble',
- 'preamble_before_setfilename',
- 'empty_spaces_after_command', 'spaces_at_end',
- 'empty_spaces_before_argument', 'empty_spaces_before_paragraph',
- 'empty_spaces_after_close_brace') {
- $default_types_conversion{$type} = undef;
- }
- my %paragraph_style = (
- 'center' => 'center',
- 'flushleft' => 'left',
- 'flushright' => 'right',
- );
- sub _quotation_arg_to_prepend($$)
- {
- my $self = shift;
- my $command = shift;
- if ($command->{'parent'} and $command->{'parent'}->{'cmdname'}
- and ($command->{'parent'}->{'cmdname'} eq 'quotation'
- or $command->{'parent'}->{'cmdname'} eq 'smallquotation')
- and $command->{'parent'}->{'extra'}
- and $command->{'parent'}->{'extra'}->{'block_command_line_contents'}) {
- return $self->convert_tree($self->gdt('@b{{quotation_arg}:} ',
- {'quotation_arg' =>
- $command->{'parent'}->{'extra'}->{'block_command_line_contents'}->[0]}));
- }
- return undef;
- }
- sub _convert_paragraph_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- if ($self->paragraph_number() == 1) {
- my $in_format = $self->top_format();
- if ($in_format) {
- # no first paragraph in those environment to avoid extra spacing
- if ($in_format eq 'itemize'
- or $in_format eq 'enumerate'
- or $in_format eq 'multitable') {
- return $content;
- } else {
- my $prepended = $self->_quotation_arg_to_prepend($command);
- $content = $prepended.$content if (defined($prepended));
- }
- }
- }
- return $content if ($self->in_string());
- if ($content =~ /\S/) {
- my $align = $self->in_align();
- if ($align and $paragraph_style{$align}) {
- return "<p align=\"$paragraph_style{$align}\">".$content."</p>";
- } else {
- return "<p>".$content."</p>";
- }
- } else {
- return '';
- }
- }
- $default_types_conversion{'paragraph'} = \&_convert_paragraph_type;
- sub _preformatted_class()
- {
- my $self = shift;
- my $pre_class;
- my @pre_classes = $self->preformatted_classes_stack();
- foreach my $class (@pre_classes) {
- # FIXME maybe add or $pre_class eq 'menu-preformatted' to override
- # 'menu-preformatted' with 'menu-comment'?
- $pre_class = $class unless ($pre_class
- and $preformatted_code_commands{$pre_class}
- and !($preformatted_code_commands{$class}
- or $class eq 'menu-preformatted'));
- }
- return $pre_class;
- }
- sub _convert_preformatted_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- if (!defined($content)) {
- cluck "content undef in _convert_preformatted_type "
- .Texinfo::Common::_print_current($command);
- }
- my $current = $command;
- # !defined preformatted_number may happen if there is something before the
- # first preformatted. For example an @exdent.
- if ($self->preformatted_number() and $self->preformatted_number() == 1) {
- my $prepended = $self->_quotation_arg_to_prepend($command);
- $content = $prepended.$content if (defined($prepended));
- }
- return '' if ($content eq '');
- return $content if ($type eq 'rawpreformatted');
- my $pre_class = $self->_preformatted_class();
- if ($self->top_format() eq 'multitable') {
- $content =~ s/^\s*//;
- $content =~ s/\s*$//;
- }
- # menu_entry_description is always in a preformatted container
- # in the tree, as the whole menu is meant to be an
- # environment where spaces and newlines are preserved.
- #
- # However, if not in preformatted block command (nor in SIMPLE_MENU),
- # we don't preserve spaces and newlines in menu_entry_description,
- # instead the whole menu_entry is in a table, so here, not <pre>
- if ($command->{'parent'}->{'type'}
- and $command->{'parent'}->{'type'} eq 'menu_entry_description'
- and !$self->_in_preformatted_in_menu()) {
- return $content;
- }
- if ($self->in_string()) {
- return $content;
- }
- $content =~ s/^\n/\n\n/; # a newline immediately after a <pre> is ignored.
- my $result = $self->_attribute_class('pre', $pre_class).">".$content."</pre>";
- # this may happen with lines without textual content
- # between a def* and def*x.
- if ($command->{'parent'}->{'cmdname'}
- and $command->{'parent'}->{'cmdname'} =~ /^def/) {
- $result = '<dd>'.$result.'</dd>';
- }
- return $result;
- }
- $default_types_conversion{'preformatted'} = \&_convert_preformatted_type;
- $default_types_conversion{'rawpreformatted'} = \&_convert_preformatted_type;
- sub _convert_bracketed_type($$$$) {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- #print STDERR "$self $type $command $content\n";
- return '{'.$content.'}';
- }
- $default_types_conversion{'bracketed'} = \&_convert_bracketed_type;
- sub _convert_definfoenclose_type($$$$) {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- return $self->protect_text($command->{'extra'}->{'begin'}) . $content
- .$self->protect_text($command->{'extra'}->{'end'});
- }
- $default_types_conversion{'definfoenclose_command'}
- = \&_convert_definfoenclose_type;
- sub _convert_text($$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $text = shift;
- if ($self->in_verbatim()) {
- return $self->protect_text($text);
- }
- return $text if ($self->in_raw());
- $text = uc($text) if ($self->in_upper_case());
- $text = $self->protect_text($text);
- if ($self->get_conf('ENABLE_ENCODING') and
- !$self->get_conf('ENABLE_ENCODING_USE_ENTITY')
- and $self->get_conf('OUTPUT_ENCODING_NAME')
- and $self->get_conf('OUTPUT_ENCODING_NAME') eq 'utf-8') {
- $text = Texinfo::Convert::Unicode::unicode_text($text,
- ($self->in_code() or $self->in_math()));
- } elsif (!$self->in_code() and !$self->in_math()) {
- if ($self->get_conf('USE_ISO')) {
- $text =~ s/---/\&mdash\;/g;
- $text =~ s/--/\&ndash\;/g;
- $text =~ s/``/\&ldquo\;/g;
- $text =~ s/''/\&rdquo\;/g;
- $text =~ s/'/\&rsquo\;/g;
- $text =~ s/`/\&lsquo\;/g;
- } else {
- $text =~ s/``/"/g;
- $text =~ s/''/"/g;
- $text =~ s/---/\x{1F}/g;
- $text =~ s/--/-/g;
- $text =~ s/\x{1F}/--/g;
- }
- }
- $text = $self->_protect_space($text);
- return $text;
- }
- $default_types_conversion{'text'} = \&_convert_text;
- sub _simplify_text_for_comparison($)
- {
- my $text = shift;
- $text =~ s/[^\w]//g;
- return $text;
- }
- sub _convert_row_type($$$$) {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- return $content if ($self->in_string());
- if ($content =~ /\S/) {
- my $row_cmdname = $command->{'contents'}->[0]->{'cmdname'};
- if ($row_cmdname eq 'headitem') {
- return '<thead><tr>' . $content . '</tr></thead>' . "\n";
- } else {
- return '<tr>' . $content . '</tr>' . "\n";
- }
- } else {
- return '';
- }
- }
- $default_types_conversion{'row'} = \&_convert_row_type;
- sub _convert_menu_entry_type($$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
-
- my $href;
- my $node;
- my $section;
- my $node_entry = $command->{'extra'}->{'menu_entry_node'};
- # external node
- my $external_node;
- if ($node_entry->{'manual_content'}) {
- $href = $self->command_href($node_entry, undef, $command);
- $external_node = 1;
- } else {
- $node = $self->label_command($node_entry->{'normalized'});
- # if !NODE_NAME_IN_MENU, we pick the associated section, except if
- # the node is the element command
- if ($node->{'extra'}->{'associated_section'}
- and !$self->get_conf('NODE_NAME_IN_MENU')
- and !($self->command_element_command($node) eq $node)) {
- $section = $node->{'extra'}->{'associated_section'};
- $href = $self->command_href($section, undef, $command);
- } else {
- $href = $self->command_href($node, undef, $command);
- }
- }
- $html_menu_entry_index++;
- my $accesskey = '';
- $accesskey = " accesskey=\"$html_menu_entry_index\""
- if ($self->get_conf('USE_ACCESSKEY') and $html_menu_entry_index < 10);
- my $MENU_SYMBOL = $self->get_conf('MENU_SYMBOL');
- my $MENU_ENTRY_COLON = $self->get_conf('MENU_ENTRY_COLON');
- if ($self->_in_preformatted_in_menu() or $self->in_string()) {
- my $result = '';
- my $i = 0;
- my @args = @{$command->{'args'}};
- while (@args) {
- last if ($args[0]->{'type'}
- and $args[0]->{'type'} eq 'menu_entry_description');
- my $arg = shift @args;
- if ($arg->{'type'} and $arg->{'type'} eq 'menu_entry_node') {
- my $name = $self->convert_tree(
- {'type' => '_code', 'contents' => $arg->{'contents'}});
- if ($href ne '' and !$self->in_string()) {
- $result .= "<a href=\"$href\"$accesskey>".$name."</a>";
- } else {
- $result .= $name;
- }
- } elsif ($arg->{'type'} and $arg->{'type'} eq 'menu_entry_leading_text') {
- my $text = $arg->{'text'};
-
- $text =~ s/\*/$MENU_SYMBOL/;
- $result .= $text;
- } else {
- $result .= $self->convert_tree($arg, "menu_arg preformatted [$i]");
- }
- $i++;
- }
- my $description = '';
- foreach my $arg (@args) {
- $description .= $self->convert_tree($arg, "menu_arg preformatted [$i]");
- $i++;
- }
- if (!$self->get_conf('SIMPLE_MENU')) {
- $description =~ s/^<pre[^>]*>//;
- $description =~ s/<\/pre>$//;
- }
- $result = $result . $description;
- if (!$self->get_conf('SIMPLE_MENU')) {
- my $pre_class = $self->_preformatted_class();
- $result = $self->_attribute_class('pre', $pre_class).">".$result."</pre>";
- }
- return $result;
- }
- my $name;
- my $name_no_number;
- if ($section) {
- #my $section_name = $self->command_text($section);
- $name = $self->command_text($section);
- $name_no_number = $self->command_text($section, 'text_nonumber');
- if ($href ne '' and $name ne '') {
- #$name = "<a href=\"$href\"$accesskey>".$section_name."</a>";
- $name = "<a href=\"$href\"$accesskey>".$name."</a>";
- }# else {
- # $name = $section_name;
- #}
- #$name = "$MENU_SYMBOL ".$name if ($section_name eq $name_no_number);
- }
- if (!defined($name) or $name eq '') {
- if ($command->{'extra'}->{'menu_entry_name'}) {
- $name = $self->convert_tree($command->{'extra'}->{'menu_entry_name'});
- }
- if (!defined($name) or $name eq '') {
- if ($node_entry->{'manual_content'}) {
- $name = $self->command_text($node_entry);
- } else {
- $name = $self->convert_tree({'type' => '_code',
- 'contents' => $node_entry->{'node_content'}},
- "menu_arg name");
- }
- }
- $name =~ s/^\s*//;
- $name_no_number = $name;
- if ($href ne '') {
- $name = "<a href=\"$href\"$accesskey>".$name."</a>";
- }
- $name = "$MENU_SYMBOL ".$name;
- }
- my $description = '';
- if ($command->{'extra'}->{'menu_entry_description'}) {
- $description = $self->convert_tree ($command->{'extra'}->{'menu_entry_description'},
- "menu_arg description");
- if ($self->get_conf('AVOID_MENU_REDUNDANCY')) {
- $description = '' if (_simplify_text_for_comparison($name_no_number)
- eq _simplify_text_for_comparison($description));
- }
- }
- return "<tr><td align=\"left\" valign=\"top\">$name$MENU_ENTRY_COLON</td><td> </td><td align=\"left\" valign=\"top\">$description</td></tr>\n";
- }
- $default_types_conversion{'menu_entry'} = \&_convert_menu_entry_type;
- sub _convert_menu_comment_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- if ($self->_in_preformatted_in_menu() or $self->in_string()) {
- return $content;
- } else {
- return "<tr><th colspan=\"3\" align=\"left\" valign=\"top\">".$content
- ."</th></tr>";
- }
- }
- $default_types_conversion{'menu_comment'} = \&_convert_menu_comment_type;
- sub _convert_before_item_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- return '' if ($content !~ /\S/);
- return $content if ($self->in_string());
- my $top_format = $self->top_format();
- if ($top_format eq 'itemize' or $top_format eq 'enumerate') {
- return '<li>'. $content .'</li>';
- } elsif ($top_format eq 'table' or $top_format eq 'vtable'
- or $top_format eq 'ftable') {
- return '<dd>'. $content .'</dd>'."\n";
- } elsif ($top_format eq 'multitable') {
- $content =~ s/^\s*//;
- $content =~ s/\s*$//;
- return '<tr><td>'.$content.'</td></tr>'."\n";
- }
- }
- $default_types_conversion{'before_item'} = \&_convert_before_item_type;
- sub _convert_def_line_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- if ($self->in_string()) {
- return $self->protect_text(Texinfo::Convert::Text::convert(
- $command, Texinfo::Common::_convert_text_options($self)));
- }
- my $index_label = '';
- my $index_id = $self->command_id($command);
- if (defined($index_id) and $index_id ne '' and !@{$self->{'multiple_pass'}}) {
- $index_label = "<a name=\"$index_id\"></a>";
- }
- my $arguments
- = Texinfo::Common::definition_arguments_content($command);
- if (!$self->get_conf('DEF_TABLE')) {
- my $tree;
- my $command_name;
- if ($Texinfo::Common::def_aliases{$command->{'extra'}->{'def_command'}}) {
- $command_name = $Texinfo::Common::def_aliases{$command->{'extra'}->{'def_command'}};
- } else {
- $command_name = $command->{'extra'}->{'def_command'};
- }
- my $name;
- if ($command->{'extra'}->{'def_parsed_hash'}->{'name'}) {
- $name = $command->{'extra'}->{'def_parsed_hash'}->{'name'};
- } else {
- $name = '';
- }
- my $category;
- if ($command->{'extra'}->{'def_parsed_hash'}->{'category'}) {
- $category = $command->{'extra'}->{'def_parsed_hash'}->{'category'};
- } else {
- $category = '';
- }
- if ($command_name eq 'deffn'
- or $command_name eq 'defvr'
- or $command_name eq 'deftp'
- or (($command_name eq 'deftypefn'
- or $command_name eq 'deftypevr')
- and !$command->{'extra'}->{'def_parsed_hash'}->{'type'})
- or (($command_name eq 'defop'
- or ($command_name eq 'deftypeop'
- and !$command->{'extra'}->{'def_parsed_hash'}->{'type'})
- or $command_name eq 'defcv'
- or ($command_name eq 'deftypecv'
- and !$command->{'extra'}->{'def_parsed_hash'}->{'type'}))
- and !$command->{'extra'}->{'def_parsed_hash'}->{'class'})) {
- if ($arguments) {
- $tree = $self->gdt("{category}: \@strong{{name}} \@emph{{arguments}}", {
- 'category' => $category,
- 'name' => $name,
- 'arguments' => $arguments});
- } else {
- $tree = $self->gdt("{category}: \@strong{{name}}", {
- 'category' => $category,
- 'name' => $name});
- }
- } elsif ($command_name eq 'deftypefn'
- or $command_name eq 'deftypevr'
- or (($command_name eq 'deftypeop'
- or $command_name eq 'deftypecv')
- and !$command->{'extra'}->{'def_parsed_hash'}->{'class'})) {
- if ($arguments) {
- my $strings = {
- 'category' => $category,
- 'name' => $name,
- 'type' => $command->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'arguments' => $arguments};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("{category}:\@* \@emph{{type}}\@* \@strong{{name}} \@emph{{arguments}}",
- $strings);
- } else {
- $tree
- = $self->gdt("{category}: \@emph{{type}} \@strong{{name}} \@emph{{arguments}}",
- $strings);
- }
- } else {
- my $strings = {
- 'category' => $category,
- 'type' => $command->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'name' => $name};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree = $self->gdt("{category}:\@* \@emph{{type}}\@* \@strong{{name}}",
- $strings);
- } else {
- $tree = $self->gdt("{category}: \@emph{{type}} \@strong{{name}}",
- $strings);
- }
- }
- } elsif ($command_name eq 'defcv'
- or ($command_name eq 'deftypecv'
- and !$command->{'extra'}->{'def_parsed_hash'}->{'type'})) {
- if ($arguments) {
- $tree = $self->gdt("{category} of {class}: \@strong{{name}} \@emph{{arguments}}", {
- 'category' => $category,
- 'name' => $name,
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'arguments' => $arguments});
- } else {
- $tree = $self->gdt("{category} of {class}: \@strong{{name}}", {
- 'category' => $category,
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'name' => $name});
- }
- } elsif ($command_name eq 'defop'
- or ($command_name eq 'deftypeop'
- and !$command->{'extra'}->{'def_parsed_hash'}->{'type'})) {
- if ($arguments) {
- $tree = $self->gdt("{category} on {class}: \@strong{{name}} \@emph{{arguments}}", {
- 'category' => $category,
- 'name' => $name,
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'arguments' => $arguments});
- } else {
- $tree = $self->gdt("{category} on {class}: \@strong{{name}}", {
- 'category' => $category,
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'name' => $name});
- }
- } elsif ($command_name eq 'deftypeop') {
- if ($arguments) {
- my $strings = {
- 'category' => $category,
- 'name' => $name,
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'type' => $command->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'arguments' => $arguments};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("{category} on {class}:\@* \@emph{{type}}\@* \@strong{{name}} \@emph{{arguments}}",
- $strings);
- } else {
- $tree
- = $self->gdt("{category} on {class}: \@emph{{type}} \@strong{{name}} \@emph{{arguments}}",
- $strings);
- }
- } else {
- my $strings = {
- 'category' => $category,
- 'type' => $command->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'name' => $name};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("{category} on {class}:\@* \@emph{{type}}\@* \@strong{{name}}",
- $strings);
- } else {
- $tree
- = $self->gdt("{category} on {class}: \@emph{{type}} \@strong{{name}}",
- $strings);
- }
- }
- } elsif ($command_name eq 'deftypecv') {
- if ($arguments) {
- my $strings = {
- 'category' => $category,
- 'name' => $name,
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'type' => $command->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'arguments' => $arguments};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("{category} of {class}:\@* \@emph{{type}}\@* \@strong{{name}} \@emph{{arguments}}",
- $strings);
- } else {
- $tree
- = $self->gdt("{category} of {class}: \@emph{{type}} \@strong{{name}} \@emph{{arguments}}",
- $strings);
- }
- } else {
- my $strings = {
- 'category' => $category,
- 'type' => $command->{'extra'}->{'def_parsed_hash'}->{'type'},
- 'class' => $command->{'extra'}->{'def_parsed_hash'}->{'class'},
- 'name' => $name};
- if ($self->get_conf('deftypefnnewline') eq 'on') {
- $tree
- = $self->gdt("{category} of {class}:\@* \@emph{{type}}\@* \@strong{{name}}",
- $strings);
- } else {
- $tree
- = $self->gdt("{category} of {class}: \@emph{{type}} \@strong{{name}}",
- $strings);
- }
- }
- }
- return '<dt>'.$index_label.$self->convert_tree({'type' => '_code',
- 'contents' => [$tree]}) . "</dt>\n";
- } else {
- my $category_prepared = '';
- if ($command->{'extra'} and $command->{'extra'}->{'def_args'}
- and @{$command->{'extra'}->{'def_args'}}) {
- my $parsed_definition_category
- = Texinfo::Common::definition_category ($self, $command);
- if ($parsed_definition_category) {
- $category_prepared = $self->convert_tree({'type' => '_code',
- 'contents' => [$parsed_definition_category]});
- }
- }
-
- my $arguments_text = '';
- if ($arguments) {
- $arguments_text = $self->convert_tree({'type' => '_code',
- 'contents' => $arguments});
- $arguments_text = '<em> ' . $arguments_text . '</em>'
- if ($arguments_text =~ /\S/);
- }
-
- my $def_type = '';
- my $type_name = '';
- if ($command->{'extra'}->{'def_parsed_hash'}->{'type'}) {
- $def_type = $self->convert_tree({'type' => '_code',
- 'contents' => [$command->{'extra'}->{'def_parsed_hash'}->{'type'}]});
- }
- $type_name = " <em>$def_type</em>" if ($def_type ne '');
- my $name = '';
- if ($command->{'extra'}->{'def_parsed_hash'}->{'name'}) {
- $name = $self->convert_tree({'type' => '_code',
- 'contents' => [$command->{'extra'}->{'def_parsed_hash'}->{'name'}]});
- }
- $type_name .= ' <strong>' . $name . '</strong>' if ($name ne '');
- $type_name .= $arguments_text;
- return "<tr><td align=\"left\">" . $type_name .
- "</td><td align=\"right\">" . $category_prepared .
- $index_label . "</td></tr>\n";
- }
- }
- $default_types_conversion{'def_line'} = \&_convert_def_line_type;
- sub _convert_def_item_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- return $content if ($self->in_string());
- if ($content =~ /\S/) {
- if (! $self->get_conf('DEF_TABLE')) {
- return '<dd>' . $content . '</dd>';
- } else {
- return '<tr><td colspan="2">' . $content . '</td></tr>';
- }
- }
- }
- $default_types_conversion{'def_item'} = \&_convert_def_item_type;
- $default_types_conversion{'inter_def_item'} = \&_convert_def_item_type;
- sub _convert_def_command($$$$) {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $content = shift;
- return $content if ($self->in_string());
- #print STDERR "IIII $self $cmdname command $command args $args content $content\n";
- if (!$self->get_conf('DEF_TABLE')) {
- return "<dl>\n". $content ."</dl>\n";
- } else {
- return "<table width=\"100%\">\n" . $content . "</table>\n";
- }
- }
- foreach my $command (keys(%def_commands)) {
- $default_commands_conversion{$command} = \&_convert_def_command;
- }
- sub _convert_table_item_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- return $content if ($self->in_string());
- if ($content =~ /\S/) {
- return '<dd>' . $content . '</dd>'."\n";
- }
- }
- $default_types_conversion{'table_item'} = \&_convert_table_item_type;
- $default_types_conversion{'inter_item'} = \&_convert_table_item_type;
- # This type is the only one present if there are no elements. It is
- # therefore used to do the formatting of the element in case there are no
- # element.
- sub _convert_root_text_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $command = shift;
- my $content = shift;
- my $result = $content;
- #$result =~ s/^\s*//;
- # if there is no element, the parent should not be an element
- if (!$command->{'parent'}
- or !$command->{'parent'}->{'type'}
- or $command->{'parent'}->{'type'} ne 'element') {
- $result .= &{$self->{'format_footnotes_text'}}($self);
- $result .= $self->get_conf('DEFAULT_RULE') ."\n",
- if ($self->get_conf('PROGRAM_NAME_IN_FOOTER')
- and defined($self->get_conf('DEFAULT_RULE'))
- and !$self->in_string());
- }
- return $result;
- }
- $default_types_conversion{'text_root'} = \&_convert_root_text_type;
- # Convert @titlepage. Falls back to simpletitle.
- sub _default_titlepage($)
- {
- my $self = shift;
- my $titlepage_text;
- if ($self->{'extra'}->{'titlepage'}) {
- $titlepage_text = $self->convert_tree({'contents'
- => $self->{'extra'}->{'titlepage'}->{'contents'}});
- } elsif ($self->{'simpletitle_tree'}) {
- my $title_text = $self->convert_tree_new_formatting_context(
- $self->{'simpletitle_tree'}, 'simpletitle_string');
- $titlepage_text = &{$self->{'format_heading_text'}}($self, 'settitle', $title_text,
- 0, {'cmdname' => 'settitle',
- 'contents' => $self->{'simpletitle_tree'}->{'contents'}});
- }
- my $result = '';
- $result .= $titlepage_text.$self->get_conf('DEFAULT_RULE')."\n"
- if (defined($titlepage_text));
- return $result;
- }
- sub _print_title($)
- {
- my $self = shift;
- my $result = '';
- if ($self->get_conf('SHOW_TITLE')) {
- if ($self->get_conf('USE_TITLEPAGE_FOR_TITLE')) {
- $result .= &{$self->{'format_titlepage'}}($self);
- } else {
- if ($self->{'simpletitle_tree'}) {
- my $title_text = $self->convert_tree_new_formatting_context(
- $self->{'simpletitle_tree'}, 'simpletitle_string');
- $result .= &{$self->{'format_heading_text'}}($self, 'settitle', $title_text,
- 0, {'cmdname' => 'settitle',
- 'contents' => $self->{'simpletitle_tree'}->{'contents'}});
- }
- }
- }
- return $result;
- }
- # Function for converting the top-level elements in the conversion: a section
- # or a node. $ELEMENT was created in this module (in _prepare_elements), with
- # type 'element' (it's not a tree element created by the parser). $CONTENT
- # is the contents of the node/section, already converted.
- sub _convert_element_type($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $element = shift;
- my $content = shift;
- if ($self->in_string()) {
- if (defined($content)) {
- return $content;
- } else {
- return '';
- }
- }
- my $result = '';
- my $special_element;
- if ($element->{'extra'}->{'special_element'}) {
- $special_element = $element->{'extra'}->{'special_element'};
- my $id = $self->command_id($element);
- if ($id ne '') {
- $result .= "<a name=\"$id\"></a>\n";
- }
- if ($self->get_conf('HEADERS')
- # first in page
- or $self->{'counter_in_file'}->{$element->{'filename'}} == 1) {
- $result .= &{$self->{'format_navigation_header'}}($self,
- $self->get_conf('MISC_BUTTONS'), undef, $element);
-
- }
- my $heading = $self->command_text($element);
- my $element_name = $element->{'extra'}->{'special_element'};
- my $class = $self->get_conf('SPECIAL_ELEMENTS_CLASS')->{$element_name};
- my $level = $self->get_conf('CHAPTER_HEADER_LEVEL');
- if ($element_name eq 'Footnotes') {
- $level = $self->get_conf('FOOTNOTE_SEPARATE_HEADER_LEVEL');
- }
- $result .= &{$self->{'format_heading_text'}}($self, $class.'-heading',
- $heading, $level)."\n";
- my $special_element_body .= &{$self->{'format_special_element_body'}}
- ($self, $special_element, $element);
- # This may happen with footnotes in regions that are not expanded,
- # like @copying or @titlepage
- if ($special_element_body eq '') {
- return '';
- }
- $result .= $special_element_body;
- } elsif (!$element->{'element_prev'}) {
- $result .= $self->_print_title();
- if (!$element->{'element_next'}) {
- # only one element
- my $foot_text = &{$self->{'format_footnotes_text'}}($self);
- return $result.$content.$foot_text.$self->get_conf('DEFAULT_RULE')."\n";
- }
- }
- $result .= $content unless ($special_element);
- $result .= &{$self->{'format_element_footer'}}($self, $type,
- $element, $content);
- return $result;
- }
- sub _default_element_footer($$$$)
- {
- my $self = shift;
- my $type = shift;
- my $element = shift;
- my $content = shift;
- my $result = '';
- my $is_top = $self->element_is_top($element);
- my $next_is_top = ($element->{'element_next'}
- and $self->element_is_top($element->{'element_next'}));
- my $next_is_special = (defined($element->{'element_next'})
- and $element->{'element_next'}->{'extra'}->{'special_element'});
- # no 'parent' defined happens if there are no pages, and there are elements
- # which should only happen when called with $self->{'output_file'}
- # set to ''.
- #print STDERR "$element $element->{'filename'} $self->{'file_counters'}->{$element->{'filename'}}\n";
- #print STDERR "next: $element->{'element_next'}->{'filename'}\n" if ($element->{'element_next'});
- my $end_page = (!$element->{'element_next'}
- or (defined($element->{'filename'})
- and $element->{'filename'} ne $element->{'element_next'}->{'filename'}
- and $self->{'file_counters'}->{$element->{'filename'}} == 1));
- #my $end_page = (!$element->{'element_next'}
- # or (defined($element->{'parent'})
- # and $element->{'parent'} ne $element->{'element_next'}->{'parent'}));
- my $is_special = $element->{'extra'}->{'special_element'};
- if (($end_page or $next_is_top or $next_is_special or $is_top)
- and $self->get_conf('VERTICAL_HEAD_NAVIGATION')
- and ($self->get_conf('SPLIT') ne 'node'
- or $self->get_conf('HEADERS') or $is_special or $is_top)) {
- $result .= "</td>
- </tr>
- </table>"."\n";
- }
- my $rule = '';
- my $buttons;
- my $maybe_in_page;
- if (($is_top or $is_special)
- and ($self->get_conf('SPLIT') or !$self->get_conf('MONOLITHIC'))
- and ($end_page
- and ($self->get_conf('HEADERS')
- or ($self->get_conf('SPLIT') and $self->get_conf('SPLIT') ne 'node')))) {
- if ($is_top) {
- $buttons = $self->get_conf('TOP_BUTTONS');
- } else {
- $buttons = $self->get_conf('MISC_BUTTONS');
- }
- } elsif ($end_page and $self->get_conf('SPLIT') eq 'section') {
- $buttons = $self->get_conf('SECTION_FOOTER_BUTTONS');
- } elsif ($end_page and $self->get_conf('SPLIT') eq 'chapter') {
- $buttons = $self->get_conf('CHAPTER_BUTTONS');
- } elsif ($self->get_conf('SPLIT') eq 'node') {
- if ($self->get_conf('HEADERS')) {
- my $no_footer_word_count;
- if ($self->get_conf('WORDS_IN_PAGE')) {
- my @cnt = split(/\W*\s+\W*/, $content);
- if (scalar(@cnt) < $self->get_conf('WORDS_IN_PAGE')) {
- $no_footer_word_count = 1;
- }
- }
- $buttons = $self->get_conf('NODE_FOOTER_BUTTONS')
- unless ($no_footer_word_count);
- }
- } else {
- $maybe_in_page = 1;
- }
- if ($maybe_in_page or $is_top or $is_special
- or ($end_page and ($self->get_conf('SPLIT') eq 'chapter'
- or $self->get_conf('SPLIT') eq 'section'))
- or ($self->get_conf('SPLIT') eq 'node' and $self->get_conf('HEADERS'))) {
- $rule = $self->get_conf('DEFAULT_RULE');
- }
- if (!$end_page and ($is_top or $next_is_top or ($next_is_special
- and !$is_special))) {
- $rule = $self->get_conf('BIG_RULE');
- }
- # FIXME the following condition is almost a duplication of end_page
- # except that the file counter needs not be 1
- if ((!$element->{'element_next'}
- or (defined($element->{'filename'})
- and $element->{'filename'} ne $element->{'element_next'}->{'filename'}))
- and $self->get_conf('footnotestyle') eq 'end') {
- $result .= &{$self->{'format_footnotes_text'}}($self);
- }
- if (!$self->get_conf('PROGRAM_NAME_IN_FOOTER')
- and !$buttons and !$maybe_in_page) {
- # no rule in that case
- } else {
- $result .= "$rule\n" if ($rule);
- }
- if ($buttons) {
- $result .= &{$self->{'format_navigation_header_panel'}}($self, $buttons,
- undef, $element);
- }
-
- return $result;
- }
- $default_types_conversion{'element'} = \&_convert_element_type;
- sub _new_document_context($$)
- {
- my $self = shift;
- my $cmdname = shift;
- push @{$self->{'document_context'}},
- {'cmdname' => $cmdname,
- 'formatting_context' => [{'cmdname' => $cmdname}],
- 'composition_context' => ['raggedright'],
- 'formats' => [],
- 'monospace' => [0],
- };
- }
- # Functions accessed with e.g. 'format_heading_text' for 'heading_text'.
- my %default_formatting_references = (
- 'heading_text' => \&_default_heading_text,
- 'comment' => \&_default_comment,
- 'protect_text' => \&_default_protect_text,
- 'css_lines' => \&_default_css_lines,
- 'begin_file' => \&_default_begin_file,
- 'node_redirection_page' => \&_default_node_redirection_page,
- 'end_file' => \&_default_end_file,
- 'special_element_body' => \&_default_special_element_body,
- 'footnotes_text' => \&_default_footnotes_text,
- 'program_string' => \&_default_program_string,
- 'titlepage' => \&_default_titlepage,
- 'navigation_header' => \&_default_navigation_header,
- 'navigation_header_panel' => \&_default_navigation_header_panel,
- 'element_header' => \&_default_element_header,
- 'element_footer' => \&_default_element_footer,
- 'button' => \&_default_button_formatting,
- 'button_icon_img' => \&_default_button_icon_img,
- 'external_href' => \&_default_external_href,
- 'contents' => \&_default_contents,
- 'frame_files' => \&_default_frame_files,
- );
- sub _use_entity_is_entity($$)
- {
- my $self = shift;
- my $text = shift;
- return 0 if (!$self->get_conf('ENABLE_ENCODING_USE_ENTITY'));
- return 1 if ($text =~ /^&/ and $text =~ /;$/);
- }
- sub _complete_commands_formatting($$)
- {
- my $self = shift;
- my $command = shift;
- if (!defined ($self->{'commands_formatting'}->{'normal'}->{$command})) {
- $self->{'commands_formatting'}->{'normal'}->{$command} = '';
- }
- if (!defined ($self->{'commands_formatting'}->{'preformatted'}->{$command})) {
- $self->{'commands_formatting'}->{'preformatted'}->{$command} =
- $self->{'commands_formatting'}->{'normal'}->{$command};
- }
- if (!defined ($self->{'commands_formatting'}->{'string'}->{$command})) {
- $self->{'commands_formatting'}->{'string'}->{$command} =
- $self->{'commands_formatting'}->{'preformatted'}->{$command};
- }
- }
- my %htmlxref_entries = (
- 'node' => [ 'node', 'section', 'chapter', 'mono' ],
- 'section' => [ 'section', 'chapter','node', 'mono' ],
- 'chapter' => [ 'chapter', 'section', 'node', 'mono' ],
- 'mono' => [ 'mono', 'chapter', 'section', 'node' ],
- );
- sub _parse_htmlxref_files($$)
- {
- my $self = shift;
- my $files = shift;
- my $htmlxref;
- foreach my $file (@$files) {
- print STDERR "html refs config file: $file\n" if ($self->get_conf('DEBUG'));
- unless (open (HTMLXREF, $file)) {
- $self->document_warn(
- sprintf($self->__("could not open html refs config file %s: %s"),
- $file, $!));
- next;
- }
- my $line_nr = 0;
- my %variables;
- while (my $hline = <HTMLXREF>) {
- my $line = $hline;
- $line_nr++;
- next if $hline =~ /^\s*#/;
- #$hline =~ s/[#]\s.*//;
- $hline =~ s/^\s*//;
- next if $hline =~ /^\s*$/;
- chomp ($hline);
- if ($hline =~ s/^\s*(\w+)\s*=\s*//) {
- # handle variables
- my $var = $1;
- my $re = join '|', map { quotemeta $_ } keys %variables;
- $hline =~ s/\$\{($re)\}/defined $variables{$1} ? $variables{$1}
- : "\${$1}"/ge;
- $variables{$var} = $hline;
- next;
- }
- my @htmlxref = split /\s+/, $hline;
- my $manual = shift @htmlxref;
- my $split_or_mono = shift @htmlxref;
- #print STDERR "$split_or_mono $Texi2HTML::Config::htmlxref_entries{$split_or_mono} $line_nr\n";
- if (!defined($split_or_mono)) {
- $self->file_line_warn($self->__("missing type"), $file, $line_nr);
- next;
- } elsif (!defined($htmlxref_entries{$split_or_mono})) {
- $self->file_line_warn(sprintf($self->__("unrecognized type: %s"),
- $split_or_mono), $file, $line_nr);
- next;
- }
- my $href = shift @htmlxref;
- next if (exists($htmlxref->{$manual}->{$split_or_mono}));
- if (defined($href)) { # substitute 'variables'
- my $re = join '|', map { quotemeta $_ } keys %variables;
- $href =~ s/\$\{($re)\}/defined $variables{$1} ? $variables{$1}
- : "\${$1}"/ge;
- $href =~ s/\/*$// if ($split_or_mono ne 'mono');
- }
- $htmlxref->{$manual}->{$split_or_mono} = $href;
- }
- if (!close (HTMLXREF)) {
- $self->document_warn(sprintf($self->__(
- "error on closing html refs config file %s: %s"),
- $file, $!));
- }
- }
- return $htmlxref;
- }
- sub converter_initialize($)
- {
- my $self = shift;
- if ($self->get_conf('SHORTEXTN')) {
- $self->set_conf('EXTENSION', 'htm');
- }
- $foot_num = 0;
- $foot_lines = '';
- %formatted_index_entries = ();
- %footnote_id_numbers = ();
- %{$self->{'css_map'}} = %css_map;
- $self->{'htmlxref'} = {};
- if ($self->{'htmlxref_files'}) {
- $self->{'htmlxref'} = _parse_htmlxref_files($self,
- $self->{'htmlxref_files'});
- }
- foreach my $type (keys(%default_types_conversion)) {
- if (exists($Texinfo::Config::texinfo_types_conversion{$type})) {
- $self->{'types_conversion'}->{$type}
- = $Texinfo::Config::texinfo_types_conversion{$type};
- } else {
- $self->{'types_conversion'}->{$type}
- = $default_types_conversion{$type};
- }
- }
- # FIXME API with a function call? Used in cvs.init.
- foreach my $type (keys(%default_code_types)) {
- $self->{'code_types'}->{$type} = $default_code_types{$type};
- }
- if ($Texinfo::Config::texinfo_code_types) {
- foreach my $type (keys(%$Texinfo::Config::texinfo_code_types)) {
- $self->{'code_types'}->{$type}
- = $Texinfo::Config::texinfo_code_types->{$type};
- }
- }
- # FIXME put value in a category in Texinfo::Common?
- foreach my $command (keys(%misc_commands), keys(%brace_commands),
- keys (%block_commands), keys(%no_brace_commands), 'value') {
- if (exists($Texinfo::Config::texinfo_commands_conversion{$command})) {
- $self->{'commands_conversion'}->{$command}
- = $Texinfo::Config::texinfo_commands_conversion{$command};
- } else {
- if (!$self->get_conf('SHOW_MENU')
- and ($command eq 'menu' or $command eq 'detailmenu')) {
- $self->{'commands_conversion'}->{$command} = undef;
- } elsif ($format_raw_commands{$command}
- and !$self->{'expanded_formats_hash'}->{$command}) {
- } elsif (exists($default_commands_conversion{$command})) {
- $self->{'commands_conversion'}->{$command}
- = $default_commands_conversion{$command};
- if ($command eq 'menu' and $self->get_conf('SIMPLE_MENU')) {
- $self->{'commands_conversion'}->{$command}
- = $default_commands_conversion{'example'};
- }
- }
- }
- }
- foreach my $context ('normal', 'preformatted', 'string') {
- foreach my $command (keys(%{$default_commands_formatting{'normal'}})) {
- if (exists ($Texinfo::Config::commands_formatting{$context}->{$command})) {
- $self->{'commands_formatting'}->{$context}->{$command}
- = $Texinfo::Config::commands_formatting{$context}->{$command};
- } else {
- if (defined($default_commands_formatting{$context}->{$command})) {
- if ($self->get_conf('ENABLE_ENCODING')
- and Texinfo::Convert::Unicode::unicode_for_brace_no_arg_command(
- $command, $self->get_conf('OUTPUT_ENCODING_NAME'))
- and !$self->_use_entity_is_entity($default_commands_formatting{$context}->{$command})) {
- $self->{'commands_formatting'}->{$context}->{$command}
- = Texinfo::Convert::Unicode::unicode_for_brace_no_arg_command(
- $command, $self->get_conf('OUTPUT_ENCODING_NAME'))
- } else {
- $self->{'commands_formatting'}->{$context}->{$command}
- = $default_commands_formatting{$context}->{$command};
- }
- }
- }
- if (exists ($Texinfo::Config::commands_translation{$context}->{$command})) {
- $self->{'commands_translation'}->{$context}->{$command}
- = $Texinfo::Config::commands_translation{$context}->{$command};
- delete $self->{'translated_commands'}->{$command};
- } elsif (defined($default_commands_translation{$context}->{$command})) {
- $self->{'commands_translation'}->{$context}->{$command}
- = $default_commands_translation{$context}->{$command};
- delete $self->{'translated_commands'}->{$command};
- }
- }
- }
- # set sane defaults in case there is none and the default formatting
- # function is used
- foreach my $command (keys(%{$default_commands_formatting{'normal'}})) {
- if ($self->{'commands_conversion'}->{$command}
- and $self->{'commands_conversion'}->{$command}
- eq $default_commands_conversion{$command}) {
- $self->_complete_commands_formatting($command);
- }
- }
- foreach my $context (keys(%style_commands_formatting)) {
- foreach my $command (keys(%{$style_commands_formatting{$context}})) {
- if (exists ($Texinfo::Config::style_commands_formatting{$context}->{$command})) {
- $self->{'style_commands_formatting'}->{$context}->{$command}
- = $Texinfo::Config::style_commands_formatting{$context}->{$command};
- } elsif (exists($style_commands_formatting{$context}->{$command})) {
- $self->{'style_commands_formatting'}->{$context}->{$command}
- = $style_commands_formatting{$context}->{$command};
- }
- }
- }
- foreach my $command (keys %{$self->{'commands_conversion'}}) {
- if (exists($Texinfo::Config::commands_args{$command})) {
- $self->{'commands_args'}->{$command}
- = $Texinfo::Config::commands_args{$command};
- } elsif (exists($default_commands_args{$command})) {
- $self->{'commands_args'}->{$command} = $default_commands_args{$command};
- }
- }
- foreach my $formatting_reference (keys(%default_formatting_references)) {
- $self->{'default_formatting_functions'}->{$formatting_reference}
- = $default_formatting_references{$formatting_reference};
- if (defined($Texinfo::Config::texinfo_formatting_references{$formatting_reference})) {
- $self->{"format_".$formatting_reference}
- = $Texinfo::Config::texinfo_formatting_references{$formatting_reference};
- } else {
- $self->{"format_".$formatting_reference}
- = $default_formatting_references{$formatting_reference};
- }
- }
- if ($Texinfo::Config::renamed_nodes) {
- %{$self->{'renamed_nodes'}} = %{$Texinfo::Config::renamed_nodes};
- }
- $self->{'document_context'} = [];
- $self->{'multiple_pass'} = [];
- $self->_new_document_context('_toplevel_context');
- if ($self->get_conf('SPLIT') and $self->get_conf('SPLIT') ne 'chapter'
- and $self->get_conf('SPLIT') ne 'section'
- and $self->get_conf('SPLIT') ne 'node') {
- $self->force_conf('SPLIT', 'node');
- }
- return $self;
- }
- # the entry point for _convert
- sub convert_tree($$;$)
- {
- my $self = shift;
- my $element = shift;
- my $explanation = shift;
- return $self->_convert($element, $explanation);
- }
- sub _normalized_to_id($)
- {
- my $id = shift;
- if (!defined($id)) {
- cluck "_normalized_to_id id not defined";
- return '';
- }
- $id =~ s/^([0-9_])/g_t$1/;
- return $id;
- }
- sub _default_css_lines ($)
- {
- my $self = shift;
- return if ($self->get_conf('NO_CSS'));
- my $css_refs = $self->get_conf('CSS_REFS');
- return if (!@{$self->{'css_import_lines'}} and !@{$self->{'css_rule_lines'}}
- and !keys(%{$self->{'css_map'}}) and !@$css_refs);
- my $css_text = "<style type=\"text/css\">\n<!--\n";
- $css_text .= join('',@{$self->{'css_import_lines'}}) . "\n"
- if (@{$self->{'css_import_lines'}});
- foreach my $css_rule (sort(keys(%{$self->{'css_map'}}))) {
- next unless ($self->{'css_map'}->{$css_rule});
- $css_text .= "$css_rule {$self->{'css_map'}->{$css_rule}}\n";
- }
- $css_text .= join('',@{$self->{'css_rule_lines'}}) . "\n"
- if (@{$self->{'css_rule_lines'}});
- $css_text .= "-->\n</style>\n";
- foreach my $ref (@$css_refs) {
- $css_text .= "<link rel=\"stylesheet\" type=\"text/css\" href=\"$ref\">\n";
- }
- $self->set_conf('CSS_LINES', $css_text);
- }
- sub _process_css_file($$$)
- {
- my $self = shift;
- my $fh =shift;
- my $file = shift;
- my $in_rules = 0;
- my $in_comment = 0;
- my $in_import = 0;
- my $in_string = 0;
- my $rules = [];
- my $imports = [];
- my $line_nr = 0;
- while (my $line = <$fh>) {
- $line_nr++;
- #print STDERR "Line: $line";
- if ($in_rules) {
- push @$rules, $line;
- next;
- }
- my $text = '';
- while (1) {
- #sleep 1;
- #print STDERR "${text}!in_comment $in_comment in_rules $in_rules in_import $in_import in_string $in_string: $line";
- if ($in_comment) {
- if ($line =~ s/^(.*?\*\/)//) {
- $text .= $1;
- $in_comment = 0;
- } else {
- push @$imports, $text . $line;
- last;
- }
- } elsif (!$in_string and $line =~ s/^\///) {
- if ($line =~ s/^\*//) {
- $text .= '/*';
- $in_comment = 1;
- } else {
- push (@$imports, $text. "\n") if ($text ne '');
- push (@$rules, '/' . $line);
- $in_rules = 1;
- last;
- }
- } elsif (!$in_string and $in_import and $line =~ s/^([\"\'])//) {
- # strings outside of import start rules
- $text .= "$1";
- $in_string = quotemeta("$1");
- } elsif ($in_string and $line =~ s/^(\\$in_string)//) {
- $text .= $1;
- } elsif ($in_string and $line =~ s/^($in_string)//) {
- $text .= $1;
- $in_string = 0;
- } elsif ((! $in_string and !$in_import)
- and ($line =~ s/^([\\]?\@import)$//
- or $line =~ s/^([\\]?\@import\s+)//)) {
- $text .= $1;
- $in_import = 1;
- } elsif (!$in_string and $in_import and $line =~ s/^\;//) {
- $text .= ';';
- $in_import = 0;
- } elsif (($in_import or $in_string) and $line =~ s/^(.)//) {
- $text .= $1;
- } elsif (!$in_import and $line =~ s/^([^\s])//) {
- push (@$imports, $text. "\n") if ($text ne '');
- push (@$rules, $1 . $line);
- $in_rules = 1;
- last;
- } elsif ($line =~ s/^(\s)//) {
- $text .= $1;
- } elsif ($line eq '') {
- push (@$imports, $text);
- last;
- }
- }
- }
- #file_line_warn (__("string not closed in css file"), $file) if ($in_string);
- #file_line_warn (__("--css-file ended in comment"), $file) if ($in_comment);
- #file_line_warn (__("\@import not finished in css file"), $file) if ($in_import and !$in_comment and !$in_string);
- $self->file_line_warn(sprintf($self->__("string not closed in css file"),
- $file, $line_nr)) if ($in_string);
- $self->file_line_warn(sprintf($self->__("--css-include ended in comment"),
- $file, $line_nr)) if ($in_comment);
- $self->file_line_warn(sprintf($self->__("\@import not finished in css file"),
- $file, $line_nr))
- if ($in_import and !$in_comment and !$in_string);
- return ($imports, $rules);
- }
- sub _prepare_css($)
- {
- my $self = shift;
-
- return if ($self->get_conf('NO_CSS'));
- my @css_import_lines;
- my @css_rule_lines;
- my $css_files = $self->get_conf('CSS_FILES');
- foreach my $file (@$css_files) {
- my $css_file_fh;
- my $css_file;
- if ($file eq '-') {
- $css_file_fh = \*STDIN;
- $css_file = '-';
- } else {
- $css_file = $self->Texinfo::Common::locate_include_file($file);
- unless (defined($css_file)) {
- $self->document_warn(sprintf(
- $self->__("CSS file %s not found"), $file));
- next;
- }
- # FIXME use open_out?
- unless (open (CSSFILE, $css_file)) {
- $self->document_warn(sprintf($self->__(
- "could not open --include-file %s: %s"),
- $css_file, $!));
- next;
- }
- $css_file_fh = \*CSSFILE;
- }
- my ($import_lines, $rules_lines);
- ($import_lines, $rules_lines)
- = $self->_process_css_file ($css_file_fh, $css_file);
- if (!close($css_file_fh)) {
- $self->document_warn(sprintf($self->__("error on closing CSS file %s: %s"),
- $css_file, $!));
- }
- push @css_import_lines, @$import_lines;
- push @css_rule_lines, @$rules_lines;
- }
- if ($self->get_conf('DEBUG')) {
- if (@css_import_lines) {
- print STDERR "# css import lines\n";
- foreach my $line (@css_import_lines) {
- print STDERR "$line";
- }
- }
- if (@css_rule_lines) {
- print STDERR "# css rule lines\n";
- foreach my $line (@css_rule_lines) {
- print STDERR "$line";
- }
- }
- }
- $self->{'css_import_lines'} = \@css_import_lines;
- $self->{'css_rule_lines'} = \@css_rule_lines;
- }
- # Get the name of a file containing a node, as well as the anchor within
- # that file to link to that node. Argument is the 'extra' value on
- # an element hash, or something that looks like it.
- sub _node_id_file($$)
- {
- my $self = shift;
- my $node_info = shift;
- my $target;
- my $normalized;
- if ($node_info->{'normalized'}) {
- $normalized = $node_info->{'normalized'};
- } elsif ($node_info->{'node_content'}) {
- $normalized = Texinfo::Convert::NodeNameNormalization::normalize_node (
- { 'contents' => $node_info->{'node_content'} });
- }
- if (defined($normalized)) {
- $target = _normalized_to_id($normalized);
- } else {
- $target = '';
- }
- # to find out the Top node, one could check $node_info->{'normalized'}
- if (defined($Texinfo::Config::node_target_name)) {
- $target = &$Texinfo::Config::node_target_name($node_info, $target);
- }
- my $filename = $self->_node_filename($node_info);
- return ($filename, $target);
- }
- sub _new_sectioning_command_target($$)
- {
- my $self = shift;
- my $command = shift;
- my ($normalized_name, $filename)
- = $self->_sectioning_command_normalized_filename($command);
- my $target_base = _normalized_to_id($normalized_name);
- if ($target_base !~ /\S/ and $command->{'cmdname'} eq 'top'
- and defined($self->{'misc_elements_targets'}->{'Top'})) {
- $target_base = $self->{'misc_elements_targets'}->{'Top'};
- }
- my $nr=1;
- my $target = $target_base;
- if ($target ne '') {
- while ($self->{'seen_ids'}->{$target}) {
- $target = $target_base.'-'.$nr;
- $nr++;
- # Avoid integer overflow
- die if ($nr == 0);
- }
- }
- # These are undefined if the $target is set to ''.
- my $target_contents;
- my $target_shortcontents;
- if ($Texinfo::Common::sectioning_commands{$command->{'cmdname'}}) {
- if ($target ne '') {
- my $target_base_contents = $target;
- $target_base_contents =~ s/^g_t//;
- $target_contents = 'toc-'.$target_base_contents;
- my $toc_nr = $nr -1;
- while ($self->{'seen_ids'}->{$target_contents}) {
- $target_contents = 'toc-'.$target_base_contents.'-'.$toc_nr;
- $toc_nr++;
- # Avoid integer overflow
- die if ($toc_nr == 0);
- }
- $target_shortcontents = 'stoc-'.$target_base_contents;
- my $target_base_shortcontents = $target_base;
- $target_base_shortcontents =~ s/^g_t//;
- my $stoc_nr = $nr -1;
- while ($self->{'seen_ids'}->{$target_shortcontents}) {
- $target_shortcontents = 'stoc-'.$target_base_shortcontents
- .'-'.$stoc_nr;
- $stoc_nr++;
- # Avoid integer overflow
- die if ($stoc_nr == 0);
- }
- }
- }
- if (defined($Texinfo::Config::sectioning_command_target_name)) {
- ($target, $target_contents,
- $target_shortcontents, $filename)
- = &$Texinfo::Config::sectioning_command_target_name($self,
- $command, $target,
- $target_contents,
- $target_shortcontents,
- $filename);
- }
- if ($self->get_conf('DEBUG')) {
- print STDERR "Register $command->{'cmdname'} $target\n";
- }
- $self->{'targets'}->{$command} = {
- 'target' => $target,
- 'section_filename' => $filename,
- };
- $self->{'seen_ids'}->{$target} = 1;
- if (defined($target_contents)) {
- $self->{'targets'}->{$command}->{'contents_target'} = $target_contents;
- } else {
- $self->{'targets'}->{$command}->{'contents_target'} = '';
- }
- if (defined($target_shortcontents)) {
- $self->{'targets'}->{$command}->{'shortcontents_target'}
- = $target_shortcontents;
- } else {
- $self->{'targets'}->{$command}->{'shortcontents_target'} = '';
- }
- return $self->{'targets'}->{$command};
- }
- # This set 2 unrelated things.
- # * The targets and id of sectioning elements
- # * the target, id and normalized filename of 'labels', ie everything that
- # may be the target of a ref, like @node, @float, @anchor...
- # conversion to HTML is done on-demand, upon call to command_text.
- sub _set_root_commands_targets_node_files($$)
- {
- my $self = shift;
- my $elements = shift;
- my $no_unidecode;
- $no_unidecode = 1 if (defined($self->get_conf('USE_UNIDECODE'))
- and !$self->get_conf('USE_UNIDECODE'));
- if ($self->{'labels'}) {
- foreach my $root_command (values(%{$self->{'labels'}})) {
- my ($filename, $target) = $self->_node_id_file($root_command->{'extra'});
- $filename .= '.'.$self->get_conf('NODE_FILE_EXTENSION')
- if (defined($self->get_conf('NODE_FILE_EXTENSION'))
- and $self->get_conf('NODE_FILE_EXTENSION') ne '');
- if (defined($Texinfo::Config::node_file_name)) {
- $filename = &$Texinfo::Config::node_file_name($self, $root_command,
- $filename);
- }
- if ($self->get_conf('DEBUG')) {
- print STDERR "Register label($root_command) $target, $filename\n";
- }
- $self->{'targets'}->{$root_command} = {'target' => $target,
- 'node_filename' => $filename};
- $self->{'seen_ids'}->{$target} = 1;
- }
- }
- if ($elements) {
- foreach my $element (@$elements) {
- foreach my $root_command(@{$element->{'contents'}}) {
- # this happens for type 'text_root' which precedes the
- # root commands. The target may also already be set for top node.
- next if (!defined($root_command->{'cmdname'})
- or $self->{'targets'}->{$root_command});
- if ($Texinfo::Common::sectioning_commands{$root_command->{'cmdname'}}) {
- $self->_new_sectioning_command_target($root_command);
- }
- }
- }
- }
- }
- sub _get_element($$;$);
- # If $find_container is set, the element that holds the command is found,
- # otherwise the element that holds the command content is found. This is
- # mostly relevant for footnote only.
- sub _get_element($$;$)
- {
- my $self = shift;
- my $command = shift;
- my $find_container = shift;
- my $current = $command;
- my ($element, $root_command);
- while (1) {
- if ($current->{'type'}) {
- if ($current->{'type'} eq 'element') {
- return ($current, $root_command);
- }
- }
- if ($current->{'cmdname'}) {
- if ($root_commands{$current->{'cmdname'}}) {
- $root_command = $current;
- return ($element, $root_command) if defined($element);
- } elsif ($region_commands{$current->{'cmdname'}}) {
- if ($current->{'cmdname'} eq 'copying'
- and $self->{'extra'} and $self->{'extra'}->{'insertcopying'}) {
- foreach my $insertcopying(@{$self->{'extra'}->{'insertcopying'}}) {
- my ($element, $root_command)
- = $self->_get_element($insertcopying, $find_container);
- return ($element, $root_command)
- if (defined($element) or defined($root_command));
- }
- } elsif ($current->{'cmdname'} eq 'titlepage'
- and $self->get_conf('USE_TITLEPAGE_FOR_TITLE')
- and $self->get_conf('SHOW_TITLE')
- and $self->{'elements'}->[0]) {
- return ($self->{'elements'}->[0],
- $self->{'elements'}->[0]->{'extra'}->{'element_command'});
- }
- die "Problem $element, $root_command" if (defined($element)
- or defined($root_command));
- return (undef, undef);
- } elsif ($current->{'cmdname'} eq 'footnote'
- and $self->{'special_elements_types'}->{'Footnotes'}
- and $find_container) {
- # in that case there is no root_command
- $element = $self->{'special_elements_types'}->{'Footnotes'};
- return ($element);
- }
- }
- if ($current->{'parent'}) {
- $current = $current->{'parent'};
- } else {
- return ($element, $root_command);
- }
- }
- }
- sub _set_pages_files($$)
- {
- my $self = shift;
- my $elements = shift;
- my $special_elements = shift;
- # Ensure that the document has pages
- return undef if (!defined($elements) or !@$elements);
- my $extension = '';
- $extension = '.'.$self->get_conf('EXTENSION')
- if (defined($self->get_conf('EXTENSION'))
- and $self->get_conf('EXTENSION') ne '');
- if (!$self->get_conf('SPLIT')) {
- foreach my $element (@$elements) {
- if (!defined($element->{'filename'})) {
- $element->{'filename'} = $self->{'output_filename'};
- $element->{'out_filename'} = $self->{'output_file'};
- }
- }
- } else {
- my $node_top;
- #my $section_top;
- $node_top = $self->{'labels'}->{'Top'} if ($self->{'labels'});
- #$section_top = $self->{'extra'}->{'top'} if ($self->{'extra'});
-
- my $top_node_filename = $self->_top_node_filename();
- # first determine the top node file name.
- if ($self->get_conf('NODE_FILENAMES') and $node_top
- and defined($top_node_filename)) {
- my ($node_top_element) = $self->_get_element($node_top);
- die "BUG: No element for top node" if (!defined($node_top));
- $self->_set_element_file($node_top_element, $top_node_filename);
- }
- my $file_nr = 0;
- my $previous_page;
- foreach my $element(@$elements) {
- # For Top node.
- next if (defined($element->{'filename'}));
- if (!$element->{'extra'}->{'first_in_page'}) {
- cluck ("No first_in_page for $element\n");
- }
- if (!defined($element->{'extra'}->{'first_in_page'}->{'filename'})) {
- my $file_element = $element->{'extra'}->{'first_in_page'};
- if ($self->get_conf('NODE_FILENAMES')) {
- foreach my $root_command (@{$file_element->{'contents'}}) {
- if ($root_command->{'cmdname'}
- and $root_command->{'cmdname'} eq 'node') {
- my $node_filename;
- # double node are not normalized, they are handled here
- if (!defined($root_command->{'extra'}->{'normalized'})
- or !defined($self->{'labels'}->{$root_command->{'extra'}->{'normalized'}})) {
- $node_filename = 'unknown_node';
- $node_filename .= '.'.$self->get_conf('NODE_FILE_EXTENSION')
- if (defined($self->get_conf('NODE_FILE_EXTENSION'))
- and $self->get_conf('NODE_FILE_EXTENSION') ne '');
- } else {
- if (!defined($self->{'targets'}->{$root_command})
- or !defined($self->{'targets'}->{$root_command}->{'node_filename'})) {
- # Could have been a double node, thus use equivalent node.
- # However since double nodes are not normalized, in fact it
- # never happens.
- $root_command
- = $self->{'labels'}->{$root_command->{'extra'}->{'normalized'}};
- }
- $node_filename
- = $self->{'targets'}->{$root_command}->{'node_filename'};
- }
- $self->_set_element_file($file_element, $node_filename);
- last;
- }
- }
- if (!defined($file_element->{'filename'})) {
- # use section to do the file name if there is no node
- my $command = $self->element_command($file_element);
- if ($command) {
- if ($command->{'cmdname'} eq 'top' and !$node_top
- and defined($top_node_filename)) {
- $self->_set_element_file($file_element, $top_node_filename);
- } else {
- $self->_set_element_file($file_element,
- $self->{'targets'}->{$command}->{'section_filename'});
- }
- } else {
- # when everything else has failed
- if ($file_nr == 0 and !$node_top
- and defined($top_node_filename)) {
- $self->_set_element_file($file_element, $top_node_filename);
- } else {
- my $filename = $self->{'document_name'} . "_$file_nr";
- $filename .= $extension;
- $self->_set_element_file($element, $filename);
- }
- $file_nr++;
- }
- }
- } else {
- my $filename = $self->{'document_name'} . "_$file_nr";
- $filename .= '.'.$self->get_conf('EXTENSION')
- if (defined($self->get_conf('EXTENSION'))
- and $self->get_conf('EXTENSION') ne '');
- $self->_set_element_file($file_element, $filename);
- $file_nr++;
- }
- }
- $element->{'filename'}
- = $element->{'extra'}->{'first_in_page'}->{'filename'};
- $element->{'out_filename'}
- = $element->{'extra'}->{'first_in_page'}->{'out_filename'};
- }
- }
- foreach my $element (@$elements) {
- if (defined($Texinfo::Config::element_file_name)) {
- # NOTE the information that it is associated with @top or @node Top
- # may be determined with $self->element_is_top($element);
- my $filename = &$Texinfo::Config::element_file_name($self, $element,
- $element->{'filename'});
- $self->_set_element_file($element, $filename) if (defined($filename));
- }
- $self->{'file_counters'}->{$element->{'filename'}}++;
- print STDERR "Page $element ".Texinfo::Structuring::_print_element_command_texi($element).": $element->{'filename'}($self->{'file_counters'}->{$element->{'filename'}})\n"
- if ($self->get_conf('DEBUG'));
- }
- if ($special_elements) {
- my $previous_element = $elements->[-1];
- foreach my $element (@$special_elements) {
- my $filename
- = $self->{'targets'}->{$element}->{'misc_filename'};
- if (defined($filename)) {
- $self->_set_element_file($element, $filename);
- $self->{'file_counters'}->{$element->{'filename'}}++;
- print STDERR "Special page $element: $element->{'filename'}($self->{'file_counters'}->{$element->{'filename'}})\n"
- if ($self->get_conf('DEBUG'));
- }
- $element->{'element_prev'} = $previous_element;
- $previous_element->{'element_next'} = $element;
- $previous_element = $element;
- }
- }
- }
- # $ROOT is a parsed Texinfo tree. Return a list of the "elements" we need to
- # output in the HTML file(s). Each "element" is what can go in one HTML file,
- # such as the content between @node lines in the Texinfo source.
- sub _prepare_elements($$)
- {
- my $self = shift;
- my $root = shift;
- my $elements;
- # do that now to have it available for formatting
- # NOTE this calls Convert::Converter::_informative_command on all the
- # @informative_global commands.
- # Thus sets among others language and encodings.
- $self->_set_global_multiple_commands(-1);
- $self->_translate_names();
- if ($self->get_conf('USE_NODES')) {
- $elements = Texinfo::Structuring::split_by_node($root);
- } else {
- $elements = Texinfo::Structuring::split_by_section($root);
- }
- $self->{'elements'} = $elements
- if (defined($elements));
- # This may be done as soon as elements are available.
- $self->_prepare_global_targets($elements);
- # Do that before the other elements, to be sure that special page ids
- # are registered before elements id are.
- my $special_elements
- = $self->_prepare_special_elements($elements);
- $self->{'special_elements'} = $special_elements
- if (defined($special_elements));
- #if ($elements) {
- # foreach my $element(@{$elements}) {
- # print STDERR "ELEMENT $element->{'type'}: $element\n";
- # }
- #}
- $self->_set_root_commands_targets_node_files($elements);
- return ($elements, $special_elements);
- }
- sub _prepare_special_elements($$)
- {
- my $self = shift;
- my $elements = shift;
- my %do_special;
- # FIXME let the user decide how @*contents are treated?
- if ($self->{'structuring'} and $self->{'structuring'}->{'sectioning_root'}
- and scalar(@{$self->{'structuring'}->{'sections_list'}}) > 1) {
- foreach my $cmdname ('contents', 'shortcontents') {
- my $type = $contents_command_element_name{$cmdname};
- if ($self->get_conf($cmdname)) {
- if (not $self->get_conf('INLINE_CONTENTS')) {
- $do_special{$type} = 1;
- }
- }
- }
- }
- if ($self->{'extra'}->{'footnote'}
- and $self->get_conf('footnotestyle') eq 'separate'
- and $elements and scalar(@$elements) > 1) {
- $do_special{'Footnotes'} = 1;
- }
- if ((!defined($self->get_conf('DO_ABOUT'))
- and $elements and scalar(@$elements) > 1
- and ($self->get_conf('SPLIT') or $self->get_conf('HEADERS')))
- or ($self->get_conf('DO_ABOUT'))) {
- $do_special{'About'} = 1;
- }
- my $extension = '';
- $extension = $self->get_conf('EXTENSION')
- if (defined($self->get_conf('EXTENSION')));
- my $special_elements = [];
- foreach my $type (@{$self->{'misc_elements_order'}}) {
- next unless ($do_special{$type});
- my $element = {'type' => 'element',
- 'extra' => {'special_element' => $type,
- }};
- $element->{'extra'}->{'directions'}->{'This'} = $element;
- $self->{'special_elements_types'}->{$type} = $element;
- push @$special_elements, $element;
- my $target = $self->{'misc_elements_targets'}->{$type};
- my $default_filename;
- if ($self->get_conf('SPLIT') or !$self->get_conf('MONOLITHIC')) {
- $default_filename = $self->{'document_name'}.
- $self->{'misc_pages_file_string'}->{$type};
- $default_filename .= '.'.$extension if (defined($extension));
- } else {
- $default_filename = undef;
- }
- my $filename;
- if (defined($Texinfo::Config::special_element_target_file_name)) {
- ($target, $filename)
- = &$Texinfo::Config::special_element_target_file_name(
- $self,
- $element,
- $target,
- $default_filename);
- }
- $filename = $default_filename if (!defined($filename));
- if ($self->get_conf('DEBUG')) {
- my $fileout = $filename;
- $fileout = 'UNDEF' if (!defined($fileout));
- print STDERR "Add special $element $type: target $target,\n".
- " filename $fileout\n"
- }
- if ($self->get_conf('SPLIT') or !$self->get_conf('MONOLITHIC')
- or (defined($filename) ne defined($default_filename))
- or (defined($filename) and $filename ne $default_filename)) {
- $self->_set_element_file($element, $filename);
- print STDERR "NEW page for $type ($filename)\n" if ($self->get_conf('DEBUG'));
- }
- $self->{'targets'}->{$element} = {'target' => $target,
- 'misc_filename' => $filename,
- };
- $self->{'seen_ids'}->{$target} = 1;
- }
- if ($self->get_conf('FRAMES')) {
- foreach my $type (keys(%{$self->{'frame_pages_file_string'}})) {
- my $default_filename;
- $default_filename = $self->{'document_name'}.
- $self->{'frame_pages_file_string'}->{$type};
- $default_filename .= '.'.$extension if (defined($extension));
- my $element = {'type' => 'element',
- 'extra' => {'special_element' => $type,
- }};
- # only the filename is used
- my ($target, $filename);
- if (defined($Texinfo::Config::special_element_target_file_name)) {
- ($target, $filename)
- = &$Texinfo::Config::special_element_target_file_name(
- $self,
- $element,
- $target,
- $default_filename);
- }
- $filename = $default_filename if (!defined($filename));
- $self->{'frame_pages_filenames'}->{$type} = $filename;
- }
- }
- return $special_elements;
- }
- sub _prepare_contents_elements($)
- {
- my $self = shift;
- if ($self->{'structuring'} and $self->{'structuring'}->{'sectioning_root'}
- and scalar(@{$self->{'structuring'}->{'sections_list'}}) > 1) {
- foreach my $cmdname ('contents', 'shortcontents') {
- my $type = $contents_command_element_name{$cmdname};
- if ($self->get_conf($cmdname)) {
- my $default_filename;
- if ($self->get_conf('INLINE_CONTENTS')) {
- if ($self->{'extra'} and $self->{'extra'}->{$cmdname}) {
- foreach my $command(@{$self->{'extra'}->{$cmdname}}) {
- my ($element, $root_command)
- = $self->_get_element($command);
- if (defined($element)) {
- $default_filename = $element->{'filename'};
- last;
- }
- }
- } else {
- next;
- }
- } else { # in this case, there should already be a special element
- # if needed, done together with the other special elements.
- next;
- }
- my $element = {'type' => 'element',
- 'extra' => {'special_element' => $type}};
- $self->{'special_elements_types'}->{$type} = $element;
- my $target = $self->{'misc_elements_targets'}->{$type};
- my $filename;
- if (defined($Texinfo::Config::special_element_target_file_name)) {
- ($target, $filename)
- = &$Texinfo::Config::special_element_target_file_name(
- $self,
- $element,
- $target,
- $default_filename);
- }
- $filename = $default_filename if (!defined($filename));
- print STDERR "Add content $element $type: target $target,\n".
- " filename $filename\n" if ($self->get_conf('DEBUG'));
- $self->{'targets'}->{$element} = {'target' => $target,
- 'misc_filename' => $filename,
- 'filename' => $filename,
- };
- }
- }
- }
- }
- # Associate elements with the global targets, First, Last, Top, Index.
- sub _prepare_global_targets($$)
- {
- my $self = shift;
- my $elements = shift;
- $self->{'global_target_elements'}->{'First'} = $elements->[0];
- $self->{'global_target_elements'}->{'Last'} = $elements->[-1];
- # It is always the first printindex, even if it is not output (for example
- # it is in @copying and @titlepage, which are certainly wrong constructs).
- if ($self->{'extra'} and $self->{'extra'}->{'printindex'}) {
- my ($element, $root_command)
- = $self->_get_element($self->{'extra'}->{'printindex'}->[0]);
- if (defined($element)) {
- if ($root_command and $root_command->{'cmdname'} eq 'node'
- and $element->{'extra'}->{'section'}) {
- $root_command = $element->{'extra'}->{'section'};
- }
- if ($root_command and $root_command->{'cmdname'} ne 'node') {
- while ($root_command->{'level'} > 1
- and $root_command->{'section_up'}
- and $root_command->{'section_up'}->{'parent'}) {
- $root_command = $root_command->{'section_up'};
- $element = $root_command->{'parent'};
- }
- }
- $self->{'global_target_elements'}->{'Index'} = $element;
- }
- }
- my $node_top;
- $node_top = $self->{'labels'}->{'Top'} if ($self->{'labels'});
- my $section_top;
- $section_top = $self->{'extra'}->{'top'} if ($self->{'extra'});
- if ($section_top) {
- $self->{'global_target_elements'}->{'Top'} = $section_top->{'parent'};
- } elsif ($node_top) {
- my $element_top = $node_top->{'parent'};
- if (!$element_top) {
- die "No parent for node_top: ".Texinfo::Common::_print_current($node_top);
- }
- $self->{'global_target_elements'}->{'Top'} = $element_top;
- } else {
- $self->{'global_target_elements'}->{'Top'} = $elements->[0];
- }
-
- if ($self->get_conf('DEBUG')) {
- print STDERR "GLOBAL DIRECTIONS:\n";
- foreach my $global_direction ('First', 'Last', 'Index', 'Top') {
- if (defined($self->{'global_target_elements'}->{$global_direction})) {
- print STDERR "$global_direction($self->{'global_target_elements'}->{$global_direction}): ".
- Texinfo::Structuring::_print_element_command_texi(
- $self->{'global_target_elements'}->{$global_direction})."\n";
- }
- }
- }
- }
- sub _prepare_index_entries($)
- {
- my $self = shift;
- if ($self->{'parser'}) {
- my $no_unidecode;
- $no_unidecode = 1 if (defined($self->get_conf('USE_UNIDECODE'))
- and !$self->get_conf('USE_UNIDECODE'));
- my $index_names = $self->{'parser'}->indices_information();
- $self->{'index_names'} = $index_names;
- my $merged_index_entries
- = Texinfo::Structuring::merge_indices($index_names);
- $self->{'index_entries_by_letter'}
- = $self->Texinfo::Structuring::sort_indices_by_letter($merged_index_entries,
- $index_names);
- $self->{'index_entries'} = $merged_index_entries;
- foreach my $index_name (sort(keys(%$index_names))) {
- foreach my $index_entry (@{$index_names->{$index_name}->{'index_entries'}}) {
- my $region = '';
- $region = "$index_entry->{'region'}->{'cmdname'}-"
- if (defined($index_entry->{'region'}));
- my @contents = @{$index_entry->{'content_normalized'}};
- my $trimmed_contents
- = Texinfo::Common::trim_spaces_comment_from_content(\@contents);
- my $normalized_index =
- Texinfo::Convert::NodeNameNormalization::transliterate_texinfo(
- {'contents' => \@contents}, $no_unidecode);
- my $target_base = "index-" . $region .$normalized_index;
- my $nr=1;
- my $target = $target_base;
- while ($self->{'seen_ids'}->{$target}) {
- $target = $target_base.'-'.$nr;
- $nr++;
- # Avoid integer overflow
- die if ($nr == 0);
- }
- $self->{'seen_ids'}->{$target} = 1;
- $self->{'targets'}->{$index_entry->{'command'}} = {'target' => $target,
- };
- }
- }
- }
- }
- sub _prepare_footnotes($)
- {
- my $self = shift;
- if ($self->{'extra'}->{'footnote'}) {
- my $footnote_nr = 0;
- foreach my $footnote (@{$self->{'extra'}->{'footnote'}}) {
- $footnote_nr++;
- my $nr = $footnote_nr;
- my $footid = $footid_base.$nr;
- my $docid = $docid_base.$nr;
- while ($self->{'seen_ids'}->{$docid} or $self->{'seen_ids'}->{$footid}) {
- $nr++;
- $footid = $footid_base.$nr;
- $docid = $docid_base.$nr;
- # Avoid integer overflow
- die if ($nr == 0);
- }
- $self->{'seen_ids'}->{$footid} = 1;
- $self->{'seen_ids'}->{$docid} = 1;
- $self->{'targets'}->{$footnote} = { 'target' => $footid };
- print STDERR "Enter footnote $footnote: target $footid, nr $footnote_nr\n"
- .Texinfo::Convert::Texinfo::convert($footnote)."\n"
- if ($self->get_conf('DEBUG'));
- }
- }
- }
- # TODO this encapsulates some information.
- # The encapsulation and API should be more consistent for
- # the overall module.
- sub _htmlxref($$)
- {
- my $self = shift;
- my $file = shift;
- return $self->{'htmlxref'}->{$file};
- }
- sub _external_node_href($$$$)
- {
- my $self = shift;
- my $external_node = shift;
- my $filename = shift;
- my $link_command = shift;
-
- # This only overrides an implicit pointer to (dir) as the Top node's Up.
- # It has no effect if a pointer is explicitly specified,
- # or if implicit pointers aren't being created (e.g., just a Top node).
- if ($external_node->{'top_node_up'}
- and defined($self->get_conf('TOP_NODE_UP_URL'))) {
- return $self->get_conf('TOP_NODE_UP_URL');
- }
- # In addition to that implicit (dir) as the Top node's Up, replace all
- # other references to external file "dir" with the same TOP_NODE_UP_URL.
- if (defined($self->get_conf('TOP_NODE_UP_URL'))
- and $external_node->{'manual_content'}[0]->{'text'} eq "dir") {
- return $self->get_conf('TOP_NODE_UP_URL');
- }
-
- #print STDERR "external_node: ".join('|', keys(%$external_node))."\n";
- my ($target_filebase, $target) = $self->_node_id_file($external_node);
- my $xml_target = _normalized_to_id($target);
- my $default_target_split = $self->get_conf('EXTERNAL_CROSSREF_SPLIT');
- my $extension = '';
- $extension = "." . $self->get_conf('NODE_FILE_EXTENSION')
- if (defined($self->get_conf('NODE_FILE_EXTENSION'))
- and $self->get_conf('NODE_FILE_EXTENSION') ne '');
- my $target_split;
- my $file;
- if ($external_node->{'manual_content'}) {
- my $manual_name = Texinfo::Convert::Text::convert(
- {'contents' => $external_node->{'manual_content'}},
- { 'code' => 1,
- Texinfo::Common::_convert_text_options($self)});
- my $manual_base = $manual_name;
- $manual_base =~ s/\.[^\.]*$//;
- $manual_base =~ s/^.*\///;
- my $document_split = $self->get_conf('SPLIT');
- $document_split = 'mono' if (!$document_split);
- my $split_found;
- my $href;
- my $htmlxref_info = $self->_htmlxref($manual_base);
- if ($htmlxref_info) {
- foreach my $split_ordered (@{$htmlxref_entries{$document_split}}) {
- if (defined($htmlxref_info->{$split_ordered})) {
- $split_found = $split_ordered;
- $href = $htmlxref_info->{$split_ordered};
- last;
- }
- }
- }
- if (defined($split_found)) {
- $target_split = 1 unless ($split_found eq 'mono');
- } else { # nothing specified for that manual, use default
- $target_split = $default_target_split;
- if ($self->get_conf('CHECK_HTMLXREF')
- and !$external_node->{'top_node_up'}) {
- if (defined($link_command) and $link_command->{'line_nr'}) {
- $self->line_warn(sprintf($self->__(
- "no htmlxref.cnf entry found for `%s'"), $manual_name),
- $link_command->{'line_nr'});
- } elsif (!$self->{'check_htmlxref_already_warned'}->{$manual_name}) {
- $self->document_warn(sprintf($self->__(
- "no htmlxref.cnf entry found for `%s'"), $manual_name),
- );
- }
- $self->{'check_htmlxref_already_warned'}->{$manual_name} = 1;
- }
- }
- if ($target_split) {
- if (defined($href)) {
- $file = $href;
- } elsif (defined($self->get_conf('EXTERNAL_DIR'))) {
- $file = $self->get_conf('EXTERNAL_DIR')."/$manual_base";
- } elsif ($self->get_conf('SPLIT')) {
- $file = "../$manual_base";
- }
- $file .= "/";
- } else {# target not split
- if (defined($href)) {
- $file = $href;
- } else {
- if (defined($self->get_conf('EXTERNAL_DIR'))) {
- $file = $self->get_conf('EXTERNAL_DIR')."/$manual_base";
- } elsif ($self->get_conf('SPLIT')) {
- $file = "../$manual_base";
- } else {
- $file = $manual_base;
- }
- $file .= $extension;
- }
- }
- } else {
- $file = '';
- $target_split = $default_target_split;
- }
- if ($target eq '') {
- if ($target_split) {
- if (defined($self->get_conf('TOP_NODE_FILE_TARGET'))) {
- return $file . $self->get_conf('TOP_NODE_FILE_TARGET')
- . $extension;# . '#Top';
- } else {
- return $file;# . '#Top';
- }
- } else {
- return $file . '#Top';
- }
- }
- if (! $target_split) {
- return $file . '#' . $xml_target;
- } else {
- my $file_basename;
- if ($target eq 'Top' and defined($self->get_conf('TOP_NODE_FILE_TARGET'))) {
- $file_basename = $self->get_conf('TOP_NODE_FILE_TARGET');
- } else {
- $file_basename = $target_filebase;
- }
- return $file . $file_basename . $extension . '#' . $xml_target;
- }
- }
- my %valid_types = (
- 'href' => 1,
- 'string' => 1,
- 'text' => 1,
- 'tree' => 1,
- 'target' => 1,
- 'node' => 1,
- );
- foreach my $no_number_type ('text', 'tree', 'string') {
- $valid_types{$no_number_type .'_nonumber'} = 1;
- }
- sub _element_direction($$$$;$)
- {
- my $self = shift;
- my $element = shift;
- my $direction = shift;
- my $type = shift;
- my $filename = shift;
- my $element_target;
- my $command;
- my $target;
- $filename = $self->{'current_filename'} if (!defined($filename));
-
- if (!$valid_types{$type}) {
- print STDERR "Incorrect type $type in _element_direction call\n";
- return undef;
- }
- if ($self->{'global_target_elements'}->{$direction}) {
- $element_target = $self->{'global_target_elements'}->{$direction};
- } elsif ($element and $element->{'extra'}
- and $element->{'extra'}->{'directions'}
- and $element->{'extra'}->{'directions'}->{$direction}) {
- $element_target
- = $element->{'extra'}->{'directions'}->{$direction};
- }
- if ($element_target) {
- ######## debug
- if (!$element_target->{'type'}) {
- die "No type for element_target $direction $element_target: "
- . Texinfo::Common::_print_current_keys($element_target)
- . "directions :". Texinfo::Structuring::_print_directions($element);
- }
- ########
- if ($element_target->{'type'} eq 'external_node'
- or $element_target->{'type'} eq 'top_node_up') {
- my $external_node = $element_target->{'extra'};
- if ($type eq 'href') {
- return $self->command_href($external_node, $filename);
- } elsif ($type eq 'text' or $type eq 'node') {
- return $self->command_text($external_node);
- } elsif ($type eq 'string') {
- return $self->command_text($external_node, $type);
- }
- } elsif ($type eq 'node') {
- $command = $element_target->{'extra'}->{'node'};
- $target = $self->{'targets'}->{$command} if ($command);
- $type = 'text';
- } else {
- if ($element_target->{'extra'}->{'special_element'}) {
- $command = $element_target;
- } else {
- $command = $element_target->{'extra'}->{'element_command'};
- }
- if ($type eq 'href') {
- if (defined($command)) {
- return $self->command_href($command, $filename);
- } else {
- return '';
- }
- }
- $target = $self->{'targets'}->{$command} if ($command);
- }
- } elsif ($self->special_element($direction)) {
- $element_target = $self->special_element($direction);
- $command = $element_target;
- if ($type eq 'href') {
- return $self->command_href($element_target, $filename);
- }
- $target = $self->{'targets'}->{$element_target};
- } else {
- return undef;
- }
- if (exists($target->{$type})) {
- return $target->{$type};
- } elsif ($type eq 'target') {
- return undef;
- } elsif ($command) {
- return $self->command_text($command, $type);
- }
- }
- sub _default_contents($$;$$)
- {
- my $self = shift;
- my $cmdname = shift;
- my $command = shift;
- my $filename = shift;
- $filename = $self->{'current_filename'} if (!defined($filename));
- return ''
- if (!$self->{'structuring'} or !$self->{'structuring'}->{'sectioning_root'});
- my $section_root = $self->{'structuring'}->{'sectioning_root'};
- my $contents;
- $contents = 1 if ($cmdname eq 'contents');
- my $min_root_level = $section_root->{'section_childs'}->[0]->{'level'};
- my $max_root_level = $section_root->{'section_childs'}->[0]->{'level'};
- foreach my $top_section(@{$section_root->{'section_childs'}}) {
- $min_root_level = $top_section->{'level'}
- if ($top_section->{'level'} < $min_root_level);
- $max_root_level = $top_section->{'level'}
- if ($top_section->{'level'} > $max_root_level);
- }
- # chapter level elements are considered top-level here.
- $max_root_level = 1 if ($max_root_level < 1);
- #print STDERR "ROOT_LEVEL Max: $max_root_level, Min: $min_root_level\n";
- my $ul_class = '';
- $ul_class = $NO_BULLET_LIST_CLASS if ($self->get_conf('NUMBER_SECTIONS'));
- my $result = '';
- if ($contents and !defined($self->get_conf('BEFORE_TOC_LINES'))
- or (!$contents and !defined($self->get_conf('BEFORE_OVERVIEW')))) {
- $result .= $self->_attribute_class('div', $cmdname).">\n";
- } elsif($contents) {
- $result .= $self->get_conf('BEFORE_TOC_LINES');
- } else {
- $result .= $self->get_conf('BEFORE_OVERVIEW');
- }
- my $toplevel_contents;
- if (@{$section_root->{'section_childs'}} > 1) {
- # or $section_root->{'section_childs'}->[0]->{'cmdname'} ne 'top') {
- $result .= $self->_attribute_class('ul', $ul_class) .">\n";
- $toplevel_contents = 1;
- }
- foreach my $top_section (@{$section_root->{'section_childs'}}) {
- my $section = $top_section;
- SECTION:
- while ($section) {
- if ($section->{'cmdname'} ne 'top') {
- my $text = $self->command_text($section);
- my $href;
- if (!$contents and $self->get_conf('OVERVIEW_LINK_TO_TOC')) {
- $href = $self->command_contents_href($section, 'contents', $filename);
- } else {
- $href = $self->command_href($section, $filename);
- }
- my $toc_id = $self->command_contents_target($section, $cmdname);
- if ($text ne '') {
- # no indenting for shortcontents
- $result .= (' ' x (2*($section->{'level'} - $min_root_level)))
- if ($contents);
- if ($toc_id ne '' or $href ne '') {
- my $toc_name_attribute = '';
- if ($toc_id ne '') {
- $toc_name_attribute = "name=\"$toc_id\" ";
- }
- my $href_attribute = '';
- if ($href ne '') {
- $href_attribute = "href=\"$href\"";
- }
- $result .= "<li><a ${toc_name_attribute}${href_attribute}>$text</a>";
- } else {
- $result .= "<li>$text";
- }
- }
- } elsif ($section->{'section_childs'} and @{$section->{'section_childs'}}
- and $toplevel_contents) {
- $result .= "<li>";
- }
- # for shortcontents don't do child if child is not toplevel
- if ($section->{'section_childs'}
- and ($contents or $section->{'level'} < $max_root_level)) {
- # no indenting for shortcontents
- $result .= "\n". ' ' x (2*($section->{'level'} - $min_root_level))
- if ($contents);
- $result .= $self->_attribute_class('ul', $ul_class) .">\n";
- $section = $section->{'section_childs'}->[0];
- } elsif ($section->{'section_next'} and $section->{'cmdname'} ne 'top') {
- $result .= "</li>\n";
- last if ($section eq $top_section);
- $section = $section->{'section_next'};
- } else {
- #last if ($section eq $top_section);
- if ($section eq $top_section) {
- $result .= "</li>\n" unless ($section->{'cmdname'} eq 'top');
- last;
- }
- while ($section->{'section_up'}) {
- $section = $section->{'section_up'};
- $result .= "</li>\n". ' ' x (2*($section->{'level'} - $min_root_level))
- . "</ul>";
- if ($section eq $top_section) {
- $result .= "</li>\n" if ($toplevel_contents);
- last SECTION;
- }
- if ($section->{'section_next'}) {
- $result .= "</li>\n";
- $section = $section->{'section_next'};
- last;
- }
- }
- }
- }
- }
- if (@{$section_root->{'section_childs'}} > 1) {
- # or $section_root->{'section_childs'}->[0]->{'cmdname'} ne 'top') {
- $result .= "\n</ul>";
- }
- if ($contents and !defined($self->get_conf('AFTER_TOC_LINES'))
- or (!$contents and !defined($self->get_conf('AFTER_OVERVIEW')))) {
- $result .= "\n</div>\n";
- } elsif($contents) {
- $result .= $self->get_conf('AFTER_TOC_LINES');
- } else {
- $result .= $self->get_conf('AFTER_OVERVIEW');
- }
- return $result;
- }
- sub _default_program_string($)
- {
- my $self = shift;
- if (defined($self->get_conf('PROGRAM'))
- and $self->get_conf('PROGRAM') ne ''
- and defined($self->get_conf('PACKAGE_URL'))) {
- return $self->convert_tree(
- $self->gdt('This document was generated on @emph{@today{}} using @uref{{program_homepage}, @emph{{program}}}.',
- { 'program_homepage' => $self->get_conf('PACKAGE_URL'),
- 'program' => $self->get_conf('PROGRAM') }));
- } else {
- return $self->convert_tree(
- $self->gdt('This document was generated on @emph{@today{}}.'));
- }
- }
- sub _default_end_file($)
- {
- my $self = shift;
- my $program_text = '';
- if ($self->get_conf('PROGRAM_NAME_IN_FOOTER')) {
- my $program_string = &{$self->{'format_program_string'}}($self);
- $program_text = "<p><font size=\"-1\">
- $program_string
- </font></p>";
- }
- my $pre_body_close = $self->get_conf('PRE_BODY_CLOSE');
- $pre_body_close = '' if (!defined($pre_body_close));
- return "$program_text
- $pre_body_close
- </body>
- </html>
- ";
- }
- # This is used for normal output files and other files, like renamed
- # nodes file headers, or redirection file headers.
- sub _file_header_informations($$)
- {
- my $self = shift;
- my $command = shift;
-
- my $title;
- if ($command) {
- my $command_string =
- $self->command_text($command, 'string');
- if (defined($command_string)
- and $command_string ne $self->{'title_string'}) {
- print STDERR "DO <title>\n"
- if ($self->get_conf('DEBUG'));
- my $title_tree = $self->gdt('{element_text} ({title})',
- { 'title' => $self->{'title_tree'},
- 'element_text' => $self->command_text($command, 'tree')});
- $title = $self->convert_tree_new_formatting_context(
- {'type' => '_string', 'contents' => [$title_tree]},
- $command->{'cmdname'}, 'element_title');
- }
- }
- $title = $self->{'title_string'} if (!defined($title));
- my $description;
- if ($self->{'documentdescription_string'}) {
- $description = $self->{'documentdescription_string'};
- } else {
- $description = $title;
- }
- $description = "<meta name=\"description\" content=\"$description\">"
- if ($description ne '');
- my $encoding = '';
- $encoding
- = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=".
- $self->get_conf('OUTPUT_ENCODING_NAME')."\">"
- if (defined($self->get_conf('OUTPUT_ENCODING_NAME'))
- and ($self->get_conf('OUTPUT_ENCODING_NAME') ne ''));
- my $date = '';
- if ($self->get_conf('DATE_IN_HEADER')) {
- my $today = $self->convert_tree_new_formatting_context(
- {'cmdname' => 'today'}, 'DATE_IN_HEADER');
- $date = "\n<meta name=\"date\" content=\"$today\">";
- }
- my $css_lines;
- if (defined($self->get_conf('CSS_LINES'))) {
- $css_lines = $self->get_conf('CSS_LINES');
- } else {
- $css_lines = '';
- }
- my $doctype = $self->get_conf('DOCTYPE');
- my $bodytext = $self->get_conf('BODYTEXT');
- my $copying_comment = '';
- $copying_comment = $self->{'copying_comment'}
- if (defined($self->{'copying_comment'}));
- my $after_body_open = '';
- $after_body_open = $self->get_conf('AFTER_BODY_OPEN')
- if (defined($self->get_conf('AFTER_BODY_OPEN')));
- my $extra_head = '';
- $extra_head = $self->get_conf('EXTRA_HEAD')
- if (defined($self->get_conf('EXTRA_HEAD')));
- my $program_and_version = $self->get_conf('PACKAGE_AND_VERSION');
- my $program_homepage = $self->get_conf('PACKAGE_URL');
- my $program = $self->get_conf('PROGRAM');
- my $generator = '';
- if (defined($program) and $program ne '') {
- $generator = "\n<meta name=\"Generator\" content=\"$program\">";
- }
- return ($title, $description, $encoding, $date, $css_lines,
- $doctype, $bodytext, $copying_comment, $after_body_open,
- $extra_head, $program_and_version, $program_homepage,
- $program, $generator);
- }
- sub _get_links ($$$)
- {
- my $self = shift;
- my $filename = shift;
- my $element = shift;
- my $links = '';
- if ($self->get_conf('USE_LINKS')) {
- my $link_buttons = $self->get_conf('LINKS_BUTTONS');
- foreach my $link (@$link_buttons) {
- my $link_href = $self->_element_direction($element,
- $link, 'href', $filename);
- #print STDERR "$title: $link -> $link_href \n";
- if ($link_href and $link_href ne '') {
- my $link_string = $self->_element_direction($element,
- $link, 'string');
- my $link_title = '';
- $link_title = " title=\"$link_string\"" if (defined($link_string));
- my $rel = '';
- $rel = " rel=\"".$self->get_conf('BUTTONS_REL')->{$link}.'"'
- if (defined($self->get_conf('BUTTONS_REL')->{$link}));
- $links .= "<link href=\"$link_href\"${rel}${link_title}>\n";
- }
- }
- }
- return $links;
- }
- sub _default_begin_file($$$)
- {
- my $self = shift;
- my $filename = shift;
- my $element = shift;
-
- my $command;
- if ($element and $self->get_conf('SPLIT')) {
- $command = $self->element_command($element);
- }
- my ($title, $description, $encoding, $date, $css_lines,
- $doctype, $bodytext, $copying_comment, $after_body_open,
- $extra_head, $program_and_version, $program_homepage,
- $program, $generator) = $self->_file_header_informations($command);
- my $links = $self->_get_links ($filename, $element);
- my $result = "$doctype
- <html>
- $copying_comment<!-- Created by $program_and_version, $program_homepage -->
- <head>
- <title>$title</title>
- $description
- <meta name=\"keywords\" content=\"$title\">
- <meta name=\"resource-type\" content=\"document\">
- <meta name=\"distribution\" content=\"global\">${generator}$date
- $encoding
- ${links}$css_lines
- $extra_head
- </head>
- <body $bodytext>
- $after_body_open";
- return $result;
- }
- sub _default_node_redirection_page($$)
- {
- my $self = shift;
- my $command = shift;
- my ($title, $description, $encoding, $date, $css_lines,
- $doctype, $bodytext, $copying_comment, $after_body_open,
- $extra_head, $program_and_version, $program_homepage,
- $program, $generator) = $self->_file_header_informations($command);
- my $name = $self->command_text($command);
- my $href = $self->command_href($command);
- my $direction = "<a href=\"$href\">$name</a>";
- my $string = $self->convert_tree (
- $self->gdt('The node you are looking for is at {href}.',
- { 'href' => {'type' => '_converted', 'text' => $direction }}));
- my $result = "$doctype
- <html>
- $copying_comment<!-- Created by $program_and_version, $program_homepage -->
- <!-- This file redirects to the location of a node or anchor -->
- <head>
- <title>$title</title>
- $description
- <meta name=\"keywords\" content=\"$title\">
- <meta name=\"resource-type\" content=\"document\">
- <meta name=\"distribution\" content=\"global\">${generator}$date
- $encoding
- $css_lines
- <meta http-equiv=\"Refresh\" content=\"0; url=$href\">
- $extra_head
- </head>
- <body $bodytext>
- $after_body_open
- <p>$string</p>
- </body>
- ";
- return $result;
- }
- sub _default_footnotes_text($)
- {
- my $self = shift;
- return '' if (!$foot_lines);
- my $result = $self->_attribute_class('div', 'footnote').">\n";
- $result .= $self->get_conf('DEFAULT_RULE') . "\n"
- if (defined($self->get_conf('DEFAULT_RULE'))
- and $self->get_conf('DEFAULT_RULE') ne '');
- my $footnote_heading
- = $self->convert_tree ($self->get_conf('SPECIAL_ELEMENTS_NAME')->{'Footnotes'});
- my $class = $self->get_conf('SPECIAL_ELEMENTS_CLASS')->{'Footnotes'};
- my $level = $self->get_conf('FOOTNOTE_END_HEADER_LEVEL');
- $result .= &{$self->{'format_heading_text'}}($self, $class.'-heading',
- $footnote_heading, $level)."\n";
- $result .= &{$self->{'format_special_element_body'}}($self, 'Footnotes',
- $self->{'current_element'});
- $result .= "</div>\n";
- return $result;
- }
- sub _default_special_element_body($$$)
- {
- my $self = shift;
- my $special_type = shift;
- my $element = shift;
- if ($special_type eq 'About') {
- my $about = "<p>\n";
- my $PRE_ABOUT = $self->get_conf('PRE_ABOUT');
- if (defined($PRE_ABOUT)) {
- if (ref($PRE_ABOUT) eq 'CODE') {
- $about .= &$PRE_ABOUT($self, $element);
- } else {
- $about .= $PRE_ABOUT;
- }
- } else {
- $about .= ' '.&{$self->{'format_program_string'}}($self) ."\n";
- }
- $about .= <<EOT;
- </p>
- <p>
- EOT
- $about .= $self->convert_tree($self->gdt(' The buttons in the navigation panels have the following meaning:')) . "\n";
- $about .= <<EOT;
- </p>
- <table border="1">
- <tr>
- EOT
- $about .= ' <th> ' . $self->convert_tree($self->gdt('Button')) . " </th>\n" .
- ' <th> ' . $self->convert_tree($self->gdt('Name')) . " </th>\n" .
- ' <th> ' . $self->convert_tree($self->gdt('Go to')) . " </th>\n" .
- ' <th> ' . $self->convert_tree($self->gdt('From 1.2.3 go to')) . "</th>\n" . " </tr>\n";
- foreach my $button (@{$self->get_conf('SECTION_BUTTONS')}) {
- next if ($button eq ' ' or ref($button) eq 'CODE' or ref($button) eq 'SCALAR'
- or ref($button) eq 'ARRAY');
- my $button_name = $self->get_conf('BUTTONS_NAME')->{$button};
- $about .= " <tr>\n <td align=\"center\">";
- $about .=
- ($self->get_conf('ICONS') && $self->get_conf('ACTIVE_ICONS')->{$button} ?
- &{$self->{'format_button_icon_img'}}($self, $button_name,
- $self->get_conf('ACTIVE_ICONS')->{$button}) :
- ' [' . $self->get_conf('BUTTONS_TEXT')->{$button} . '] ');
- $about .= "</td>\n";
- $about .=
- " <td align=\"center\">".$button_name."</td>
- <td>".$self->get_conf('BUTTONS_GOTO')->{$button}."</td>
- <td>".$self->get_conf('BUTTONS_EXAMPLE')->{$button}."</td>
- </tr>
- ";
- }
- $about .= <<EOT;
- </table>
- <p>
- EOT
- $about .= $self->convert_tree($self->gdt(' where the @strong{ Example } assumes that the current position is at @strong{ Subsubsection One-Two-Three } of a document of the following structure:')) . "\n";
- # where the <strong> Example </strong> assumes that the current position
- # is at <strong> Subsubsection One-Two-Three </strong> of a document of
- # the following structure:
- $about .= <<EOT;
- </p>
- <ul>
- EOT
- $about .= ' <li> 1. ' . $self->convert_tree($self->gdt('Section One')) . "\n" .
- " <ul>\n" .
- ' <li>1.1 ' . $self->convert_tree($self->gdt('Subsection One-One')) . "\n";
- $about .= <<EOT;
- <ul>
- <li>...</li>
- </ul>
- </li>
- EOT
- $about .= ' <li>1.2 ' . $self->convert_tree($self->gdt('Subsection One-Two')) . "\n" .
- " <ul>\n" .
- ' <li>1.2.1 ' . $self->convert_tree($self->gdt('Subsubsection One-Two-One')) . "</li>\n" .
- ' <li>1.2.2 ' . $self->convert_tree($self->gdt('Subsubsection One-Two-Two')) . "</li>\n" .
- ' <li>1.2.3 ' . $self->convert_tree($self->gdt('Subsubsection One-Two-Three')) . " \n"
- .
- ' <strong><== ' . $self->convert_tree($self->gdt('Current Position')) . " </strong></li>\n" .
- ' <li>1.2.4 ' . $self->convert_tree($self->gdt('Subsubsection One-Two-Four')) . "</li>\n" .
- " </ul>\n" .
- " </li>\n" .
- ' <li>1.3 ' . $self->convert_tree($self->gdt('Subsection One-Three')) . "\n";
- $about .= <<EOT;
- <ul>
- <li>...</li>
- </ul>
- </li>
- EOT
- $about .= ' <li>1.4 ' . $self->convert_tree($self->gdt('Subsection One-Four')) . "</li>\n";
- my $AFTER_ABOUT = '';
- if (defined($self->get_conf('AFTER_ABOUT'))) {
- $AFTER_ABOUT = $self->get_conf('AFTER_ABOUT');
- }
- $about .= <<EOT;
- </ul>
- </li>
- </ul>
- $AFTER_ABOUT
- EOT
- return $about;
- } elsif ($special_type eq 'Contents') {
- return &{$self->{'format_contents'}}($self, 'contents', undef);
- } elsif ($special_type eq 'Overview') {
- return &{$self->{'format_contents'}}($self, 'shortcontents', undef);
- } elsif ($special_type eq 'Footnotes') {
- my $result = $foot_lines;
- $foot_lines = '';
- return $result;
- }
- }
- sub _default_frame_files($)
- {
- my $self = shift;
- my $frame_file = $self->{'frame_pages_filenames'}->{'Frame'};
- my $frame_outfile;
- if (defined($self->{'destination_directory'})
- and $self->{'destination_directory'} ne '') {
- $frame_outfile = File::Spec->catfile($self->{'destination_directory'},
- $frame_file);
- } else {
- $frame_outfile = $frame_file;
- }
-
- my $toc_frame_file = $self->{'frame_pages_filenames'}->{'Toc_Frame'};
- my $toc_frame_outfile;
- if (defined($self->{'destination_directory'})
- and $self->{'destination_directory'} ne '') {
- $toc_frame_outfile = File::Spec->catfile($self->{'destination_directory'},
- $toc_frame_file);
- } else {
- $toc_frame_outfile = $toc_frame_file;
- }
-
- my $frame_fh = $self->Texinfo::Common::open_out($frame_outfile);
- if (defined($frame_fh)) {
- my $doctype = $self->get_conf('FRAMESET_DOCTYPE');
- my $top_file = '';
- if ($self->global_element('Top')) {
- my $top_element = $self->global_element('Top');
- $top_file = $top_element->{'filename'};
- }
- my $title = $self->{'title_string'};
- print $frame_fh <<EOT;
- $doctype
- <html>
- <head><title>$title</title></head>
- <frameset cols="140,*">
- <frame name="toc" src="$toc_frame_file">
- <frame name="main" src="$top_file">
- </frameset>
- </html>
- EOT
- $self->register_close_file($frame_outfile);
- if (!close ($frame_fh)) {
- $self->document_error(sprintf($self->__("error on closing frame file %s: %s"),
- $frame_outfile, $!));
- return 0;
- }
- } else {
- $self->document_error(sprintf($self->__("could not open %s for writing: %s"),
- $frame_outfile, $!));
- return 0;
- }
- my $toc_frame_fh = $self->Texinfo::Common::open_out($toc_frame_outfile);
- if (defined($toc_frame_fh)) {
- my $header = &{$self->{'format_begin_file'}}($self, $toc_frame_file, undef);
- print $toc_frame_fh $header;
- print $toc_frame_fh '<h2>Content</h2>'."\n";
- my $shortcontents =
- &{$self->{'format_contents'}}($self, 'shortcontents', undef);
- $shortcontents =~ s/\bhref=/target="main" href=/g;
- print $toc_frame_fh $shortcontents;
- print $toc_frame_fh "</body></html>\n";
- $self->register_close_file($toc_frame_outfile);
- if (!close ($toc_frame_fh)) {
- $self->document_error(sprintf($self->__("error on closing TOC frame file %s: %s"),
- $toc_frame_outfile, $!));
- return 0;
- }
- } else {
- $self->document_error(sprintf($self->__("could not open %s for writing: %s"),
- $toc_frame_outfile, $!));
- return 0;
- }
- return 1;
- }
- sub convert($$)
- {
- my $self = shift;
- my $root = shift;
- my $result = '';
- # This should return undef if called on a tree without node or sections.
- my ($elements, $special_elements)
- = $self->_prepare_elements($root);
- $self->_prepare_index_entries();
- $self->_prepare_footnotes();
- if (!defined($elements)) {
- $result = $self->_convert($root);
- } else {
- foreach my $element (@$elements) {
- my $element_text = $self->_convert($element);
- $result .= $element_text;
- }
- }
- return $result;
- }
- # This is called from the main program on the converter.
- sub output_internal_links($)
- {
- my $self = shift;
- my $out_string = '';
- if ($self->{'elements'}) {
- foreach my $element (@{$self->{'elements'}}) {
- my $text;
- my $href;
- my $command = $self->element_command($element);
- if (defined($command)) {
- # Use '' for filename, to force a filename in href.
- $href = $self->command_href($command, '');
- my $tree = $self->command_text($command, 'tree');
- if ($tree) {
- $text = Texinfo::Convert::Text::convert($tree,
- {Texinfo::Common::_convert_text_options($self)});
- }
- }
- if (defined($href) or defined($text)) {
- $out_string .= $href if (defined($href));
- $out_string .= "\ttoc\t";
- $out_string .= $text if (defined($text));
- $out_string .= "\n";
- }
- }
- }
- if ($self->{'parser'}) {
- foreach my $index_name (sort(keys (%{$self->{'index_entries_by_letter'}}))) {
- foreach my $letter_entry (@{$self->{'index_entries_by_letter'}->{$index_name}}) {
- foreach my $index_entry (@{$letter_entry->{'entries'}}) {
- my $href;
- my $key;
- $href = $self->command_href($index_entry->{'command'}, '');
- $key = $index_entry->{'key'};
- if (defined($key) and $key =~ /\S/) {
- $out_string .= $href if (defined($href));
- $out_string .= "\t$index_name\t";
- $out_string .= $key;
- $out_string .= "\n";
- }
- }
- }
- }
- }
- if ($out_string ne '') {
- return $out_string;
- } else {
- return undef;
- }
- }
- my @possible_stages = ('setup', 'structure', 'init', 'finish');
- my %possible_stages;
- foreach my $stage (@possible_stages) {
- $possible_stages{$stage} = 1;
- }
- sub run_stage_handlers($$)
- {
- my $converter = shift;
- my $stage = shift;
- die if (!$possible_stages{$stage});
- return 1 if (!defined($Texinfo::Config::texinfo_default_stage_handlers{$stage}));
- my @sorted_priorities = sort keys(%{$Texinfo::Config::texinfo_default_stage_handlers{$stage}});
- foreach my $priority (@sorted_priorities) {
- foreach my $handler (@{$Texinfo::Config::texinfo_default_stage_handlers{$stage}->{$priority}}) {
- if ($converter->get_conf('DEBUG')) {
- print STDERR "HANDLER($stage) , priority $priority: $handler\n";
- }
- my $status = &{$handler}($converter, $stage);
- if (!$status) {
- #if ($converter->get_conf('VERBOSE')) {
- # print STDERR "Handler $handler of $stage($priority) failed\n";
- #}
- $converter->document_error(sprintf($converter->__(
- "handler %s of stage %s priority %s failed"),
- $handler, $stage, $priority));
- return $status;
- }
- }
- }
- return 1;
- }
- my $default_priority = 'default';
- {
- package Texinfo::Config;
- use vars qw(%texinfo_default_stage_handlers %texinfo_formatting_references
- %texinfo_commands_conversion %texinfo_types_conversion);
- sub texinfo_register_handler($$;$)
- {
- my $stage = shift;
- my $handler = shift;
- my $priority = shift;
- if (!$possible_stages{$stage}) {
- carp ("Unknown stage $stage\n");
- return 0;
- }
- $priority = $default_priority if (!defined($priority));
- push @{$texinfo_default_stage_handlers{$stage}->{$priority}}, $handler;
- return 1;
- }
- sub texinfo_register_formatting_function($$)
- {
- my $thing = shift;
- my $handler = shift;
- if (!$default_formatting_references{$thing}) {
- carp ("Unknown formatting type $thing\n");
- return 0;
- }
- $texinfo_formatting_references{$thing} = $handler;
- }
- sub texinfo_register_command_formatting($$)
- {
- my $command = shift;
- my $reference = shift;
- $texinfo_commands_conversion{$command} = $reference;
- }
- sub texinfo_register_type_formatting($$)
- {
- my $command = shift;
- my $reference = shift;
- $texinfo_types_conversion{$command} = $reference;
- }
- }
- # Main function for outputting a manual in HTML.
- # $SELF is the output converter object of class Texinfo::Convert::HTML (this
- # module), and $ROOT is the Texinfo tree from the parser.
- sub output($$)
- {
- my $self = shift;
- my $root = shift;
- # no splitting when writing to the null device or to stdout or returning
- # a string
- if (defined($self->get_conf('OUTFILE'))
- and ($Texinfo::Common::null_device_file{$self->get_conf('OUTFILE')}
- or $self->get_conf('OUTFILE') eq '-'
- or $self->get_conf('OUTFILE') eq '')) {
- $self->force_conf('SPLIT', 0);
- $self->force_conf('MONOLITHIC', 1);
- $self->force_conf('FRAMES', 0);
- }
- if ($self->get_conf('SPLIT')) {
- $self->set_conf('NODE_FILES', 1);
- }
- if ($self->get_conf('NODE_FILES') or $self->get_conf('SPLIT') eq 'node') {
- $self->set_conf('NODE_FILENAMES', 1);
- }
- if ($self->get_conf('FRAMES')) {
- $self->set_conf('shortcontents', 1);
- }
- $self->set_conf('EXTERNAL_CROSSREF_SPLIT', $self->get_conf('SPLIT'));
- my $setup_status = $self->run_stage_handlers('setup');
- return undef unless($setup_status);
- $self->_prepare_css();
- # this sets OUTFILE, to be used if not split, but also
- # 'destination_directory' and 'output_filename' that are useful when split.
- $self->_set_outfile();
- return undef unless $self->_create_destination_directory();
- # collect renamed nodes
- ($self->{'renamed_nodes'}, $self->{'renamed_nodes_lines'},
- $self->{'renamed_nodes_file'})
- = Texinfo::Common::collect_renamed_nodes($self, $self->{'input_basename_name'},
- $self->{'renamed_nodes'});
- # Get the list of "elements" to be processed, i.e. nodes or sections.
- # This should return undef if called on a tree without node or sections.
- my ($elements, $special_elements) = $self->_prepare_elements($root);
- Texinfo::Structuring::split_pages($elements, $self->get_conf('SPLIT'));
- # determine file names associated with the different pages, and setup
- # the counters for special element pages.
- if ($self->{'output_file'} ne '') {
- $self->_set_pages_files($elements, $special_elements);
- }
- $self->_prepare_contents_elements();
- # do element directions.
- Texinfo::Structuring::elements_directions($self, $elements);
- # do element directions related to files.
- # FIXME do it here or before? Here it means that
- # PrevFile and NextFile can be set.
- Texinfo::Structuring::elements_file_directions($self, $elements);
- # Associate the special elements that have no page with the main page.
- # This may only happen if not split.
- if ($special_elements
- and $elements and $elements->[0]
- and defined($elements->[0]->{'filename'})) {
- foreach my $special_element (@$special_elements) {
- if (!defined($special_element->{'filename'})) {
- $special_element->{'filename'} = $elements->[0]->{'filename'};
- $special_element->{'out_filename'} = $elements->[0]->{'out_filename'};
- $self->{'file_counters'}->{$special_element->{'filename'}}++;
- print STDERR "Special page $special_element: $special_element->{'filename'}($self->{'file_counters'}->{$special_element->{'filename'}})\n"
- if ($self->get_conf('DEBUG'));
- }
- }
- }
- $self->_prepare_index_entries();
- $self->_prepare_footnotes();
- my $structure_status = $self->run_stage_handlers('structure');
- return undef unless($structure_status);
- &{$self->{'format_css_lines'}}($self);
- $self->set_conf('BODYTEXT',
- 'lang="' . $self->get_conf('documentlanguage') . '"');
- # prepare title. fulltitle uses more possibility than simpletitle for
- # title, including @-commands found in @titlepage only. Therefore
- # simpletitle is more in line with what makeinfo in C does.
- my $fulltitle;
- foreach my $fulltitle_command('settitle', 'title',
- 'shorttitlepage', 'top') {
- if ($self->{'extra'}->{$fulltitle_command}) {
- my $command = $self->{'extra'}->{$fulltitle_command};
- next if (!$command->{'extra'}
- or (!$command->{'extra'}->{'misc_content'}
- or $command->{'extra'}->{'missing_argument'}));
- print STDERR "Using $fulltitle_command as title\n"
- if ($self->get_conf('DEBUG'));
- $fulltitle = {'contents' => $command->{'extra'}->{'misc_content'}};
- last;
- }
- }
- if (!$fulltitle and $self->{'extra'}->{'titlefont'}
- and $self->{'extra'}->{'titlefont'}->[0]->{'extra'}
- and $self->{'extra'}->{'titlefont'}->[0]->{'extra'}->{'brace_command_contents'}
- and defined($self->{'extra'}->{'titlefont'}->[0]->{'extra'}->{'brace_command_contents'}->[0])) {
- $fulltitle = $self->{'extra'}->{'titlefont'}->[0];
- }
- # prepare simpletitle
- foreach my $simpletitle_command('settitle', 'shorttitlepage') {
- if ($self->{'extra'}->{$simpletitle_command}) {
- my $command = $self->{'extra'}->{$simpletitle_command};
- next if ($command->{'extra'}
- and $command->{'extra'}->{'missing_argument'});
- $self->{'simpletitle_tree'} =
- {'contents' => $command->{'extra'}->{'misc_content'}};
- last;
- }
- }
- my $html_title_string;
- if ($fulltitle) {
- $self->{'title_tree'} = $fulltitle;
- print STDERR "DO fulltitle_string\n" if ($self->get_conf('DEBUG'));
- $html_title_string = $self->convert_tree_new_formatting_context(
- {'type' => '_string', 'contents' => [$self->{'title_tree'}]},
- 'title_string');
- }
- if (!defined($html_title_string) or $html_title_string !~ /\S/) {
- my $default_title = $self->gdt('Untitled Document');
- $self->{'title_tree'} = $default_title;
- $self->{'title_string'} = $self->convert_tree_new_formatting_context(
- {'type' => '_string', 'contents' => [$self->{'title_tree'}]},
- 'title_string');
- $self->file_line_warn($self->__(
- "must specify a title with a title command or \@top"),
- $self->{'info'}->{'input_file_name'});
- } else {
- $self->{'title_string'} = $html_title_string;
- }
- # copying comment
- if ($self->{'extra'}->{'copying'}) {
- print STDERR "DO copying_comment\n" if ($self->get_conf('DEBUG'));
- my $copying_comment = Texinfo::Convert::Text::convert(
- {'contents' => $self->{'extra'}->{'copying'}->{'contents'}},
- {Texinfo::Common::_convert_text_options($self)});
- if ($copying_comment ne '') {
- $self->{'copying_comment'} = &{$self->{'format_comment'}}($self, $copying_comment);
- }
- }
- # documentdescription
- if (defined($self->get_conf('documentdescription'))) {
- $self->{'documentdescription_string'}
- = $self->get_conf('documentdescription');
- } elsif ($self->{'extra'}->{'documentdescription'}) {
- print STDERR "DO documentdescription\n" if ($self->get_conf('DEBUG'));
- $self->{'documentdescription_string'}
- = $self->convert_tree_new_formatting_context(
- {'type' => '_string',
- 'contents' => $self->{'extra'}->{'documentdescription'}->{'contents'}},
- 'documentdescription');
- chomp($self->{'documentdescription_string'});
- }
- my $init_status = $self->run_stage_handlers('init');
- return undef unless($init_status);
- if ($self->get_conf('FRAMES')) {
- my $status = &{$self->{'format_frame_files'}}($self);
- return undef if (!$status);
- }
- # FIXME here call _unset_global_multiple_commands? Problem is
- # that some conversion, for instance for page header requires
- # that the correct language is set, for instance. The @-command
- # will necessarily appear later on -- even if it appears a the
- # beginning of the file.
- my $fh;
- my $output = '';
- if (!$elements or !defined($elements->[0]->{'filename'})) {
- # no page
- my $outfile;
- if ($self->{'output_file'} ne '') {
- if ($self->get_conf('SPLIT')) {
- $outfile = $self->_top_node_filename();
- if (defined($self->{'destination_directory'})
- and $self->{'destination_directory'} ne '') {
- $outfile = File::Spec->catfile($self->{'destination_directory'},
- $outfile);
- }
- } else {
- $outfile = $self->{'output_file'};
- }
- print STDERR "DO No pages, output in $outfile\n"
- if ($self->get_conf('DEBUG'));
- $fh = $self->Texinfo::Common::open_out($outfile);
- if (!$fh) {
- $self->document_error(sprintf($self->__("could not open %s for writing: %s"),
- $outfile, $!));
- return undef;
- }
- } else {
- print STDERR "DO No pages, string output\n"
- if ($self->get_conf('DEBUG'));
- }
- $self->{'current_filename'} = $self->{'output_filename'};
- my $header = &{$self->{'format_begin_file'}}($self,
- $self->{'output_filename'}, undef);
- $output .= $self->_output_text($header, $fh);
- if ($elements and @$elements) {
- foreach my $element (@$elements) {
- my $element_text = $self->_convert($element);
- $output .= $self->_output_text($element_text, $fh);
- }
- } else {
- $output .= $self->_output_text($self->_print_title(), $fh);
- $output .= $self->_output_text($self->_convert($root), $fh);
- }
- $output .= $self->_output_text(&{$self->{'format_end_file'}}($self), $fh);
- # NOTE do not close STDOUT now to avoid a perl warning.
- if ($fh and $outfile ne '-') {
- $self->register_close_file($outfile);
- if (!close($fh)) {
- $self->document_error(sprintf($self->__("error on closing %s: %s"),
- $outfile, $!));
- }
- }
- return $output if ($self->{'output_file'} eq '');
- } else {
- # output with pages
- print STDERR "DO Elements with filenames\n"
- if ($self->get_conf('DEBUG'));
- my %files;
-
- # Now do the output, converting each member in @$elements in turn.
- $special_elements = [] if (!defined($special_elements));
- foreach my $element (@$elements, @$special_elements) {
- my $file_fh;
- $self->{'current_filename'} = $element->{'filename'};
- $self->{'counter_in_file'}->{$element->{'filename'}}++;
- #print STDERR "TTTTTTT($element) $element->{'filename'}: $self->{'file_counters'}->{$element->{'filename'}} (out_filename $element->{'out_filename'})\n";
- # First do the special pages, to avoid outputting these if they are
- # empty.
- my $special_element_content;
- if ($element->{'extra'} and $element->{'extra'}->{'special_element'}) {
- $special_element_content .= $self->_convert($element);
- #print STDERR "Special element converter: $element->{'extra'}->{'special_element'}\n";
- if ($special_element_content eq '') {
- $self->{'file_counters'}->{$element->{'filename'}}--;
- next ;
- }
- }
- # Then open the file and output the elements or the special_page_content
- if (!$files{$element->{'filename'}}->{'fh'}) {
- $file_fh = $self->Texinfo::Common::open_out($element->{'out_filename'});
- if (!$file_fh) {
- $self->document_error(sprintf($self->__("could not open %s for writing: %s"),
- $element->{'out_filename'}, $!));
- return undef;
- }
- print $file_fh "".&{$self->{'format_begin_file'}}($self,
- $element->{'filename'},
- $element);
- $files{$element->{'filename'}}->{'fh'} = $file_fh;
- } else {
- $file_fh = $files{$element->{'filename'}}->{'fh'};
- }
- if (defined($special_element_content)) {
- print $file_fh $special_element_content;
- } else {
- my $element_text = $self->_convert($element);
- print $file_fh $element_text;
- }
- $self->{'file_counters'}->{$element->{'filename'}}--;
- if ($self->{'file_counters'}->{$element->{'filename'}} == 0) {
- # end file
- print $file_fh "". &{$self->{'format_end_file'}}($self);
- # NOTE do not close STDOUT here to avoid a perl warning
- if ($element->{'out_filename'} ne '-') {
- $self->register_close_file($element->{'out_filename'});
- if (!close($file_fh)) {
- $self->document_error(sprintf($self->__("error on closing %s: %s"),
- $element->{'out_filename'}, $!));
- return undef;
- }
- }
- }
- }
- }
- my $finish_status = $self->run_stage_handlers('finish');
- return undef unless($finish_status);
- # do node redirection pages
- $self->{'current_filename'} = undef;
- if ($self->get_conf('NODE_FILES')
- and $self->{'labels'} and $self->{'output_file'} ne '') {
- foreach my $label (sort(keys (%{$self->{'labels'}}))) {
- my $node = $self->{'labels'}->{$label};
- my $target = $self->_get_target($node);
- # filename may not be defined in case of an @anchor or similar in
- # @titlepage, and @titlepage is not used.
- my $filename = $self->command_filename($node);
- my $node_filename;
- # NOTE 'node_filename' is not used for Top, so the other manual
- # must use the same convention to get it right. We avoid doing
- # also 'node_filename' to avoid unneeded redirection files.
- if ($node->{'extra'} and $node->{'extra'}->{'normalized'}
- and $node->{'extra'}->{'normalized'} eq 'Top'
- and defined($self->get_conf('TOP_NODE_FILE_TARGET'))) {
- my $extension = '';
- $extension = "." . $self->get_conf('NODE_FILE_EXTENSION')
- if (defined($self->get_conf('NODE_FILE_EXTENSION'))
- and $self->get_conf('NODE_FILE_EXTENSION') ne '');
- $node_filename = $self->get_conf('TOP_NODE_FILE_TARGET')
- .$extension;
- } else {
- $node_filename = $target->{'node_filename'};
- }
- if (defined($filename) and $node_filename ne $filename) {
- my $redirection_page
- = &{$self->{'format_node_redirection_page'}}($self, $node);
- my $out_filename;
- if (defined($self->{'destination_directory'})
- and $self->{'destination_directory'} ne '') {
- $out_filename = File::Spec->catfile($self->{'destination_directory'},
- $node_filename);
- } else {
- $out_filename = $node_filename;
- }
- my $file_fh = $self->Texinfo::Common::open_out($out_filename);
- if (!$file_fh) {
- $self->document_error(sprintf($self->__(
- "could not open %s for writing: %s"),
- $out_filename, $!));
- } else {
- print $file_fh $redirection_page;
- $self->register_close_file($out_filename);
- if (!close ($file_fh)) {
- $self->document_error(sprintf($self->__(
- "error on closing redirection node file %s: %s"),
- $out_filename, $!));
- return undef;
- }
- }
- }
- }
- }
- if ($self->{'renamed_nodes'}
- and $self->{'labels'} and $self->{'output_file'} ne '') {
- # do a fresh parser, to avoid, for example adding new labels if renamed
- # nodes incorrectly define anchors...
- my $parser_for_renamed_nodes;
- if ($self->{'parser'}) {
- $parser_for_renamed_nodes = $self->{'parser'}->parser();
- }
- my %warned_new_node;
- foreach my $old_node_name (sort(keys(%{$self->{'renamed_nodes'}}))) {
- my $parsed_old_node = $self->_parse_node_and_warn_external(
- $old_node_name, $parser_for_renamed_nodes,
- $self->{'renamed_nodes_lines'}->{$old_node_name},
- $self->{'renamed_nodes_file'});
- if ($parsed_old_node) {
- if ($self->label_command($parsed_old_node->{'normalized'})) {
- $self->file_line_error(sprintf($self->__(
- "old name for `%s' is a node of the document"), $old_node_name),
- $self->{'renamed_nodes_file'},
- $self->{'renamed_nodes_lines'}->{$old_node_name});
- $parsed_old_node = undef;
- } elsif ($parsed_old_node->{'normalized'} !~ /[^-]/) {
- $self->file_line_error(sprintf($self->__(
- "file empty for renamed node `%s'"), $old_node_name),
- $self->{'renamed_nodes_file'},
- $self->{'renamed_nodes_lines'}->{$old_node_name});
- $parsed_old_node = undef;
- }
- }
- my $new_node_name = $self->{'renamed_nodes'}->{$old_node_name};
- my $parsed_new_node = $self->_parse_node_and_warn_external(
- $new_node_name, $parser_for_renamed_nodes,
- $self->{'renamed_nodes_lines'}->{$new_node_name},
- $self->{'renamed_nodes_file'});
- if (!$self->label_command($parsed_new_node->{'normalized'})) {
- if (!$warned_new_node{$new_node_name}) {
- $self->file_line_warn(sprintf($self->__(
- "target node (new name for `%s') not in document: %s"),
- $old_node_name, $new_node_name), $self->{'renamed_nodes_file'},
- $self->{'renamed_nodes_lines'}->{$new_node_name});
- $warned_new_node{$new_node_name} = 1;
- }
- $parsed_new_node = undef;
- }
- if ($parsed_new_node and $parsed_old_node) {
- my ($filename, $target) = $self->_node_id_file($parsed_old_node);
- $filename .= '.'.$self->get_conf('NODE_FILE_EXTENSION')
- if (defined($self->get_conf('NODE_FILE_EXTENSION'))
- and $self->get_conf('NODE_FILE_EXTENSION') ne '');
- my $redirection_page
- = &{$self->{'format_node_redirection_page'}}($self,
- $self->label_command($parsed_new_node->{'normalized'}));
- my $out_filename;
- if (defined($self->{'destination_directory'})
- and $self->{'destination_directory'} ne '') {
- $out_filename = File::Spec->catfile($self->{'destination_directory'},
- $filename);
- } else {
- $out_filename = $filename;
- }
- my $file_fh = $self->Texinfo::Common::open_out($out_filename);
- if (!$file_fh) {
- $self->document_error(sprintf($self->__("could not open %s for writing: %s"),
- $out_filename, $!));
- } else {
- print $file_fh $redirection_page;
- $self->register_close_file($out_filename);
- if (!close ($file_fh)) {
- $self->document_error(sprintf($self->__(
- "error on closing renamed node redirection file %s: %s"),
- $out_filename, $!));
- return undef;
- }
- }
- }
- }
- }
- }
- sub _parse_node_and_warn_external($$$$$)
- {
- my $self = shift;
- my $node_texi = shift;
- my $parser = shift;
- my $line_number = shift;
- my $file = shift;
- # NOTE nothing to check that there is an invalid nesting. Indeed, there
- # is no information given to the parser stating that we are in a label
- # command.
- # A possibility would be to consider
- # 'root_line' type as a $simple_text_command, or, to avoid spurious
- # messages, $full_text_command. This would imply really using
- # the gdt 4th argument to pass 'translated_paragraph' when in a
- # less constrained environment, for instance @center in @quotation for
- # @author
- #
- # it is unlikely, however that invalid nesting does much harm, since
- # the tree is mostly used to be normalized and this converter should
- # be rather foolproof.
- my $node_tree = Texinfo::Parser::parse_texi_line($parser,
- $node_texi, $line_number, $file);
- if ($node_tree) {
- my $node_normalized_result = Texinfo::Parser::_parse_node_manual(
- $node_tree);
- my $line_nr = {'line_nr' => $line_number, 'file_name' => $file };
- if (!$node_normalized_result) {
- $self->line_warn($self->__('empty node name'), $line_nr);
- } elsif ($node_normalized_result->{'manual_content'}) {
- $self->line_error(sprintf($self->__("syntax for an external node used for `%s'"),
- $node_texi), $line_nr);
- } else {
- if ($node_normalized_result->{'node_content'}) {
- $node_normalized_result->{'normalized'} =
- Texinfo::Convert::NodeNameNormalization::normalize_node(
- {'contents' => $node_normalized_result->{'node_content'}});
- }
- return $node_normalized_result;
- }
- }
- return undef;
- }
- # Convert the 'contents' of a tree element.
- sub _convert_contents($$$)
- {
- my $self = shift;
- my $root = shift;
- my $command_type = shift;
- my $content_formatted = '';
- if (ref($root->{'contents'}) ne 'ARRAY') {
- cluck "for $root contents not an array: $root->{'contents'}";
- print STDERR Texinfo::Common::_print_current($root);
- }
- my $content_idx = 0;
- foreach my $content (@{$root->{'contents'}}) {
- my $new_content = $self->_convert($content, "$command_type [$content_idx]");
- if (!defined($new_content)) {
- cluck "content not defined for $command_type [$content_idx]\n";
- print STDERR "root is: ".Texinfo::Common::_print_current ($root);
- print STDERR "content is: ".Texinfo::Common::_print_current ($content);
- } else {
- $content_formatted .= $new_content;
- }
- $content_idx++;
- }
- return $content_formatted;
- }
- sub _attribute_class($$$)
- {
- my $self = shift;
- my $element = shift;
- my $class = shift;
- if (!defined($class) or $class eq '' or $self->get_conf('NO_CSS')) {
- if ($element eq 'span') {
- return '';
- } else {
- return "<$element";
- }
- }
- my $style = '';
- if ($self->get_conf('INLINE_CSS_STYLE')
- and defined($self->{'css_map'}->{"$element.$class"})) {
- $style = ' style="'.$self->{'css_map'}->{"$element.$class"}.'"';
- }
- return "<$element class=\"$class\"$style";
- }
- sub _protect_space($$)
- {
- my $self = shift;
- my $text = shift;
- return $text if ($self->in_preformatted());
- if ($self->in_space_protected()) {
- my $open = $self->_attribute_class('span', 'nolinebreak');
- if ($open ne '') {
- $open .= '>';
- # Protect spaces in the html leading attribute in case we are in 'w'
- $open =~ s/ /\x{1F}/g;
- # Special span to avoid breaking at _-
- $text =~ s/(\S*[_-]\S*)/${open}$1<\/span>/g;
- }
- $text .= ' ' if (chomp($text));
- # Protect spaces within text
- $text =~ s/ / /g;
- # Revert protected spaces in leading html attribute
- $text =~ s/\x{1F}/ /g;
- }
- return $text;
- }
- # Convert tree element $ROOT, and return HTML text for the output files.
- sub _convert($$;$);
- sub _convert($$;$)
- {
- my $self = shift;
- my $root = shift;
- # only used for debug
- my $explanation = shift;
- # to help debug and trace
- my $command_type = '';
- if ($root->{'cmdname'}) {
- $command_type = "\@$root->{'cmdname'} ";
- }
- if (defined($root->{'type'})) {
- $command_type .= $root->{'type'};
- }
- if ($self->get_conf('DEBUG')) {
- $explanation = 'NO EXPLANATION' if (!defined($explanation));
- print STDERR "ROOT($explanation):$root (".join('|',@{$self->{'document_context'}->[-1]->{'formatting_context'}})."), ->";
- print STDERR " cmd: $root->{'cmdname'}," if ($root->{'cmdname'});
- print STDERR " type: $root->{'type'}" if ($root->{'type'});
- my $text = $root->{'text'};
- if (defined($text)) {
- $text =~ s/\n/\\n/;
- print STDERR " text: $text";
- }
- print STDERR "\n";
- }
- if (ref($root) ne 'HASH') {
- cluck "_convert: root not a HASH\n";
- return '';
- }
- if (($root->{'type'}
- and exists ($self->{'types_conversion'}->{$root->{'type'}})
- and !defined($self->{'types_conversion'}->{$root->{'type'}}))
- or ($root->{'cmdname'}
- and exists($self->{'commands_conversion'}->{$root->{'cmdname'}})
- and !defined($self->{'commands_conversion'}->{$root->{'cmdname'}}))) {
- if ($self->get_conf('DEBUG')) {
- my $string = 'IGNORED';
- $string .= " \@$root->{'cmdname'}" if ($root->{'cmdname'});
- $string .= " $root->{'type'}" if ($root->{'type'});
- print STDERR "$string\n";
- }
- return '';
- }
- # Process text
- if (defined($root->{'text'})) {
- # already converted to html, keep it as is
- if ($root->{'type'} and $root->{'type'} eq '_converted') {
- return $root->{'text'};
- }
- if ($root->{'type'} and $root->{'type'} eq 'untranslated') {
- my $translated = $self->gdt($root->{'text'});
- my $result = $self->_convert($translated);
- return $result;
- }
- my $result = &{$self->{'types_conversion'}->{'text'}} ($self,
- $root->{'type'},
- $root,
- $root->{'text'});
- print STDERR "DO TEXT => `$result'\n" if ($self->get_conf('DEBUG'));
- return $result;
- }
- if ($root->{'extra'}) {
- #if ($root->{'extra'}->{'invalid_nesting'}) {
- # print STDERR "INVALID_NESTING\n" if ($self->get_conf('DEBUG'));
- # return '';
- #} elsif ($root->{'extra'}->{'missing_argument'}
- if ($root->{'extra'}->{'missing_argument'}
- and (!$root->{'contents'} or !@{$root->{'contents'}})) {
- print STDERR "MISSING_ARGUMENT\n" if ($self->get_conf('DEBUG'));
- return '';
- }
- }
- # commands like @deffnx have both a cmdname and a def_line type. It is
- # better to consider them as a def_line type, as the whole point of the
- # def_line type is to handle the same the def*x and def* line formatting.
- if ($root->{'cmdname'}
- and !($root->{'type'} and $root->{'type'} eq 'def_line'
- or $root->{'type'} and $root->{'type'} eq 'definfoenclose_command')) {
- my $command_name = $root->{'cmdname'};
- # use the same command name for all the index entry commands
- if ($root->{'extra'} and $root->{'extra'}->{'index_entry'}
- and $root->{'cmdname'} and $root->{'cmdname'} =~ /index$/) {
- $command_name = 'cindex';
- }
- if ($root_commands{$command_name}) {
- $self->{'current_root_command'} = $root;
- }
- if (exists($self->{'commands_conversion'}->{$command_name})) {
- if (exists($context_brace_commands{$command_name})) {
- $self->_new_document_context($command_name);
- }
- push @{$self->{'document_context'}->[-1]->{'commands'}},
- $root->{'cmdname'};
- if (exists($format_context_commands{$command_name})) {
- push @{$self->{'document_context'}->[-1]->{'formatting_context'}},
- {'cmdname' => $command_name};
- }
- if (exists($block_commands{$command_name})) {
- push @{$self->{'document_context'}->[-1]->{'formats'}}, $command_name;
- }
- if (exists ($composition_context_commands{$command_name})) {
- push @{$self->{'document_context'}->[-1]->{'composition_context'}}, $command_name;
- }
- if ($pre_class_commands{$command_name}) {
- push @{$self->{'document_context'}->[-1]->{'preformatted_classes'}},
- $pre_class_commands{$command_name};
- }
- if ($format_raw_commands{$command_name}) {
- $self->{'document_context'}->[-1]->{'raw'}++;
- } elsif ($command_name eq 'verb' or $command_name eq 'verbatim') {
- $self->{'document_context'}->[-1]->{'verbatim'}++;
- }
- if ($code_style_commands{$command_name} or
- $preformatted_code_commands{$command_name}) {
- push @{$self->{'document_context'}->[-1]->{'monospace'}}, 1;
- } elsif ($regular_font_style_commands{$command_name}) {
- push @{$self->{'document_context'}->[-1]->{'monospace'}}, 0;
- } elsif ($upper_case_commands{$command_name}) {
- $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'upper_case'}++;
- } elsif ($command_name eq 'math') {
- $self->{'document_context'}->[-1]->{'math'}++;
- } elsif ($command_name eq 'w') {
- $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'space_protected'}++;
- }
- my $content_formatted;
- if ($root->{'contents'}) {
- $content_formatted = $self->_convert_contents($root, $command_type);
- }
- my $args_formatted;
- if ($brace_commands{$command_name}
- or ($misc_commands{$command_name}
- and $misc_commands{$command_name} eq 'line')
- or (($command_name eq 'item' or $command_name eq 'itemx')
- and ($root->{'parent'}->{'type'}
- and $root->{'parent'}->{'type'} eq 'table_term'))
- or ($command_name eq 'quotation'
- or $command_name eq 'smallquotation')
- or ($command_name eq 'float')) {
- $args_formatted = [];
- if ($root->{'args'}) {
- my @args_specification;
- @args_specification = @{$self->{'commands_args'}->{$command_name}}
- if (defined($self->{'commands_args'}->{$command_name}));
- my $arg_idx = 0;
- foreach my $arg (@{$root->{'args'}}) {
- my $arg_spec = shift @args_specification;
- $arg_spec = ['normal'] if (!defined($arg_spec));
- my $arg_formatted = {'tree' => $arg};
- foreach my $arg_type (@$arg_spec) {
- my $explanation = "$command_type \[$arg_idx\]$arg_type";
- if ($arg_type eq 'normal') {
- $arg_formatted->{'normal'} = $self->_convert($arg, $explanation);
- } elsif ($arg_type eq 'monospace') {
- push @{$self->{'document_context'}->[-1]->{'monospace'}}, 1;
- #$self->{'document_context'}->[-1]->{'code'}++;
- $arg_formatted->{$arg_type} = $self->_convert($arg, $explanation);
- #$self->{'document_context'}->[-1]->{'code'}--;
- pop @{$self->{'document_context'}->[-1]->{'monospace'}};
- } elsif ($arg_type eq 'string') {
- $self->_new_document_context($command_type);
- $self->{'document_context'}->[-1]->{'string'}++;
- $arg_formatted->{$arg_type} = $self->_convert($arg, $explanation);
- pop @{$self->{'document_context'}};
- } elsif ($arg_type eq 'monospacestring') {
- $self->_new_document_context($command_type);
- $self->{'document_context'}->[-1]->{'monospace'}->[-1] = 1;
- $self->{'document_context'}->[-1]->{'string'}++;
- $arg_formatted->{$arg_type} = $self->_convert($arg, $explanation);
- pop @{$self->{'document_context'}};
- } elsif ($arg_type eq 'monospacetext') {
- $arg_formatted->{$arg_type}
- = Texinfo::Convert::Text::convert($arg, {'code' => 1,
- Texinfo::Common::_convert_text_options($self)});
- } elsif ($arg_type eq 'raw') {
- $self->{'document_context'}->[-1]->{'raw'}++;
- $arg_formatted->{$arg_type} = $self->_convert($arg, $explanation);
- $self->{'document_context'}->[-1]->{'raw'}--;
- }
- }
-
- push @$args_formatted, $arg_formatted;
- $arg_idx++;
- }
- }
- }
- if (exists ($composition_context_commands{$command_name})) {
- pop @{$self->{'document_context'}->[-1]->{'composition_context'}};
- }
- if ($pre_class_commands{$command_name}) {
- pop @{$self->{'document_context'}->[-1]->{'preformatted_classes'}};
- }
- if ($code_style_commands{$command_name}
- or $preformatted_code_commands{$command_name}
- or $regular_font_style_commands{$command_name}) {
- #$self->{'document_context'}->[-1]->{'code'}--;
- pop @{$self->{'document_context'}->[-1]->{'monospace'}};
- } elsif ($upper_case_commands{$command_name}) {
- $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'upper_case'}--;
- } elsif ($command_name eq 'math') {
- $self->{'document_context'}->[-1]->{'math'}--;
- } elsif ($command_name eq 'w') {
- $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'space_protected'}--;
- }
- if ($format_raw_commands{$command_name}) {
- $self->{'document_context'}->[-1]->{'raw'}--;
- } elsif ($command_name eq 'verb' or $command_name eq 'verbatim') {
- $self->{'document_context'}->[-1]->{'verbatim'}--;
- }
- if (exists($block_commands{$command_name})) {
- pop @{$self->{'document_context'}->[-1]->{'formats'}};
- }
- if (exists($format_context_commands{$command_name})) {
- pop @{$self->{'document_context'}->[-1]->{'formatting_context'}};
- }
- pop @{$self->{'document_context'}->[-1]->{'commands'}};
- if (exists($context_brace_commands{$command_name})) {
- pop @{$self->{'document_context'}};
- }
- if ($root->{'cmdname'} eq 'node') {
- $self->{'current_node'} = $root;
- }
- # args are formatted, now format the command itself
- my $result;
- if ($args_formatted) {
- if (!defined($self->{'commands_conversion'}->{$command_name})) {
- print STDERR "No command_conversion for $command_name\n";
- $result = '';
- } else {
- $result = &{$self->{'commands_conversion'}->{$command_name}}($self,
- $command_name, $root, $args_formatted, $content_formatted);
- }
- } else {
- $result = &{$self->{'commands_conversion'}->{$command_name}}($self,
- $command_name, $root, $content_formatted);
- }
- return $result;
- } else {
- print STDERR "Unknown command `$command_name'\n"
- if ($self->get_conf('VERBOSE') or $self->get_conf('DEBUG'));
- return '';
- }
- if ($root_commands{$command_name}) {
- delete $self->{'current_root_command'};
- }
- } elsif ($root->{'type'}) {
- push @{$self->{'document_context'}->[-1]->{'commands'}},
- $root->{'cmdname'}
- if ($root->{'cmdname'});
- if ($root->{'type'} eq 'paragraph') {
- $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'paragraph_number'}++;
- } elsif ($root->{'type'} eq 'preformatted'
- or $root->{'type'} eq 'rawpreformatted') {
- $self->{'document_context'}->[-1]->{'formatting_context'}->[-1]->{'preformatted_number'}++;
- } elsif ($root->{'type'} eq 'element') {
- $self->{'current_element'} = $root;
- $self->{'current_filename'} = $root->{'filename'};
- } elsif ($pre_class_types{$root->{'type'}}) {
- push @{$self->{'document_context'}->[-1]->{'preformatted_classes'}},
- $pre_class_types{$root->{'type'}};
- push @{$self->{'document_context'}->[-1]->{'composition_context'}},
- $root->{'type'};
- }
- if ($self->{'code_types'}->{$root->{'type'}}) {
- #$self->{'document_context'}->[-1]->{'code'}++;
- push @{$self->{'document_context'}->[-1]->{'monospace'}}, 1;
- }
- if ($root->{'type'} eq '_string') {
- $self->{'document_context'}->[-1]->{'string'}++;
- }
- my $content_formatted;
- if ($root->{'type'} eq 'definfoenclose_command') {
- if ($root->{'args'}) {
- $content_formatted = $self->_convert($root->{'args'}->[0]);
- }
- } elsif ($root->{'contents'}) {
- $content_formatted = $self->_convert_contents($root, $command_type);
- }
- my $result = '';
- if (exists($self->{'types_conversion'}->{$root->{'type'}})) {
- $result = &{$self->{'types_conversion'}->{$root->{'type'}}} ($self,
- $root->{'type'},
- $root,
- $content_formatted);
- #print STDERR "Converting type $root->{'type'} -> $result\n";
- } elsif (defined($content_formatted)) {
- $result = $content_formatted;
- }
- if ($self->{'code_types'}->{$root->{'type'}}) {
- #$self->{'document_context'}->[-1]->{'code'}--;
- pop @{$self->{'document_context'}->[-1]->{'monospace'}};
- }
- if ($root->{'type'} eq '_string') {
- $self->{'document_context'}->[-1]->{'string'}--;
- }
- if ($root->{'type'} eq 'element') {
- delete $self->{'current_element'};
- delete $self->{'current_filename'};
- } elsif ($pre_class_types{$root->{'type'}}) {
- pop @{$self->{'document_context'}->[-1]->{'preformatted_classes'}};
- pop @{$self->{'document_context'}->[-1]->{'composition_context'}};
- }
- print STDERR "DO type ($root->{'type'}) => `$result'\n"
- if ($self->get_conf('DEBUG'));
- pop @{$self->{'document_context'}->[-1]->{'commands'}}
- if ($root->{'cmdname'});
- return $result;
- # no type, no cmdname, but contents.
- } elsif ($root->{'contents'}) {
- # this happens inside accents, for section/node names, for @images.
- my $content_formatted = '';
- my $i = 0;
- foreach my $content (@{$root->{'contents'}}) {
- $content_formatted .= $self->_convert($content, "$command_type [$i]");
- $i++;
- }
- print STDERR "UNNAMED HOLDER => `$content_formatted'\n"
- if ($self->get_conf('DEBUG'));
- return $content_formatted;
- } else {
- print STDERR "UNNAMED empty\n" if ($self->get_conf('DEBUG'));
- if ($self->{'types_conversion'}->{''}) {
- return &{$self->{'types_conversion'}->{''}} ($self, $root);
- } else {
- return '';
- }
- }
- print STDERR "DEBUG: HERE!($root)\n";
- }
- sub _set_variables_texi2html()
- {
- my @texi2html_options = (
- ['NO_USE_SETFILENAME', 1],
- ['USE_SETFILENAME_EXTENSION', 0],
- ['footnotestyle', 'separate'],
- ['INLINE_CONTENTS', 0],
- ['FORCE', 1],
- ['AVOID_MENU_REDUNDANCY', 1],
- ['TOP_FILE', ''],
- ['USE_ACCESSKEY', 0],
- ['NODE_NAME_IN_MENU', 0],
- ['OVERVIEW_LINK_TO_TOC', 0],
- ['USE_UP_NODE_FOR_ELEMENT_UP', 1],
- ['USE_REL_REV', 0],
- ['USE_LINKS', 0],
- ['USE_NODES', 0],
- ['NODE_FILENAMES', 0],
- ['USE_NUMERIC_ENTITY', 1],
- ['SPLIT', ''],
- ['SPLIT_INDEX', 100],
- ['PROGRAM_NAME_IN_FOOTER', 1],
- ['HEADER_IN_TABLE', 1],
- ['USE_TITLEPAGE_FOR_TITLE', 1],
- ['MENU_ENTRY_COLON', ''],
- ['INDEX_ENTRY_COLON', ''],
- ['ENABLE_ENCODING_USE_ENTITY', 1],
- ['DO_ABOUT', undef],
- ['NODE_NAME_IN_INDEX', 0],
- ['CHAPTER_HEADER_LEVEL', 1],
- ['BIG_RULE', '<hr size="6">'],
- ['FOOTNOTE_END_HEADER_LEVEL', 3],
- ['FOOTNOTE_SEPARATE_HEADER_LEVEL', 1],
- ['KEEP_TOP_EXTERNAL_REF', 1],
- ['SECTION_BUTTONS', ['FastBack', 'Back', 'Up', 'Forward', 'FastForward',
- ' ', ' ', ' ', ' ',
- 'Top', 'Contents', 'Index', 'About' ]],
- ['TOP_BUTTONS', ['Back', 'Forward', ' ',
- 'Contents', 'Index', 'About']],
- ['MISC_BUTTONS', [ 'Top', 'Contents', 'Index', 'About' ]],
- ['CHAPTER_BUTTONS', [ 'FastBack', 'FastForward', ' ',
- ' ', ' ', ' ', ' ',
- 'Top', 'Contents', 'Index', 'About', ]],
- ['SECTION_FOOTER_BUTTONS', [ 'FastBack', 'Back', 'Up',
- 'Forward', 'FastForward' ]],
- ['NODE_FOOTER_BUTTONS', [ 'FastBack', 'Back',
- 'Up', 'Forward', 'FastForward',
- ' ', ' ', ' ', ' ',
- 'Top', 'Contents', 'Index', 'About' ]],
- );
- foreach my $option (@texi2html_options) {
- #no warnings 'once';
- $defaults{$option->[0]} = $option->[1];
- }
- }
- 1;
- __END__
- # $Id$
- # Automatically generated from maintain/template.pod
- =head1 NAME
- Texinfo::Convert::HTML - Convert Texinfo tree to HTML
- =head1 SYNOPSIS
- my $converter
- = Texinfo::Convert::HTML->converter({'parser' => $parser});
- $converter->output($tree);
- $converter->convert($tree);
- $converter->convert_tree($tree);
- $converter->output_internal_links(); # HTML only
- =head1 DESCRIPTION
- Texinfo::Convert::HTML converts a Texinfo tree to HTML.
- =head1 METHODS
- =over
- =item $converter = Texinfo::Convert::HTML->converter($options)
- Initialize converter from Texinfo to HTML.
- The I<$options> hash reference holds options for the converter. In
- this option hash reference a parser object may be associated with the
- I<parser> key. The other options should be configuration options
- described in the Texinfo manual. Those options, when appropriate,
- override the document content.
- See L<Texinfo::Convert::Converter> for more informations.
- =item $converter->output($tree)
- Convert a Texinfo tree I<$tree> and output the result in files as
- described in the Texinfo manual.
- =item $result = $converter->convert($tree)
- Convert a Texinfo tree I<$tree> or tree portion and return
- the resulting output.
- =item $result = $converter->convert_tree($tree)
- Convert a Texinfo tree portion I<$tree> and return the resulting
- output. This function does not try to output a full document but only
- portions. For a full document use C<convert>.
- =item $result = $converter->output_internal_links()
- Returns text representing the links in the document. The format should
- follow the C<--internal-links> option of the texi2any/makeinfo
- specification. This is only supported in (and relevant for) HTML.
- =back
- =head1 AUTHOR
- Patrice Dumas, E<lt>pertusus@free.frE<gt>
- =head1 COPYRIGHT AND LICENSE
- Copyright 2015 Free Software Foundation, Inc.
- This library is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or (at
- your option) any later version.
- =cut
|