with ARM_Output, ARM_Contents, Ada.Text_IO, Ada.Exceptions, Ada.Strings.Maps, Ada.Strings.Fixed, Ada.Unchecked_Deallocation; package body ARM_HTML is -- -- Ada reference manual formatter. -- -- This package defines the HTML output object. -- Output objects are responsible for implementing the details of -- a particular format. -- -- --------------------------------------- -- Copyright 2000, 2001, 2002, 2003, 2004, 2005 AXE Consultants. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- AXE Consultants grants to all users the right to use/modify this -- formatting tool for non-commercial purposes. (ISO/IEC JTC 1 SC 22 WG 9 -- activities are explicitly included as "non-commercial purposes".) -- Commercial uses of this software and its source code, including but not -- limited to documents for sale and sales of modified versions of this -- tool, are prohibited without the prior written permission of -- AXE Consultants. All rights not explicitly granted above are reserved -- by AXE Consultants. -- -- You use this tool and/or its source code on the condition that you indemnify and hold harmless -- AXE Consultants, its agents, and employees, from any and all liability -- or damages to yourself or your hardware or software, or third parties, -- including attorneys' fees, court costs, and other related costs and -- expenses, arising out of your use of this tool and/or source code irrespective of the -- cause of said liability. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- --------------------------------------- -- -- Edit History: -- -- 4/19/00 - RLB - Created base package. -- 4/21/00 - RLB - Added line break and hard space routines. -- 4/24/00 - RLB - Added DR references and Insert/Delete text formats. -- 4/25/00 - RLB - Added size to format. -- 4/26/00 - RLB - Added paragraph formats. -- 4/29/00 - RLB - Added more paragraph formats. -- 5/10/00 - RLB - Added even more formats. -- - RLB - Added End_Hang_Item. -- 5/12/00 - RLB - Added No_Prefix to Start_Paragraph. -- 5/13/00 - RLB - Added Special_Character. -- 5/16/00 - RLB - Added additional special characters. -- 5/17/00 - RLB - Added New_Page. -- 5/22/00 - RLB - Added Includes_Changes to Create. -- 5/23/00 - RLB - Added multi-column formats and New_Column. -- - Added Tab_Info and Tab_Stops. -- 5/24/00 - RLB - Added Location to Text_Format. -- - RLB - Added No_Breaks and Keep_with_Next to Start_Paragraph. -- 5/25/00 - RLB - Added Big_Files to Create. Added Justification. -- - RLB - Added Separator_Lines and TOC routines. -- - RLB - Added "Legal" to the footer, pointing at the title page. -- 5/26/00 - RLB - Added table operations. -- 5/28/00 - RLB - Added index references. -- 6/ 2/00 - RLB - Added Soft_Line_Break. -- 8/ 2/00 - RLB - Added Soft_Hyphen_Break and left and right quote -- characters. -- - RLB - Added additional styles. -- 8/ 7/00 - RLB - Added Leading flag to Start_Paragraph, removed "Leading" -- styles. -- 8/11/00 - RLB - Added Hanging_in_Bulleted styles. -- 8/16/00 - RLB - Added Code_Indented_Nested_Bulleted. -- 8/17/00 - RLB - Replaced "Leading" by "Space_After". -- - RLB - Added Nested_Enumerated. -- 8/22/00 - RLB - Added Revised_Clause_Header. -- 9/ 8/00 - RLB - Removed soft hyphen, as this does not work on either -- browser I tried. -- 9/26/00 - RLB - Added Syntax_Summary style. -- 9/27/00 - RLB - Added tab emulation when in the fixed font. -- 9/28/00 - RLB - Added some style sheets. -- - RLB - Updated to use absolute positioning for paragraph -- numbers (this looks much better than floating). -- 7/18/01 - RLB - Added "Indented" style to supported styles for -- multi-column. -- - RLB - Implemented single "Big-File" support. -- 7/18/02 - RLB - Removed Document parameter from Create, replaced by -- three strings and For_ISO boolean. -- - RLB - Added AI_Reference. -- - RLB - Added Change_Version_Type and uses. -- 1/15/03 - RLB - Removed space from DIV.paranum, as it doesn't validate -- with it. -- 4/10/03 - RLB - Updated to add access to search pages (not generated -- here; make them by hand, it only needs to be done once). -- - RLB - Updated to insure that changes are separated by a space. -- 4/11/03 - RLB - Changed some formats to meet WC3 validation requirements. -- 9/09/04 - RLB - Removed unused junk noted by Stephen Leake. -- 9/10/04 - RLB - Added "Both" to possible changes to handle -- replacement of changed text. -- 9/14/04 - RLB - Moved Change_Version_Type to ARM_Contents. -- - RLB - Changed to use left/right quotes whether or not Unicode -- is being used. (These work on IE, but not on old -- Netscape.) -- 9/16/04 - RLB - Added a charset meta in the header, so that browsers -- can't misinterpret these documents. -- 11/03/04 - RLB - Added Nested_X2_Bulleted. -- 11/15/04 - RLB - Added Indented_Nested_Bulleted. -- 12/15/04 - RLB - Added wider columns. -- 1/24/05 - RLB - Added Inner_Indented. -- 2/ 1/05 - RLB - Added Turkish chars to allow an AARM note. -- 3/15/05 - RLB - Turned on Unicode characters at Pascal's insistence. -- 3/17/05 - RLB - Removed ceiling and floor characters because they don't -- work on Windows. -- 4/ 7/05 - RLB - Added "Related Documents" link, so users can go between -- the RM and AARM (and also so that they see the ARA -- sponsor ads). -- 5/27/05 - RLB - Added arbitrary Unicode characters. LINE_LENGTH : constant := 78; -- Maximum intended line length. SWISS_FONT_CODE : constant String := ""; TINY_SWISS_FONT_CODE : constant String := ""; type HTML_Type is (HTML_3, -- Use only HTML 3 elements. HTML_4_Compatible, -- Use HTML 4 when needed, but try to look good on old browsers. HTML_4_Only); -- Use only HTML 4 elements (no attempt to look good on old browsers). HTML_Kind : constant HTML_Type := HTML_4_Compatible; -- Eventually, this will be a parameter to the Create routine. Use_Unicode : constant Boolean := True; -- Use Unicode characters. (Many older browsers can't display these; -- it's known that IE can't do so on Windows 95/98/ME.) LEADING_PERCENT : constant := 70; -- Leading is 70% of normal height. TRAILING_PERCENT : constant := 150; -- Leading is 150% of normal height. type Tag_Kind is (DIV, UL, DL); type Format_Info_Type is record Tag : Tag_Kind; Size : Integer; -- In relative "units" (based on the normal size). A unit is 125%/80% of normal. Font : ARM_Output.Font_Family_Type; Indent : Natural; -- In "units". (A unit is = 2EM of the full sized font). Right_Indent : Natural; -- In "units". (A unit is = 2EM of the full sized font). Before : Integer; -- Vertical space before in 0.1 EM. After : Natural; -- Vertical space after in 0.1 EM. end record; Paragraph_Info : constant array (ARM_Output.Paragraph_Type) of Format_Info_Type := ( ARM_Output.Normal => (Tag => DIV, Size => 0, -- 18 Font => ARM_Output.Roman, Indent => 0, Right_Indent => 0, Before => 0, After => 6), -- 120 ARM_Output.Wide => (Tag => DIV, Size => 0, Font => ARM_Output.Roman, Indent => 0, Right_Indent => 0, Before => 6, After => 6), ARM_Output.Index => (Tag => DIV, Size => 0, Font => ARM_Output.Roman, Indent => 0, Right_Indent => 0, Before => 0, After => 0), ARM_Output.Syntax_Summary => (Tag => DIV, Size => -1, Font => ARM_Output.Roman, Indent => 1, Right_Indent => 0, Before => 0, After => 4), ARM_Output.Notes => (Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Roman, Indent => 1, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Notes_Header => (Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Roman, Indent => 1, Right_Indent => 0, Before => 0, After => 0), ARM_Output.Annotations => (Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Roman, Indent => 2, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Wide_Annotations => (Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Roman, Indent => 2, Right_Indent => 0, Before => 6, After => 6), ARM_Output.Examples => (Tag => DIV, Size => 0, Font => ARM_Output.Fixed, Indent => 1, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Small_Examples => (Tag => DIV, Size => -1, Font => ARM_Output.Fixed, Indent => 3, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Syntax_Indented => (Tag => DIV, Size => 0, Font => ARM_Output.Roman, Indent => 1, Right_Indent => 0, Before => 0, After => 4), -- 80 ARM_Output.Indented => (Tag => DIV, Size => 0, Font => ARM_Output.Roman, Indent => 3, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Small_Indented => (Tag => DIV, Size => -1, Font => ARM_Output.Roman, Indent => 5, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Inner_Indented => (Tag => DIV, Size => 0, Font => ARM_Output.Roman, Indent => 4, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Small_Inner_Indented => (Tag => DIV, Size => -1, Font => ARM_Output.Roman, Indent => 6, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Code_Indented => (Tag => DIV, Size => 0, Font => ARM_Output.Roman, Indent => 2, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Small_Code_Indented => (Tag => DIV, Size => -1, Font => ARM_Output.Roman, Indent => 4, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Indented_Examples => (Tag => DIV, Size => 0, Font => ARM_Output.Fixed, Indent => 4, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Small_Indented_Examples => (Tag => DIV, Size => -1, Font => ARM_Output.Fixed, Indent => 6, Right_Indent => 0, Before => 0, After => 6), ARM_Output.Hanging => (Tag => DL, Size => 0, Font => ARM_Output.Roman, Indent => 0, -- Hang amount = 3 (total = 3). Right_Indent => 0, Before => 0, After => 6), ARM_Output.Indented_Hanging => (Tag => DL, Size => 0, Font => ARM_Output.Roman, Indent => 2, -- Hang amount = 1 (total = 3). Right_Indent => 0, Before => 0, After => 6), ARM_Output.Small_Hanging => (Tag => DL, Size => -1, Font => ARM_Output.Roman, Indent => 2, -- Hang amount = 3 (total = 5). Right_Indent => 0, Before => 0, After => 6), ARM_Output.Small_Indented_Hanging => (Tag => DL, Size => 0, Font => ARM_Output.Roman, Indent => 4, -- Hang amount = 1 (total = 5). Right_Indent => 0, Before => 0, After => 6), ARM_Output.Hanging_in_Bulleted => (Tag => DL, Size => 0, Font => ARM_Output.Roman, Indent => 1, -- Hang amount = 2 (total = 3). Right_Indent => 1, Before => 0, After => 5), ARM_Output.Small_Hanging_in_Bulleted => (Tag => DL, Size => -1, Font => ARM_Output.Roman, Indent => 3, -- Hang amount = 2 (total = 5). Right_Indent => 1, Before => 0, After => 5), ARM_Output.Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 1, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Nested_Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 2, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Nested_X2_Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 3, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Small_Bulleted => (Tag => UL, Size => -1, Font => ARM_Output.Roman, Indent => 3, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Small_Nested_Bulleted => (Tag => UL, Size => -1, Font => ARM_Output.Roman, Indent => 4, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Small_Nested_X2_Bulleted => (Tag => UL, Size => -1, Font => ARM_Output.Roman, Indent => 5, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Indented_Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 4, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Indented_Nested_Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 5, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Syntax_Indented_Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 2, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Code_Indented_Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 3, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Code_Indented_Nested_Bulleted => (Tag => UL, Size => 0, Font => ARM_Output.Roman, Indent => 4, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Notes_Bulleted => (Tag => UL, Size => -1, Font => ARM_Output.Roman, Indent => 2, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Notes_Nested_Bulleted => (Tag => UL, Size => -1, Font => ARM_Output.Roman, Indent => 3, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Enumerated => (Tag => DL, Size => 0, Font => ARM_Output.Roman, Indent => 0, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Small_Enumerated => (Tag => DL, Size => -1, Font => ARM_Output.Roman, Indent => 2, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Nested_Enumerated => (Tag => DL, Size => 0, Font => ARM_Output.Roman, Indent => 1, Right_Indent => 1, Before => 0, After => 5), ARM_Output.Small_Nested_Enumerated => (Tag => DL, Size => -1, Font => ARM_Output.Roman, Indent => 3, Right_Indent => 1, Before => 0, After => 5)); procedure Free is new Ada.Unchecked_Deallocation (Column_Text_Item_Type, Column_Text_Ptr); function Make_Clause_Anchor_Name (Output_Object : in HTML_Output_Type; Clause_Number : in String) return String is -- Internal routine. -- Returns the Clause anchor name for the current output object and -- Clause_Number. Clause_Name : String(1..7); Clause_Name_Len : Natural; begin if Clause_Number'Length >= 7 and then Clause_Number(Clause_Number'First .. Clause_Number'First + 5) = "Annex " then Clause_Name(1) := Clause_Number(Clause_Number'First + 6); -- We only want the letter. Clause_Name_Len := 1; else Clause_Name_Len := Clause_Number'Length; Clause_Name(1..Clause_Name_Len) := Clause_Number; for I in 1 .. Clause_Name_Len loop if Clause_Name(I) = '.' then Clause_Name(I) := '-'; end if; end loop; end if; return Clause_Name(1..Clause_Name_Len); end Make_Clause_Anchor_Name; function Make_Clause_File_Name (Output_Object : in HTML_Output_Type; Clause_Number : in String) return String is -- Internal routine. -- Returns the Clause file name for the current output object and -- Clause_Number. This does not include any path or extension. begin if Output_Object.Big_Files then -- One big file. return Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right); else -- Clause files. return Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-" &Make_Clause_Anchor_Name (Output_Object, Clause_Number); end if; end Make_Clause_File_Name; function Make_Clause_Link_Name (Output_Object : in HTML_Output_Type; Clause_Number : in String) return String is -- Internal routine. -- Returns the link name for a link to the given clause. begin if Output_Object.Big_Files then -- One big file. -- Note this is a self-reference, so the file name is not needed. return "#" & Make_Clause_Anchor_Name (Output_Object, Clause_Number); else -- Clause files. return Make_Clause_File_Name (Output_Object, Clause_Number) & ".html"; end if; end Make_Clause_Link_Name; procedure Put_EMs (Fyle : in Ada.Text_IO.File_Type; Value : in Natural) is -- Put an EMs Value (Value is in 0.1 EM). begin if Value <= 9 then Ada.Text_IO.Put (Fyle, '0'); elsif Value <= 99 then Ada.Text_IO.Put (Fyle, Character'Val(Character'Pos('0') + (Value / 10))); else Ada.Text_IO.Put (Fyle, Natural'Image (Value / 10)); end if; Ada.Text_IO.Put (Fyle, '.'); Ada.Text_IO.Put (Fyle, Character'Val(Character'Pos('0') + (Value Mod 10))); Ada.Text_IO.Put (Fyle, "em"); end Put_EMs; procedure Start_HTML_File (Output_Object : in out HTML_Output_Type; File_Name : in String; Title : in String; Clause : in String) is -- Internal routine. -- Create an HTML file, and generate the needed text to start an HTML -- file. The file name is just the name portion, not the path or -- extension. Clause is the properly formatted Clause number for -- this file, if known. procedure Make_Style (Name : in String; Format : in ARM_Output.Paragraph_Type) is -- Generate the style needed. function Units_to_EMs (Value : in Natural) return Natural is -- Convert Value from indentation units to EMs. (0.1 EMs, really). begin if HTML_Kind = HTML_4_Only then case Paragraph_Info(Format).Font is when ARM_Output.Default | ARM_Output.Roman | ARM_Output.Swiss => case Paragraph_Info(Format).Size is when 0 => return Paragraph_Info(Format).Indent * 20; when 1 => return Paragraph_Info(Format).Indent * 16; -- 20/1.25. when 2 => return Paragraph_Info(Format).Indent * 13; -- 20/1.56. when -1 => return Paragraph_Info(Format).Indent * 25; -- 20/0.80. when -2 => return Paragraph_Info(Format).Indent * 31; -- 20/0.64. when -3 => return Paragraph_Info(Format).Indent * 40; -- 20/0.50. when others => return Value; -- Out of range. end case; when ARM_Output.Fixed => -- Start at 90% (otherwise it is huge!) case Paragraph_Info(Format).Size is when 0 => return Paragraph_Info(Format).Indent * 22; -- 20/0.90 when 1 => return Paragraph_Info(Format).Indent * 18; -- 20/1.13. when 2 => return Paragraph_Info(Format).Indent * 14; -- 20/1.40. when -1 => return Paragraph_Info(Format).Indent * 28; -- 20/0.72. when -2 => return Paragraph_Info(Format).Indent * 34; -- 20/0.58. when -3 => return Paragraph_Info(Format).Indent * 44; -- 20/0.45. when others => return Value; -- Out of range. end case; end case; elsif ARM_Output."=" (Paragraph_Info(Format).Font, ARM_Output.Fixed) then -- Special case, see below. case Paragraph_Info(Format).Size is when 0 => return Paragraph_Info(Format).Indent * 20; when 1 => return Paragraph_Info(Format).Indent * 16; -- 20/1.25. when 2 => return Paragraph_Info(Format).Indent * 13; -- 20/1.56. when -1 => return Paragraph_Info(Format).Indent * 25; -- 20/0.80. when -2 => return Paragraph_Info(Format).Indent * 31; -- 20/0.64. when -3 => return Paragraph_Info(Format).Indent * 40; -- 20/0.50. when others => return Value; -- Out of range. end case; else return Paragraph_Info(Format).Indent * 20; -- No font sizes here. end if; end Units_to_EMs; begin case Paragraph_Info(Format).Tag is when DIV => Ada.Text_IO.Put (Output_Object.Output_File, " DIV."); when UL => Ada.Text_IO.Put (Output_Object.Output_File, " UL."); when DL => Ada.Text_IO.Put (Output_Object.Output_File, " DL."); end case; Ada.Text_IO.Put (Output_Object.Output_File, Name & " {"); case Paragraph_Info(Format).Font is when ARM_Output.Default => null; -- Shouldn't happen. when ARM_Output.Roman => Ada.Text_IO.Put (Output_Object.Output_File, "font-family: ""Times New Roman"", Times, serif"); when ARM_Output.Swiss => Ada.Text_IO.Put (Output_Object.Output_File, "font-family: Arial, Helvetica, sans-serif"); when ARM_Output.Fixed => Ada.Text_IO.Put (Output_Object.Output_File, "font-family: ""Courier New"", monospace"); end case; if HTML_Kind = HTML_4_Only then case Paragraph_Info(Format).Font is when ARM_Output.Default | ARM_Output.Roman | ARM_Output.Swiss => case Paragraph_Info(Format).Size is when 0 => null; -- Default. when 1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 125%"); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 156%"); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 80%"); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 64%"); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 50%"); when others => null; -- Out of range. end case; when ARM_Output.Fixed => -- Start at 90% (otherwise it is huge!) case Paragraph_Info(Format).Size is when 0 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 90%"); when 1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 113%"); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 140%"); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 72%"); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 58%"); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 45%"); when others => null; -- Out of range. end case; end case; elsif ARM_Output."=" (Paragraph_Info(Format).Font, ARM_Output.Fixed) then -- Special case because the font otherwise gets too small and -- loses bold-facing. case Paragraph_Info(Format).Size is when 0 => null; -- Default. when 1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 125%"); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 156%"); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 80%"); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 64%"); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 50%"); when others => null; -- Out of range. end case; -- else the size will be set explicitly for HTML_4_Compatible. end if; if Paragraph_Info(Format).Indent /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-left: "); Put_Ems (Output_Object.Output_File, Units_to_EMs(Paragraph_Info(Format).Indent)); end if; if Paragraph_Info(Format).Right_Indent /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-right: "); Put_Ems (Output_Object.Output_File, Units_to_EMs(Paragraph_Info(Format).Right_Indent)); end if; if Paragraph_Info(Format).Before /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-top: "); Put_Ems (Output_Object.Output_File, Paragraph_Info(Format).Before); elsif Paragraph_Info(Format).Tag /= DIV then -- The default is non-zero. Ada.Text_IO.Put (Output_Object.Output_File, "; margin-top: 0em"); end if; if Paragraph_Info(Format).After /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-bottom: "); Put_Ems (Output_Object.Output_File, Paragraph_Info(Format).After); end if; -- Done, close it. Ada.Text_IO.Put_Line (Output_Object.Output_File, "}"); end Make_Style; procedure Make_Hung_Text_Style (Name : in String; Format : in ARM_Output.Paragraph_Type; Indent : in Natural) is -- Generate the style needed. begin Ada.Text_IO.Put (Output_Object.Output_File, " DD." & Name & " {"); Ada.Text_IO.Put (Output_Object.Output_File, "margin-left: "); case Paragraph_Info(Format).Size is when 0 => Put_Ems (Output_Object.Output_File, Indent * 20); when 1 => Put_Ems (Output_Object.Output_File, Indent * 16); -- 20/1.25. when 2 => Put_Ems (Output_Object.Output_File, Indent * 13); -- 20/1.56. when -1 => Put_Ems (Output_Object.Output_File, Indent * 25); -- 20/0.80. when -2 => Put_Ems (Output_Object.Output_File, Indent * 31); -- 20/0.64. when -3 => Put_Ems (Output_Object.Output_File, Indent * 40); -- 20/0.50. when others => null; -- Out of range. end case; -- Done, close it. Ada.Text_IO.Put_Line (Output_Object.Output_File, "}"); end Make_Hung_Text_Style; begin Ada.Text_IO.Create (Output_Object.Output_File, Ada.Text_IO.Out_File, ".\Output\" & File_Name & ".html"); --Ada.Text_IO.Put_Line ("--Creating " & File_Name & ".html"); -- File introduction: if HTML_Kind > HTML_3 then Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); -- HTML 4.01 (with depreciated features) else Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); -- HTML 3.2 end if; -- so the result can be used on version 3 browsers.) Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); -- Header information: Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, " " & Title & ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); if HTML_Kind = HTML_4_Only then -- The style sheet. Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); elsif HTML_Kind = HTML_4_Compatible then -- The style sheet. Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); end if; Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); Ada.Text_IO.Put (Output_Object.Output_File, "

Contents"); Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "Index"); Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "Search"); Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "Related Documents"); if Clause /= "" then begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put (Output_Object.Output_File, "   Previous"); exception when ARM_Contents.Not_Found_Error => null; -- Probably the first section. end; begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put (Output_Object.Output_File, "   Next"); exception when ARM_Contents.Not_Found_Error => null; -- Probably the last section. end; end if; Ada.Text_IO.Put_Line (Output_Object.Output_File, "

"); Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- Horizontal line (rule). end Start_HTML_File; procedure End_HTML_File (Output_Object : in out HTML_Output_Type; Clause : in String) is -- Internal routine. -- Generate the needed text to end an HTML file. Also closes the file. -- Clause is the properly formatted Clause number for the NEXT file, -- if known. begin Ada.Text_IO.New_Line (Output_Object.Output_File); -- Blank line to set off paragraphs. Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- Horizontal line (rule). Ada.Text_IO.Put (Output_Object.Output_File, "

Contents"); Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "Index"); Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "Search"); Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "Related Documents"); if Clause /= "" then begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put (Output_Object.Output_File, "   Previous"); exception when ARM_Contents.Not_Found_Error => null; -- Probably the first section. end; Ada.Text_IO.Put (Output_Object.Output_File, "   Next"); end if; Ada.Text_IO.Put (Output_Object.Output_File, "   Legal"); Ada.Text_IO.Put_Line (Output_Object.Output_File, "

"); Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); Ada.Text_IO.Close (Output_Object.Output_File); end End_HTML_File; procedure Create (Output_Object : in out HTML_Output_Type; Page_Size : in ARM_Output.Page_Size; Includes_Changes : in Boolean; Big_Files : in Boolean; For_ISO : in Boolean := False; File_Prefix : in String; Header_Prefix : in String := ""; Title : in String := "") is -- Create an Output_Object for a document with the specified page -- size. Changes from the base standard are included if -- Includes_Changes is True. Generate a few large output files if -- Big_Files is True; otherwise generate smaller output files. -- The prefix of the output file names is File_Prefix - this -- should be no more then 4 characters allowed in file names. -- The title of the document is Title. -- The header prefix appears in the header (if any) before the title, -- separated by a dash. begin if Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already valid object"); end if; Output_Object.Is_Valid := True; Ada.Strings.Fixed.Move (Target => Output_Object.File_Prefix, Source => File_Prefix); Output_Object.Title := Ada.Strings.Unbounded.To_Unbounded_String (Title); -- We don't use the page size, changes flag, for ISO flag, or -- Header prefix. Output_Object.Big_Files := Big_Files; if Output_Object.Big_Files then Start_HTML_File (Output_Object, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right), Ada.Strings.Unbounded.To_String (Output_Object.Title), Clause => ""); -- Insert an anchor for the title page: Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); end if; end Create; procedure Close (Output_Object : in out HTML_Output_Type) is -- Close an Output_Object. No further output to the object is -- allowed after this call. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Ada.Text_IO.Is_Open (Output_Object.Output_File) then End_HTML_File (Output_Object, ""); end if; Output_Object.Is_Valid := False; end Close; procedure Section (Output_Object : in out HTML_Output_Type; Section_Title : in String; Section_Name : in String) is -- Start a new section. The title is Section_Title (this is -- intended for humans). The name is Section_Name (this is -- intended to be suitable to be a portion of a file name). begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Section in paragraph"); end if; -- We don't generate a file here for HTML. We generate a file for each -- clause. if Section_Name'Length > 3 then Output_Object.Section_Name := Section_Name (Section_Name'First .. Section_Name'First + 2); else Output_Object.Section_Name := (others => '-'); Output_Object.Section_Name (1 .. Section_Name'Length) := Section_Name; end if; end Section; procedure Set_Columns (Output_Object : in out HTML_Output_Type; Number_of_Columns : in ARM_Output.Column_Count) is -- Set the number of columns. -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "In paragraph"); end if; if Number_of_Columns >= 4 then -- We have special processing for 4 or more columns. Note that we -- assume such items are formated with explicit New_Column calls, -- and do not contain any nested paragraph formats. Output_Object.Current_Column := 1; Output_Object.Current_Item := 1; elsif Output_Object.Column_Count >= 4 and then Number_of_Columns = 1 then -- Finished processing columns, output the columns as a table. if HTML_Kind = HTML_3 then Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); else Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); end if; exit; end if; -- End the row: Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put (Output_Object.Output_File, ""); end loop; Output_Object.Current_Column := 0; Output_Object.Current_Item := 0; -- else Two and Three column formats are displayed without any columns. -- This is mainly used for the syntax cross-reference and index, and -- these definitely look better without columns. end if; Output_Object.Column_Count := Number_of_Columns; end Set_Columns; procedure Check_Clause_File (Output_Object : in out HTML_Output_Type) is -- Check that a Clause file has been made for this clause; if not, -- create one. begin if not Ada.Text_IO.Is_Open (Output_Object.Output_File) then Start_HTML_File (Output_Object, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-" & Output_Object.Section_Name, "", Clause => ""); end if; end Check_Clause_File; procedure Put_Compatibility_Font_Info (Output_Object : in out HTML_Output_Type; Format : in ARM_Output.Paragraph_Type) is -- Internal: -- Output the font information for HTML 4.0 compatibility mode. begin if HTML_Kind = HTML_4_Compatible then case Paragraph_Info(Format).Font is when ARM_Output.Default | ARM_Output.Roman => null; when ARM_Output.Swiss => Ada.Text_IO.Put (Output_Object.Output_File, SWISS_FONT_CODE); Output_Object.Char_Count := Output_Object.Char_Count + SWISS_FONT_CODE'Length; when ARM_Output.Fixed => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 4; end case; if ARM_Output."=" (Paragraph_Info(Format).Font, ARM_Output.Fixed) then null; -- No font change here. else case Paragraph_Info(Format).Size is when 0 => null; when 1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when 2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when -1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when -2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when -3 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when others => null; -- Not supported. end case; end if; end if; end Put_Compatibility_Font_Info; procedure Put_End_Compatibility_Font_Info (Output_Object : in out HTML_Output_Type; Format : in ARM_Output.Paragraph_Type) is -- Internal: -- Output the font information for HTML 4.0 compatibility mode. begin if HTML_Kind = HTML_4_Compatible then if ARM_Output."=" (Paragraph_Info(Format).Font, ARM_Output.Fixed) then null; -- No font change here. else case Paragraph_Info(Format).Size is when 0 => null; when 1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when others => null; -- Not supported. end case; end if; case Paragraph_Info(Format).Font is when ARM_Output.Default | ARM_Output.Roman => null; when ARM_Output.Swiss => Ada.Text_IO.Put (Output_Object.Output_File, "
"); when ARM_Output.Fixed => Ada.Text_IO.Put (Output_Object.Output_File, ""); end case; end if; end Put_End_Compatibility_Font_Info; procedure Start_Paragraph (Output_Object : in out HTML_Output_Type; Format : in ARM_Output.Paragraph_Type; Number : in String; No_Prefix : in Boolean := False; Tab_Stops : in ARM_Output.Tab_Info := ARM_Output.NO_TABS; No_Breaks : in Boolean := False; Keep_with_Next : in Boolean := False; Space_After : in ARM_Output.Space_After_Type := ARM_Output.Normal; Justification : in ARM_Output.Justification_Type := ARM_Output.Default) is -- Start a new paragraph. The format of the paragraph is as specified. -- The (AA)RM paragraph number (which might include update and version -- numbers as well: [12.1/1]) is Number. If the format is a type with -- a prefix (bullets, hangining items), the prefix is omitted if -- No_Prefix is true. Tab_Stops defines the tab stops for the -- paragraph. If No_Breaks is True, we will try to avoid page breaks -- in the paragraph. If Keep_with_Next is true, we will try to avoid -- separating this paragraph and the next one. (These may have no -- effect in formats that don't have page breaks). Space_After -- specifies the amount of space following the paragraph. Justification -- specifies the text justification for the paragraph. Not_Valid_Error -- is raised if Tab_Stops /= NO_TABS for a hanging or bulleted format. procedure Put_Style (Name : in String; Include_Compatibility : in Boolean := True) is -- Output a style for HTML 4.0; if Include_Compatibility is True, -- include compatibility font information as well. begin case Paragraph_Info(Format).Tag is when DIV => Ada.Text_IO.Put (Output_Object.Output_File, " Ada.Text_IO.Put (Output_Object.Output_File, " Ada.Text_IO.Put (Output_Object.Output_File, " null; when ARM_Output.Center => Ada.Text_IO.Put (Output_Object.Output_File, " Style=""text-align: center"""); Output_Object.Char_Count := Output_Object.Char_Count + 27; when ARM_Output.Right => Ada.Text_IO.Put (Output_Object.Output_File, " Style=""text-align: right"""); Output_Object.Char_Count := Output_Object.Char_Count + 26; end case; case Space_After is when ARM_Output.Normal => null; when ARM_Output.Narrow => Ada.Text_IO.Put (Output_Object.Output_File, " Style=""margin-bottom: "); Output_Object.Char_Count := Output_Object.Char_Count + 24; Put_EMs(Output_Object.Output_File, (Paragraph_Info(Format).After * LEADING_PERCENT) / 100); Ada.Text_IO.Put (Output_Object.Output_File, """"); Output_Object.Char_Count := Output_Object.Char_Count + 6; when ARM_Output.Wide => Ada.Text_IO.Put (Output_Object.Output_File, " Style=""margin-bottom: "); Output_Object.Char_Count := Output_Object.Char_Count + 24; Put_EMs(Output_Object.Output_File, (Paragraph_Info(Format).After * TRAILING_PERCENT) / 100); Ada.Text_IO.Put (Output_Object.Output_File, """"); Output_Object.Char_Count := Output_Object.Char_Count + 6; end case; Ada.Text_IO.Put (Output_Object.Output_File, ">"); Output_Object.Char_Count := Output_Object.Char_Count + 1; if HTML_Kind = HTML_4_Compatible and then Include_Compatibility then Put_Compatibility_Font_Info (Output_Object, Format); end if; end Put_Style; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already in paragraph"); end if; Output_Object.Is_In_Paragraph := True; Output_Object.Had_Prefix := not No_Prefix; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line Output_Object.Conditional_Space := False; Output_Object.Saw_Hang_End := False; Check_Clause_File (Output_Object); -- Note: We only support Justification for the Normal and Wide styles. if Output_Object.Column_Count >= 4 then -- Formatting is deferred; only a few formats are supported. if Tab_Stops.Number /= 0 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Tabs in 4+ column text"); end if; case Format is when ARM_Output.Normal | ARM_Output.Syntax_Indented | ARM_Output.Code_Indented | ARM_Output.Indented => null; when others => Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Unsupported format in 4+ column text - " & ARM_Output.Paragraph_Type'Image(Format)); end case; if Number /= "" then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "No paragraph numbers in 4+ column text"); end if; return; -- Nothing more to do here. end if; -- Set up tabs: case Format is when ARM_Output.Normal | ARM_Output.Wide | ARM_Output.Notes | ARM_Output.Notes_Header | ARM_Output.Annotations | ARM_Output.Wide_Annotations | ARM_Output.Index | ARM_Output.Syntax_Summary | ARM_Output.Examples | ARM_Output.Small_Examples | ARM_Output.Indented_Examples | ARM_Output.Small_Indented_Examples | ARM_Output.Syntax_Indented | ARM_Output.Indented | ARM_Output.Small_Indented | ARM_Output.Inner_Indented | ARM_Output.Small_Inner_Indented | ARM_Output.Code_Indented | ARM_Output.Small_Code_Indented => Output_Object.Tab_Stops := Tab_Stops; -- No tabs in HTML; we'll emulate them for fixed fonts. -- We'll expand proportional stops here (text characters -- are larger than the variable ones these are set up for). Output_Object.Emulate_Tabs := ARM_Output."=" (Paragraph_Info(Format).Font, ARM_Output.Fixed); for I in 1 .. Tab_Stops.Number loop if ARM_Output."=" (Tab_Stops.Stops(I).Kind, ARM_Output.Left_Proportional) then if ARM_Output."=" (Paragraph_Info(Format).Font, ARM_Output.Fixed) then Output_Object.Tab_Stops.Stops(I).Stop := (Tab_Stops.Stops(I).Stop * 13 / 12); else -- Proportional characters are smaller. Output_Object.Tab_Stops.Stops(I).Stop := (Tab_Stops.Stops(I).Stop * 5 / 4); end if; else Output_Object.Tab_Stops.Stops(I).Stop := Tab_Stops.Stops(I).Stop; end if; end loop; when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted | ARM_Output.Nested_X2_Bulleted | ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted | ARM_Output.Small_Nested_X2_Bulleted | ARM_Output.Indented_Bulleted | ARM_Output.Indented_Nested_Bulleted | ARM_Output.Code_Indented_Bulleted | ARM_Output.Code_Indented_Nested_Bulleted | ARM_Output.Syntax_Indented_Bulleted | ARM_Output.Notes_Bulleted | ARM_Output.Notes_Nested_Bulleted | ARM_Output.Hanging | ARM_Output.Indented_Hanging | ARM_Output.Small_Hanging | ARM_Output.Small_Indented_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Enumerated | ARM_Output.Small_Enumerated | ARM_Output.Nested_Enumerated | ARM_Output.Small_Nested_Enumerated => if Tab_Stops.Number /= 0 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Tabs in hanging/bulleted paragraph"); end if; Output_Object.Emulate_Tabs := False; end case; if HTML_Kind = HTML_3 then -- Note: We can't control the space below the paragraphs here, so -- Space_After is ignored. case Format is when ARM_Output.Normal => case Justification is when ARM_Output.Default | ARM_Output.Left | ARM_Output.Justified => Ada.Text_IO.Put (Output_Object.Output_File, "

"); Output_Object.Char_Count := 3; when ARM_Output.Center => Ada.Text_IO.Put (Output_Object.Output_File, "

"); Output_Object.Char_Count := 16; when ARM_Output.Right => Ada.Text_IO.Put (Output_Object.Output_File, "

"); Output_Object.Char_Count := 15; end case; when ARM_Output.Wide => case Justification is when ARM_Output.Default | ARM_Output.Left | ARM_Output.Justified => Ada.Text_IO.Put (Output_Object.Output_File, "

"); Output_Object.Char_Count := 3; when ARM_Output.Center => Ada.Text_IO.Put (Output_Object.Output_File, "

"); Output_Object.Char_Count := 16; when ARM_Output.Right => Ada.Text_IO.Put (Output_Object.Output_File, "

"); Output_Object.Char_Count := 15; end case; -- Note: In HTML 4, we might be able to control the space above. when ARM_Output.Notes=> Ada.Text_IO.Put (Output_Object.Output_File, "