1
-------------------------------------------------------------------------------
3
-- This file is part of AdaBrowse.
5
-- <STRONG>Copyright (c) 2002 by Thomas Wolf.</STRONG>
7
-- AdaBrowse is free software; you can redistribute it and/or modify it
8
-- under the terms of the GNU General Public License as published by the
9
-- Free Software Foundation; either version 2, or (at your option) any
10
-- later version. AdaBrowse is distributed in the hope that it will be
11
-- useful, but <EM>without any warranty</EM>; without even the implied
12
-- warranty of <EM>merchantability or fitness for a particular purpose.</EM>
13
-- See the GNU General Public License for more details. You should have
14
-- received a copy of the GNU General Public License with this distribution,
15
-- see file "<A HREF="GPL.txt">GPL.txt</A>". If not, write to the Free
16
-- Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21
-- Author:</STRONG><DD>
23
-- <ADDRESS><A HREF="mailto:twolf@acm.org">twolf@acm.org</A></ADDRESS></DL>
26
-- Purpose:</STRONG><DD>
27
-- HTML output helper routines.</DL>
32
-- 02-FEB-2002 TW First release.
33
-- 04-FEB-2002 TW Added 'Get_Compile_Command' for V1.01.
34
-- 13-MAR-2002 TW Added 'Header' and 'Footer' with file parameter.
35
-- Also added key 'Index_XRef'.
36
-- 14-MAR-2002 TW Added key 'Index_Title'.
37
-- 18-MAR-2002 TW Correction in HTMLize: only replace & by & if it
38
-- isn't already the start of a named character entity
39
-- (e.g., if the original comment is "<", we *don't*
40
-- want to replace the '&', and the same goes for """).
41
-- Also changed HTMLize_Comment to replace pairs of '@'
42
-- without white-space in between by <CODE> and </CODE>.
43
-- 03-APR-2002 TW Moved all items for indices to package AD.Indices.
44
-- 18-JUN-2002 TW Removed a bunch of unused operations.
45
-- 24-JUn-2002 TW Changed 'Is_Named_Char' to also handle numeric character
46
-- entities in hexadecimal format ("å" or å").
47
-- 04-JUL-2002 TW Changed the 'Header' and 'Footer' routines by factoring
48
-- their bodies into generic procedures such that there's
49
-- only one place in the sources where these string occur,
50
-- not two. Also added a "STYLE" element to the header.
51
-- 07-JUL-2003 TW Added a new "UL.index" style to the STYLE element in the
54
-------------------------------------------------------------------------------
58
with Ada.Characters.Handling;
60
with Ada.Strings.Fixed;
61
with Ada.Strings.Maps;
62
with Ada.Strings.Unbounded;
68
with Util.Calendar.IO;
72
package body AD.HTML is
74
package ASF renames Ada.Strings.Fixed;
75
package ASM renames Ada.Strings.Maps;
76
package ASU renames Ada.Strings.Unbounded;
80
type HTML_Tag is array (HTML_Tag_Kind) of ASU.Unbounded_String;
82
Style_Sheet : ASU.Unbounded_String;
84
Body_Start : ASU.Unbounded_String;
86
Char_Set : ASU.Unbounded_String;
92
Definition : HTML_Tag;
97
function Character_Set
101
return ASU.To_String (Char_Set);
105
with procedure Line (S : in String);
106
procedure Dump_Header
109
procedure Dump_Header
114
("<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"">");
119
Line ("<TITLE>" & HTMLize (Title) & "</TITLE>");
120
Line ("<META NAME=""generator"" CONTENT=""AdaBrowse " &
121
AD.Version.Get_Version & ' ' & AD.Version.Get_URL & """>");
122
if ASU.Length (Char_Set) /= 0 then
123
Line ("<META http-equiv=""Content-Type"" content=""" &
124
"text/html; charset=" & ASU.To_String (Char_Set) & """>");
126
Line ("<LINK REV=""made"" HREF=""" & AD.Version.Get_URL & """>");
127
-- Now put the default styles here. They can be overwritten by a user-
128
-- defined style sheet containing !important rules.
129
Line ("<STYLE TYPE=""text/css"">");
130
Line (" TABLE.title { background-color : #99CCFF }");
131
Line (" TABLE.footer { background-color : #99CCFF }");
132
Line (" TD.type { background-color : #CCEEFF }");
133
Line (" TD.odd { background-color : #99CCFF }");
134
Line (" TD.even { background-color : #CCEEFF }");
135
Line (" TD.code { background-color : #EEEEEE }");
136
Line (" SPAN.comment { color : red }");
137
Line (" SPAN.literal { color : green }");
138
Line (" SPAN.definition { color : purple }");
139
Line (" H3.subtitle { background-color : #CCEEFF }");
140
Line (" UL.index { list-style: none }");
143
S : constant String := ASU.To_String (Style_Sheet);
145
if S'Last >= S'First then
146
Line ("<LINK REL=""stylesheet"" HREF=""" & S &
147
""" TYPE=""text/css"">");
152
Line (ASU.To_String (Body_Start));
154
Line (ASU.To_String (AD.HTML.Title (Before)) & HTMLize (Title) &
155
ASU.To_String (AD.HTML.Title (After)));
157
Line ("<!-- Generated by AdaBrowse " & AD.Version.Get_Version &
158
' ' & AD.Version.Get_URL & " -->");
162
(File : in Ada.Text_IO.File_Type;
169
Ada.Text_IO.Put_Line (File, S);
172
procedure Dump is new Dump_Header (Write_Line);
179
with procedure Write (S : in String);
180
with procedure Line (S : in String);
181
procedure Dump_Footer;
183
procedure Dump_Footer
185
T : constant Ada.Calendar.Time := Ada.Calendar.Clock;
186
Debug_Mode : constant Boolean :=
189
-- Make sure we're no longer in an HTML comment!
191
ASU.To_String (Ending (Before)) & "<!-- -->" &
193
if not Debug_Mode then
195
(" on " & Util.Calendar.IO.Image (T) &
196
" at " & Util.Calendar.IO.Image (Ada.Calendar.Seconds (T)));
198
Write (" by <A HREF=""" & AD.Version.Get_URL & """ TARGET=""_top""" &
199
">AdaBrowse " & AD.Version.Get_Version & "</A>");
200
if not Debug_Mode then
201
if AD.Config.Get_Nof_Config_Files = 1 then
202
Write (" using configuration file " &
203
HTMLize (AD.Config.Get_Config_Files));
204
elsif AD.Config.Get_Nof_Config_Files > 1 then
205
Write (" using configuration files " &
206
HTMLize (AD.Config.Get_Config_Files));
209
Line ('.' & ASU.To_String (Ending (After)));
215
(File : in Ada.Text_IO.File_Type)
221
Ada.Text_IO.Put (File, S);
228
Ada.Text_IO.Put_Line (File, S);
231
procedure Dump is new Dump_Footer (Write, Write_Line);
238
(File : in Ada.Text_IO.File_Type;
244
ASU.To_String (Sub_Title (Before)) &
246
ASU.To_String (Sub_Title (After)));
249
----------------------------------------------------------------------------
251
HTML_Special_Chars : constant ASM.Character_Set :=
252
ASM.To_Set ("&<>""");
253
Is_8_Bit : constant ASM.Character_Set :=
254
ASM.To_Set (ASM.Character_Range'(Low => Character'Val (160),
255
High => Character'Last));
257
subtype Var_String_Length is Natural range 0 .. 6;
259
type Variable_String (N : Var_String_Length := 0) is
264
type Replacement_Table is array (Character) of Variable_String;
266
Replacement : constant Replacement_Table :=
267
('&' => (5, "&"),
268
'"' => (6, """),
273
function Get_Replacement
278
if Replacement (Ch).N > 0 then
279
return Replacement (Ch).S;
281
return "&#" & Trim (Natural'Image (Character'Pos (Ch))) & ';';
285
function Is_Named_Char
290
if S'Last < S'First then return False; end if;
291
if S (S'First) = '#' then
294
I : Natural := S'First + 1;
296
if I <= S'Last and then (S (I) = 'x' or else S (I) = 'X') then
298
I := I + 1; Start := I;
299
while I <= S'Last and then
300
Ada.Characters.Handling.Is_Hexadecimal_Digit (S (I))
307
while I <= S'Last and then
308
Ada.Characters.Handling.Is_Decimal_Digit (S (I))
313
return I > Start and then I > S'Last;
317
I : Natural := S'First;
319
while I <= S'Last and then Is_In (Letters, S (I)) loop
329
Keep_Entities : in Boolean := True)
333
I : constant Natural := ASF.Index (S, HTML_Special_Chars or Is_8_Bit);
335
if I = 0 then return S; end if;
337
R : constant String := Get_Replacement (S (I));
339
if S (I) = '&' and then Keep_Entities then
340
-- Crap. What if we already have "<" or """ in the source?
342
J : constant Natural := First_Index (S (I + 1 .. S'Last), ';');
344
if J > I + 1 and then
345
-- Check that we have either: # followed by decimal digits,
346
-- # followed by 'x' or 'X' and hex digits, or sequence of
348
Is_Named_Char (S (I + 1 .. J - 1))
350
return S (S'First .. J) &
351
HTMLize (S (J + 1 .. S'Last), Keep_Entities);
356
return R & HTMLize (S (I + 1 .. S'Last), Keep_Entities);
358
return S (S'First .. I - 1) & R &
359
HTMLize (S (I + 1 .. S'Last), Keep_Entities);
364
function Find_Tag_End
366
Is_End : in Boolean := False)
369
I : Natural := S'First;
372
-- Scan ahead to the next '>'.
373
I := First_Index (S, '>');
376
In_String : Boolean := False;
377
Delim : Character := ' ';
379
while I <= S'Last loop
380
if In_String and then S (I) = Delim then
382
elsif not In_String then
384
if Delim = '"' or else Delim = ''' then
387
exit when Delim = '>';
393
if I > S'Last then I := 0; end if;
398
----------------------------------------------------------------------------
404
I : Natural := Next_Non_Blank (Source);
406
if I = 0 then return ""; end if;
408
Result : String (I .. Source'Last);
409
J : Natural := Result'First - 1;
411
-- Replace all LFs or TABs by a space.
412
while I <= Source'Last loop
414
if Is_In (Blanks, Source (I)) then
417
Result (J) := Source (I);
421
-- Strip trailing white space:
422
while J >= Result'First and then Result (J) = ' ' loop
425
return Result (Result'First .. J);
429
----------------------------------------------------------------------------
432
(What : in HTML_Tag_Kind)
436
return ASU.To_String (Keyword (What));
439
function Get_Attribute
440
(What : in HTML_Tag_Kind)
444
return ASU.To_String (Attribute (What));
447
function Get_Definition
448
(What : in HTML_Tag_Kind)
452
return ASU.To_String (Definition (What));
456
(What : in HTML_Tag_Kind)
460
return ASU.To_String (Comment (What));
464
(What : in HTML_Tag_Kind)
468
return ASU.To_String (Literal (What));
471
----------------------------------------------------------------------------
473
procedure Set_Char_Set
477
Char_Set := ASU.To_Unbounded_String (Id);
480
procedure Set_Style_Sheet
484
Style_Sheet := ASU.To_Unbounded_String (URL);
491
Body_Start := ASU.To_Unbounded_String (S);
495
(What : in HTML_Tag_Kind;
499
Title (What) := ASU.To_Unbounded_String (S);
502
procedure Set_Subtitle
503
(What : in HTML_Tag_Kind;
507
Sub_Title (What) := ASU.To_Unbounded_String (S);
510
procedure Set_Keyword
511
(What : in HTML_Tag_Kind;
515
Keyword (What) := ASU.To_Unbounded_String (S);
518
procedure Set_Attribute
519
(What : in HTML_Tag_Kind;
523
Attribute (What) := ASU.To_Unbounded_String (S);
526
procedure Set_Definition
527
(What : in HTML_Tag_Kind;
531
Definition (What) := ASU.To_Unbounded_String (S);
534
procedure Set_Comment
535
(What : in HTML_Tag_Kind;
539
Comment (What) := ASU.To_Unbounded_String (S);
542
procedure Set_Literal
543
(What : in HTML_Tag_Kind;
547
Literal (What) := ASU.To_Unbounded_String (S);
551
Set_Char_Set ("ISO-8859-1"); -- Latin 1
552
Set_Style_Sheet ("adabrowse.css");
553
Set_Body ("<BODY BGCOLOR=""#FFFFF4"">");
556
"<TABLE WIDTH=""100%"" CLASS=""title"" " &
557
"BORDER=0 CELLSPACING=0 CELLPADDING=5><TR><TD><H2>");
558
Set_Title (After, "</H2></TD></TR></TABLE>");
560
Set_Subtitle (Before, "<H3 CLASS=""subtitle"">");
561
Set_Subtitle (After, "</H3>");
563
Set_Keyword (Before, "<STRONG>");
564
Set_Keyword (After, "</STRONG>");
566
Set_Attribute (Before, "<STRONG>");
567
Set_Attribute (After, "</STRONG>");
569
Set_Definition (Before, "<SPAN CLASS=""definition"">");
570
Set_Definition (After, "</SPAN>");
572
Set_Comment (Before, "<EM><SPAN CLASS=""comment"">");
573
Set_Comment (After, "</SPAN></EM>");
575
Set_Literal (Before, "<SPAN CLASS=""literal"">");
576
Set_Literal (After, "</SPAN>");
579
ASU.To_Unbounded_String
580
("<HR><TABLE WIDTH=""100%"" CLASS=""footer"" " &
581
"BORDER=0 CELLSPACING=0 CELLPADDING=5><TR><TD><FONT SIZE=-1>");
584
ASU.To_Unbounded_String ("</FONT></TD></TR></TABLE>");