tidy-ext 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/LICENSE +50 -0
- data/README +12 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/ext/tidy/access.c +3310 -0
- data/ext/tidy/access.h +279 -0
- data/ext/tidy/alloc.c +107 -0
- data/ext/tidy/attrask.c +209 -0
- data/ext/tidy/attrdict.c +2398 -0
- data/ext/tidy/attrdict.h +122 -0
- data/ext/tidy/attrget.c +213 -0
- data/ext/tidy/attrs.c +1911 -0
- data/ext/tidy/attrs.h +374 -0
- data/ext/tidy/buffio.c +232 -0
- data/ext/tidy/buffio.h +118 -0
- data/ext/tidy/charsets.c +1032 -0
- data/ext/tidy/charsets.h +14 -0
- data/ext/tidy/clean.c +2674 -0
- data/ext/tidy/clean.h +87 -0
- data/ext/tidy/config.c +1746 -0
- data/ext/tidy/config.h +153 -0
- data/ext/tidy/entities.c +419 -0
- data/ext/tidy/entities.h +24 -0
- data/ext/tidy/extconf.rb +5 -0
- data/ext/tidy/fileio.c +106 -0
- data/ext/tidy/fileio.h +46 -0
- data/ext/tidy/forward.h +69 -0
- data/ext/tidy/iconvtc.c +105 -0
- data/ext/tidy/iconvtc.h +15 -0
- data/ext/tidy/istack.c +373 -0
- data/ext/tidy/lexer.c +3825 -0
- data/ext/tidy/lexer.h +617 -0
- data/ext/tidy/localize.c +1882 -0
- data/ext/tidy/mappedio.c +329 -0
- data/ext/tidy/mappedio.h +16 -0
- data/ext/tidy/message.h +207 -0
- data/ext/tidy/parser.c +4408 -0
- data/ext/tidy/parser.h +76 -0
- data/ext/tidy/platform.h +636 -0
- data/ext/tidy/pprint.c +2276 -0
- data/ext/tidy/pprint.h +93 -0
- data/ext/tidy/ruby-tidy.c +195 -0
- data/ext/tidy/streamio.c +1407 -0
- data/ext/tidy/streamio.h +222 -0
- data/ext/tidy/tagask.c +286 -0
- data/ext/tidy/tags.c +955 -0
- data/ext/tidy/tags.h +235 -0
- data/ext/tidy/tidy-int.h +129 -0
- data/ext/tidy/tidy.h +1097 -0
- data/ext/tidy/tidyenum.h +622 -0
- data/ext/tidy/tidylib.c +1751 -0
- data/ext/tidy/tmbstr.c +306 -0
- data/ext/tidy/tmbstr.h +92 -0
- data/ext/tidy/utf8.c +539 -0
- data/ext/tidy/utf8.h +52 -0
- data/ext/tidy/version.h +14 -0
- data/ext/tidy/win32tc.c +795 -0
- data/ext/tidy/win32tc.h +19 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/tidy/compat_spec.rb +44 -0
- data/spec/tidy/remote_uri_spec.rb +14 -0
- data/spec/tidy/test1.html +5 -0
- data/spec/tidy/tidy_spec.rb +34 -0
- metadata +125 -0
data/ext/tidy/pprint.c
ADDED
@@ -0,0 +1,2276 @@
|
|
1
|
+
/*
|
2
|
+
pprint.c -- pretty print parse tree
|
3
|
+
|
4
|
+
(c) 1998-2007 (W3C) MIT, ERCIM, Keio University
|
5
|
+
See tidy.h for the copyright notice.
|
6
|
+
|
7
|
+
CVS Info :
|
8
|
+
|
9
|
+
$Author: arnaud02 $
|
10
|
+
$Date: 2008/03/22 20:23:37 $
|
11
|
+
$Revision: 1.119 $
|
12
|
+
|
13
|
+
*/
|
14
|
+
|
15
|
+
#include <stdio.h>
|
16
|
+
#include <stdlib.h>
|
17
|
+
#include <string.h>
|
18
|
+
|
19
|
+
#include "pprint.h"
|
20
|
+
#include "tidy-int.h"
|
21
|
+
#include "parser.h"
|
22
|
+
#include "entities.h"
|
23
|
+
#include "tmbstr.h"
|
24
|
+
#include "utf8.h"
|
25
|
+
|
26
|
+
/*
|
27
|
+
Block-level and unknown elements are printed on
|
28
|
+
new lines and their contents indented 2 spaces
|
29
|
+
|
30
|
+
Inline elements are printed inline.
|
31
|
+
|
32
|
+
Inline content is wrapped on spaces (except in
|
33
|
+
attribute values or preformatted text, after
|
34
|
+
start tags and before end tags
|
35
|
+
*/
|
36
|
+
|
37
|
+
static void PPrintAsp( TidyDocImpl* doc, uint indent, Node* node );
|
38
|
+
static void PPrintJste( TidyDocImpl* doc, uint indent, Node* node );
|
39
|
+
static void PPrintPhp( TidyDocImpl* doc, uint indent, Node* node );
|
40
|
+
static int TextEndsWithNewline( Lexer *lexer, Node *node, uint mode );
|
41
|
+
static int TextStartsWithWhitespace( Lexer *lexer, Node *node, uint start, uint mode );
|
42
|
+
static Bool InsideHead( TidyDocImpl* doc, Node *node );
|
43
|
+
static Bool ShouldIndent( TidyDocImpl* doc, Node *node );
|
44
|
+
|
45
|
+
#if SUPPORT_ASIAN_ENCODINGS
|
46
|
+
/* #431953 - start RJ Wraplen adjusted for smooth international ride */
|
47
|
+
|
48
|
+
#if 0
|
49
|
+
uint CWrapLen( TidyDocImpl* doc, uint ind )
|
50
|
+
{
|
51
|
+
ctmbstr lang = cfgStr( doc, TidyLanguage );
|
52
|
+
uint wraplen = cfg( doc, TidyWrapLen );
|
53
|
+
|
54
|
+
if ( !TY_(tmbstrcasecmp)(lang, "zh") )
|
55
|
+
/* Chinese characters take two positions on a fixed-width screen */
|
56
|
+
/* It would be more accurate to keep a parallel linelen and wraphere
|
57
|
+
incremented by 2 for Chinese characters and 1 otherwise, but this
|
58
|
+
is way simpler.
|
59
|
+
*/
|
60
|
+
return (ind + (( wraplen - ind ) / 2)) ;
|
61
|
+
|
62
|
+
if ( !TY_(tmbstrcasecmp)(lang, "ja") )
|
63
|
+
/* average Japanese text is 30% kanji */
|
64
|
+
return (ind + ((( wraplen - ind ) * 7) / 10)) ;
|
65
|
+
|
66
|
+
return wraplen;
|
67
|
+
}
|
68
|
+
#endif
|
69
|
+
|
70
|
+
typedef enum
|
71
|
+
{
|
72
|
+
UC00, /* None */
|
73
|
+
UCPC, /* Punctuation, Connector */
|
74
|
+
UCPD, /* Punctuation, Dash */
|
75
|
+
UCPE, /* Punctuation, Close */
|
76
|
+
UCPS, /* Punctuation, Open */
|
77
|
+
UCPI, /* Punctuation, Initial quote */
|
78
|
+
UCPF, /* Punctuation, Final quote */
|
79
|
+
UCPO, /* Punctuation, Other */
|
80
|
+
UCZS, /* Separator, Space */
|
81
|
+
UCZL, /* Separator, Line */
|
82
|
+
UCZP /* Separator, Paragraph */
|
83
|
+
} UnicodeCategory;
|
84
|
+
|
85
|
+
/*
|
86
|
+
From the original code, the following characters are removed:
|
87
|
+
|
88
|
+
U+2011 (non-breaking hyphen)
|
89
|
+
U+202F (narrow non-break space)
|
90
|
+
U+2044 (fraction slash)
|
91
|
+
U+200B (zero width space)
|
92
|
+
...... (bidi formatting control characters)
|
93
|
+
|
94
|
+
U+2011 and U+202F are non-breaking, U+2044 is a Sm character,
|
95
|
+
U+200B is a non-visible space, wrapping after it would make
|
96
|
+
this space visible, bidi should be done using HTML features
|
97
|
+
and the characters are neither Px or Zx.
|
98
|
+
|
99
|
+
The following Unicode 3.0 punctuation characters are added:
|
100
|
+
|
101
|
+
U+2048 (question exclamation mark)
|
102
|
+
U+2049 (exclamation question mark)
|
103
|
+
U+204A (tironian sign et)
|
104
|
+
U+204B (reversed pilcrow sign)
|
105
|
+
U+204C (black leftwards bullet)
|
106
|
+
U+204D (black rightwards bullet)
|
107
|
+
U+3030 (wavy dash)
|
108
|
+
U+30FB (katakana middle dot)
|
109
|
+
U+FE63 (small hyphen-minus)
|
110
|
+
U+FE68 (small reverse solidus)
|
111
|
+
U+FF3F (fullwidth low line)
|
112
|
+
U+FF5B (fullwidth left curly bracket)
|
113
|
+
U+FF5D (fullwidth right curly bracket)
|
114
|
+
|
115
|
+
Other additional characters were not included in Unicode 3.0.
|
116
|
+
The table is based on Unicode 4.0. It must include only those
|
117
|
+
characters marking a wrapping point, "before" if the general
|
118
|
+
category is UCPS or UCPI, otherwise "after".
|
119
|
+
*/
|
120
|
+
static struct _unicode4cat
|
121
|
+
{
|
122
|
+
unsigned long code;
|
123
|
+
UnicodeCategory category;
|
124
|
+
} const unicode4cat[] =
|
125
|
+
{
|
126
|
+
#if 0
|
127
|
+
{ 0x037E, UCPO }, { 0x0387, UCPO }, { 0x055A, UCPO }, { 0x055B, UCPO },
|
128
|
+
{ 0x055C, UCPO }, { 0x055D, UCPO }, { 0x055E, UCPO }, { 0x055F, UCPO },
|
129
|
+
{ 0x0589, UCPO }, { 0x058A, UCPD }, { 0x05BE, UCPO }, { 0x05C0, UCPO },
|
130
|
+
{ 0x05C3, UCPO }, { 0x05F3, UCPO }, { 0x05F4, UCPO }, { 0x060C, UCPO },
|
131
|
+
{ 0x060D, UCPO }, { 0x061B, UCPO }, { 0x061F, UCPO }, { 0x066A, UCPO },
|
132
|
+
{ 0x066B, UCPO }, { 0x066C, UCPO }, { 0x066D, UCPO }, { 0x06D4, UCPO },
|
133
|
+
{ 0x0700, UCPO }, { 0x0701, UCPO }, { 0x0702, UCPO }, { 0x0703, UCPO },
|
134
|
+
{ 0x0704, UCPO }, { 0x0705, UCPO }, { 0x0706, UCPO }, { 0x0707, UCPO },
|
135
|
+
{ 0x0708, UCPO }, { 0x0709, UCPO }, { 0x070A, UCPO }, { 0x070B, UCPO },
|
136
|
+
{ 0x070C, UCPO }, { 0x070D, UCPO }, { 0x0964, UCPO }, { 0x0965, UCPO },
|
137
|
+
{ 0x0970, UCPO }, { 0x0DF4, UCPO }, { 0x0E4F, UCPO }, { 0x0E5A, UCPO },
|
138
|
+
{ 0x0E5B, UCPO }, { 0x0F04, UCPO }, { 0x0F05, UCPO }, { 0x0F06, UCPO },
|
139
|
+
{ 0x0F07, UCPO }, { 0x0F08, UCPO }, { 0x0F09, UCPO }, { 0x0F0A, UCPO },
|
140
|
+
{ 0x0F0B, UCPO }, { 0x0F0D, UCPO }, { 0x0F0E, UCPO }, { 0x0F0F, UCPO },
|
141
|
+
{ 0x0F10, UCPO }, { 0x0F11, UCPO }, { 0x0F12, UCPO }, { 0x0F3A, UCPS },
|
142
|
+
{ 0x0F3B, UCPE }, { 0x0F3C, UCPS }, { 0x0F3D, UCPE }, { 0x0F85, UCPO },
|
143
|
+
{ 0x104A, UCPO }, { 0x104B, UCPO }, { 0x104C, UCPO }, { 0x104D, UCPO },
|
144
|
+
{ 0x104E, UCPO }, { 0x104F, UCPO }, { 0x10FB, UCPO }, { 0x1361, UCPO },
|
145
|
+
{ 0x1362, UCPO }, { 0x1363, UCPO }, { 0x1364, UCPO }, { 0x1365, UCPO },
|
146
|
+
{ 0x1366, UCPO }, { 0x1367, UCPO }, { 0x1368, UCPO }, { 0x166D, UCPO },
|
147
|
+
{ 0x166E, UCPO }, { 0x1680, UCZS }, { 0x169B, UCPS }, { 0x169C, UCPE },
|
148
|
+
{ 0x16EB, UCPO }, { 0x16EC, UCPO }, { 0x16ED, UCPO }, { 0x1735, UCPO },
|
149
|
+
{ 0x1736, UCPO }, { 0x17D4, UCPO }, { 0x17D5, UCPO }, { 0x17D6, UCPO },
|
150
|
+
{ 0x17D8, UCPO }, { 0x17D9, UCPO }, { 0x17DA, UCPO }, { 0x1800, UCPO },
|
151
|
+
{ 0x1801, UCPO }, { 0x1802, UCPO }, { 0x1803, UCPO }, { 0x1804, UCPO },
|
152
|
+
{ 0x1805, UCPO }, { 0x1806, UCPD }, { 0x1807, UCPO }, { 0x1808, UCPO },
|
153
|
+
{ 0x1809, UCPO }, { 0x180A, UCPO }, { 0x180E, UCZS }, { 0x1944, UCPO },
|
154
|
+
{ 0x1945, UCPO },
|
155
|
+
#endif
|
156
|
+
{ 0x2000, UCZS }, { 0x2001, UCZS }, { 0x2002, UCZS }, { 0x2003, UCZS },
|
157
|
+
{ 0x2004, UCZS }, { 0x2005, UCZS }, { 0x2006, UCZS }, { 0x2008, UCZS },
|
158
|
+
{ 0x2009, UCZS }, { 0x200A, UCZS }, { 0x2010, UCPD }, { 0x2012, UCPD },
|
159
|
+
{ 0x2013, UCPD }, { 0x2014, UCPD }, { 0x2015, UCPD }, { 0x2016, UCPO },
|
160
|
+
{ 0x2017, UCPO }, { 0x2018, UCPI }, { 0x2019, UCPF }, { 0x201A, UCPS },
|
161
|
+
{ 0x201B, UCPI }, { 0x201C, UCPI }, { 0x201D, UCPF }, { 0x201E, UCPS },
|
162
|
+
{ 0x201F, UCPI }, { 0x2020, UCPO }, { 0x2021, UCPO }, { 0x2022, UCPO },
|
163
|
+
{ 0x2023, UCPO }, { 0x2024, UCPO }, { 0x2025, UCPO }, { 0x2026, UCPO },
|
164
|
+
{ 0x2027, UCPO }, { 0x2028, UCZL }, { 0x2029, UCZP }, { 0x2030, UCPO },
|
165
|
+
{ 0x2031, UCPO }, { 0x2032, UCPO }, { 0x2033, UCPO }, { 0x2034, UCPO },
|
166
|
+
{ 0x2035, UCPO }, { 0x2036, UCPO }, { 0x2037, UCPO }, { 0x2038, UCPO },
|
167
|
+
{ 0x2039, UCPI }, { 0x203A, UCPF }, { 0x203B, UCPO }, { 0x203C, UCPO },
|
168
|
+
{ 0x203D, UCPO }, { 0x203E, UCPO }, { 0x203F, UCPC }, { 0x2040, UCPC },
|
169
|
+
{ 0x2041, UCPO }, { 0x2042, UCPO }, { 0x2043, UCPO }, { 0x2045, UCPS },
|
170
|
+
{ 0x2046, UCPE }, { 0x2047, UCPO }, { 0x2048, UCPO }, { 0x2049, UCPO },
|
171
|
+
{ 0x204A, UCPO }, { 0x204B, UCPO }, { 0x204C, UCPO }, { 0x204D, UCPO },
|
172
|
+
{ 0x204E, UCPO }, { 0x204F, UCPO }, { 0x2050, UCPO }, { 0x2051, UCPO },
|
173
|
+
{ 0x2053, UCPO }, { 0x2054, UCPC }, { 0x2057, UCPO }, { 0x205F, UCZS },
|
174
|
+
{ 0x207D, UCPS }, { 0x207E, UCPE }, { 0x208D, UCPS }, { 0x208E, UCPE },
|
175
|
+
{ 0x2329, UCPS }, { 0x232A, UCPE }, { 0x23B4, UCPS }, { 0x23B5, UCPE },
|
176
|
+
{ 0x23B6, UCPO }, { 0x2768, UCPS }, { 0x2769, UCPE }, { 0x276A, UCPS },
|
177
|
+
{ 0x276B, UCPE }, { 0x276C, UCPS }, { 0x276D, UCPE }, { 0x276E, UCPS },
|
178
|
+
{ 0x276F, UCPE }, { 0x2770, UCPS }, { 0x2771, UCPE }, { 0x2772, UCPS },
|
179
|
+
{ 0x2773, UCPE }, { 0x2774, UCPS }, { 0x2775, UCPE }, { 0x27E6, UCPS },
|
180
|
+
{ 0x27E7, UCPE }, { 0x27E8, UCPS }, { 0x27E9, UCPE }, { 0x27EA, UCPS },
|
181
|
+
{ 0x27EB, UCPE }, { 0x2983, UCPS }, { 0x2984, UCPE }, { 0x2985, UCPS },
|
182
|
+
{ 0x2986, UCPE }, { 0x2987, UCPS }, { 0x2988, UCPE }, { 0x2989, UCPS },
|
183
|
+
{ 0x298A, UCPE }, { 0x298B, UCPS }, { 0x298C, UCPE }, { 0x298D, UCPS },
|
184
|
+
{ 0x298E, UCPE }, { 0x298F, UCPS }, { 0x2990, UCPE }, { 0x2991, UCPS },
|
185
|
+
{ 0x2992, UCPE }, { 0x2993, UCPS }, { 0x2994, UCPE }, { 0x2995, UCPS },
|
186
|
+
{ 0x2996, UCPE }, { 0x2997, UCPS }, { 0x2998, UCPE }, { 0x29D8, UCPS },
|
187
|
+
{ 0x29D9, UCPE }, { 0x29DA, UCPS }, { 0x29DB, UCPE }, { 0x29FC, UCPS },
|
188
|
+
{ 0x29FD, UCPE }, { 0x3001, UCPO }, { 0x3002, UCPO }, { 0x3003, UCPO },
|
189
|
+
{ 0x3008, UCPS }, { 0x3009, UCPE }, { 0x300A, UCPS }, { 0x300B, UCPE },
|
190
|
+
{ 0x300C, UCPS }, { 0x300D, UCPE }, { 0x300E, UCPS }, { 0x300F, UCPE },
|
191
|
+
{ 0x3010, UCPS }, { 0x3011, UCPE }, { 0x3014, UCPS }, { 0x3015, UCPE },
|
192
|
+
{ 0x3016, UCPS }, { 0x3017, UCPE }, { 0x3018, UCPS }, { 0x3019, UCPE },
|
193
|
+
{ 0x301A, UCPS }, { 0x301B, UCPE }, { 0x301C, UCPD }, { 0x301D, UCPS },
|
194
|
+
{ 0x301E, UCPE }, { 0x301F, UCPE }, { 0x3030, UCPD }, { 0x303D, UCPO },
|
195
|
+
{ 0x30A0, UCPD }, { 0x30FB, UCPC }, { 0xFD3E, UCPS }, { 0xFD3F, UCPE },
|
196
|
+
{ 0xFE30, UCPO }, { 0xFE31, UCPD }, { 0xFE32, UCPD }, { 0xFE33, UCPC },
|
197
|
+
{ 0xFE34, UCPC }, { 0xFE35, UCPS }, { 0xFE36, UCPE }, { 0xFE37, UCPS },
|
198
|
+
{ 0xFE38, UCPE }, { 0xFE39, UCPS }, { 0xFE3A, UCPE }, { 0xFE3B, UCPS },
|
199
|
+
{ 0xFE3C, UCPE }, { 0xFE3D, UCPS }, { 0xFE3E, UCPE }, { 0xFE3F, UCPS },
|
200
|
+
{ 0xFE40, UCPE }, { 0xFE41, UCPS }, { 0xFE42, UCPE }, { 0xFE43, UCPS },
|
201
|
+
{ 0xFE44, UCPE }, { 0xFE45, UCPO }, { 0xFE46, UCPO }, { 0xFE47, UCPS },
|
202
|
+
{ 0xFE48, UCPE }, { 0xFE49, UCPO }, { 0xFE4A, UCPO }, { 0xFE4B, UCPO },
|
203
|
+
{ 0xFE4C, UCPO }, { 0xFE4D, UCPC }, { 0xFE4E, UCPC }, { 0xFE4F, UCPC },
|
204
|
+
{ 0xFE50, UCPO }, { 0xFE51, UCPO }, { 0xFE52, UCPO }, { 0xFE54, UCPO },
|
205
|
+
{ 0xFE55, UCPO }, { 0xFE56, UCPO }, { 0xFE57, UCPO }, { 0xFE58, UCPD },
|
206
|
+
{ 0xFE59, UCPS }, { 0xFE5A, UCPE }, { 0xFE5B, UCPS }, { 0xFE5C, UCPE },
|
207
|
+
{ 0xFE5D, UCPS }, { 0xFE5E, UCPE }, { 0xFE5F, UCPO }, { 0xFE60, UCPO },
|
208
|
+
{ 0xFE61, UCPO }, { 0xFE63, UCPD }, { 0xFE68, UCPO }, { 0xFE6A, UCPO },
|
209
|
+
{ 0xFE6B, UCPO }, { 0xFF01, UCPO }, { 0xFF02, UCPO }, { 0xFF03, UCPO },
|
210
|
+
{ 0xFF05, UCPO }, { 0xFF06, UCPO }, { 0xFF07, UCPO }, { 0xFF08, UCPS },
|
211
|
+
{ 0xFF09, UCPE }, { 0xFF0A, UCPO }, { 0xFF0C, UCPO }, { 0xFF0D, UCPD },
|
212
|
+
{ 0xFF0E, UCPO }, { 0xFF0F, UCPO }, { 0xFF1A, UCPO }, { 0xFF1B, UCPO },
|
213
|
+
{ 0xFF1F, UCPO }, { 0xFF20, UCPO }, { 0xFF3B, UCPS }, { 0xFF3C, UCPO },
|
214
|
+
{ 0xFF3D, UCPE }, { 0xFF3F, UCPC }, { 0xFF5B, UCPS }, { 0xFF5D, UCPE },
|
215
|
+
{ 0xFF5F, UCPS }, { 0xFF60, UCPE }, { 0xFF61, UCPO }, { 0xFF62, UCPS },
|
216
|
+
{ 0xFF63, UCPE }, { 0xFF64, UCPO }, { 0xFF65, UCPC }, { 0x10100,UCPO },
|
217
|
+
{ 0x10101,UCPO }, { 0x1039F,UCPO },
|
218
|
+
|
219
|
+
/* final entry */
|
220
|
+
{ 0x0000, UC00 }
|
221
|
+
};
|
222
|
+
|
223
|
+
typedef enum
|
224
|
+
{
|
225
|
+
NoWrapPoint,
|
226
|
+
WrapBefore,
|
227
|
+
WrapAfter
|
228
|
+
} WrapPoint;
|
229
|
+
|
230
|
+
/*
|
231
|
+
If long lines of text have no white space as defined in HTML 4
|
232
|
+
(U+0009, U+000A, U+000D, U+000C, U+0020) other characters could
|
233
|
+
be used to determine a wrap point. Since user agents would
|
234
|
+
normalize the inserted newline character to a space character,
|
235
|
+
this wrapping behaviour would insert visual whitespace into the
|
236
|
+
document.
|
237
|
+
|
238
|
+
Characters of the General Category Pi and Ps in the Unicode
|
239
|
+
character database (opening punctuation and intial quote
|
240
|
+
characters) mark a wrapping point before the character, other
|
241
|
+
punctuation characters (Pc, Pd, Pe, Pf, and Po), breakable
|
242
|
+
space characters (Zs), and paragraph and line separators
|
243
|
+
(Zl, Zp) mark a wrap point after the character. Using this
|
244
|
+
function Tidy can for example pretty print
|
245
|
+
|
246
|
+
<p>....................“...quote...”...</p>
|
247
|
+
as
|
248
|
+
<p>....................\n“...quote...”...</p>
|
249
|
+
or
|
250
|
+
<p>....................“...quote...”\n...</p>
|
251
|
+
|
252
|
+
if the next normal wrapping point would exceed the user
|
253
|
+
chosen wrapping column.
|
254
|
+
*/
|
255
|
+
static WrapPoint CharacterWrapPoint(tchar c)
|
256
|
+
{
|
257
|
+
int i;
|
258
|
+
for (i = 0; unicode4cat[i].code && unicode4cat[i].code <= c; ++i)
|
259
|
+
if (unicode4cat[i].code == c)
|
260
|
+
{
|
261
|
+
/* wrapping before opening punctuation and initial quotes */
|
262
|
+
if (unicode4cat[i].category == UCPS ||
|
263
|
+
unicode4cat[i].category == UCPI)
|
264
|
+
return WrapBefore;
|
265
|
+
/* else wrapping after this character */
|
266
|
+
else
|
267
|
+
return WrapAfter;
|
268
|
+
}
|
269
|
+
/* character has no effect on line wrapping */
|
270
|
+
return NoWrapPoint;
|
271
|
+
}
|
272
|
+
|
273
|
+
static WrapPoint Big5WrapPoint(tchar c)
|
274
|
+
{
|
275
|
+
if ((c & 0xFF00) == 0xA100)
|
276
|
+
{
|
277
|
+
/* opening brackets have odd codes: break before them */
|
278
|
+
if ( c > 0xA15C && c < 0xA1AD && (c & 1) == 1 )
|
279
|
+
return WrapBefore;
|
280
|
+
return WrapAfter;
|
281
|
+
}
|
282
|
+
return NoWrapPoint;
|
283
|
+
}
|
284
|
+
|
285
|
+
#endif /* SUPPORT_ASIAN_ENCODINGS */
|
286
|
+
|
287
|
+
static void InitIndent( TidyIndent* ind )
|
288
|
+
{
|
289
|
+
ind->spaces = -1;
|
290
|
+
ind->attrValStart = -1;
|
291
|
+
ind->attrStringStart = -1;
|
292
|
+
}
|
293
|
+
|
294
|
+
void TY_(InitPrintBuf)( TidyDocImpl* doc )
|
295
|
+
{
|
296
|
+
TidyClearMemory( &doc->pprint, sizeof(TidyPrintImpl) );
|
297
|
+
InitIndent( &doc->pprint.indent[0] );
|
298
|
+
InitIndent( &doc->pprint.indent[1] );
|
299
|
+
doc->pprint.allocator = doc->allocator;
|
300
|
+
}
|
301
|
+
|
302
|
+
void TY_(FreePrintBuf)( TidyDocImpl* doc )
|
303
|
+
{
|
304
|
+
TidyDocFree( doc, doc->pprint.linebuf );
|
305
|
+
TY_(InitPrintBuf)( doc );
|
306
|
+
}
|
307
|
+
|
308
|
+
static void expand( TidyPrintImpl* pprint, uint len )
|
309
|
+
{
|
310
|
+
uint* ip;
|
311
|
+
uint buflen = pprint->lbufsize;
|
312
|
+
|
313
|
+
if ( buflen == 0 )
|
314
|
+
buflen = 256;
|
315
|
+
while ( len >= buflen )
|
316
|
+
buflen *= 2;
|
317
|
+
|
318
|
+
ip = (uint*) TidyRealloc( pprint->allocator, pprint->linebuf, buflen*sizeof(uint) );
|
319
|
+
if ( ip )
|
320
|
+
{
|
321
|
+
TidyClearMemory( ip+pprint->lbufsize,
|
322
|
+
(buflen-pprint->lbufsize)*sizeof(uint) );
|
323
|
+
pprint->lbufsize = buflen;
|
324
|
+
pprint->linebuf = ip;
|
325
|
+
}
|
326
|
+
}
|
327
|
+
|
328
|
+
static uint GetSpaces( TidyPrintImpl* pprint )
|
329
|
+
{
|
330
|
+
int spaces = pprint->indent[ 0 ].spaces;
|
331
|
+
return ( spaces < 0 ? 0U : (uint) spaces );
|
332
|
+
}
|
333
|
+
static int ClearInString( TidyPrintImpl* pprint )
|
334
|
+
{
|
335
|
+
TidyIndent *ind = pprint->indent + pprint->ixInd;
|
336
|
+
return ind->attrStringStart = -1;
|
337
|
+
}
|
338
|
+
static int ToggleInString( TidyPrintImpl* pprint )
|
339
|
+
{
|
340
|
+
TidyIndent *ind = pprint->indent + pprint->ixInd;
|
341
|
+
Bool inString = ( ind->attrStringStart >= 0 );
|
342
|
+
return ind->attrStringStart = ( inString ? -1 : (int) pprint->linelen );
|
343
|
+
}
|
344
|
+
static Bool IsInString( TidyPrintImpl* pprint )
|
345
|
+
{
|
346
|
+
TidyIndent *ind = pprint->indent + 0; /* Always 1st */
|
347
|
+
return ( ind->attrStringStart >= 0 &&
|
348
|
+
ind->attrStringStart < (int) pprint->linelen );
|
349
|
+
}
|
350
|
+
static Bool IsWrapInString( TidyPrintImpl* pprint )
|
351
|
+
{
|
352
|
+
TidyIndent *ind = pprint->indent + 0; /* Always 1st */
|
353
|
+
int wrap = (int) pprint->wraphere;
|
354
|
+
return ( ind->attrStringStart == 0 ||
|
355
|
+
(ind->attrStringStart > 0 && ind->attrStringStart < wrap) );
|
356
|
+
}
|
357
|
+
|
358
|
+
static Bool HasMixedContent (Node *element)
|
359
|
+
{
|
360
|
+
Node * node;
|
361
|
+
|
362
|
+
if (!element)
|
363
|
+
return no;
|
364
|
+
|
365
|
+
for (node = element->content; node; node = node->next)
|
366
|
+
if ( TY_(nodeIsText)(node) )
|
367
|
+
return yes;
|
368
|
+
|
369
|
+
return no;
|
370
|
+
}
|
371
|
+
|
372
|
+
static void ClearInAttrVal( TidyPrintImpl* pprint )
|
373
|
+
{
|
374
|
+
TidyIndent *ind = pprint->indent + pprint->ixInd;
|
375
|
+
ind->attrValStart = -1;
|
376
|
+
}
|
377
|
+
static int SetInAttrVal( TidyPrintImpl* pprint )
|
378
|
+
{
|
379
|
+
TidyIndent *ind = pprint->indent + pprint->ixInd;
|
380
|
+
return ind->attrValStart = (int) pprint->linelen;
|
381
|
+
}
|
382
|
+
static Bool IsWrapInAttrVal( TidyPrintImpl* pprint )
|
383
|
+
{
|
384
|
+
TidyIndent *ind = pprint->indent + 0; /* Always 1st */
|
385
|
+
int wrap = (int) pprint->wraphere;
|
386
|
+
return ( ind->attrValStart == 0 ||
|
387
|
+
(ind->attrValStart > 0 && ind->attrValStart < wrap) );
|
388
|
+
}
|
389
|
+
|
390
|
+
static Bool WantIndent( TidyDocImpl* doc )
|
391
|
+
{
|
392
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
393
|
+
Bool wantIt = GetSpaces(pprint) > 0;
|
394
|
+
if ( wantIt )
|
395
|
+
{
|
396
|
+
Bool indentAttrs = cfgBool( doc, TidyIndentAttributes );
|
397
|
+
wantIt = ( ( !IsWrapInAttrVal(pprint) || indentAttrs ) &&
|
398
|
+
!IsWrapInString(pprint) );
|
399
|
+
}
|
400
|
+
return wantIt;
|
401
|
+
}
|
402
|
+
|
403
|
+
|
404
|
+
static uint WrapOff( TidyDocImpl* doc )
|
405
|
+
{
|
406
|
+
uint saveWrap = cfg( doc, TidyWrapLen );
|
407
|
+
TY_(SetOptionInt)( doc, TidyWrapLen, 0xFFFFFFFF ); /* very large number */
|
408
|
+
return saveWrap;
|
409
|
+
}
|
410
|
+
|
411
|
+
static void WrapOn( TidyDocImpl* doc, uint saveWrap )
|
412
|
+
{
|
413
|
+
TY_(SetOptionInt)( doc, TidyWrapLen, saveWrap );
|
414
|
+
}
|
415
|
+
|
416
|
+
static uint WrapOffCond( TidyDocImpl* doc, Bool onoff )
|
417
|
+
{
|
418
|
+
if ( onoff )
|
419
|
+
return WrapOff( doc );
|
420
|
+
return cfg( doc, TidyWrapLen );
|
421
|
+
}
|
422
|
+
|
423
|
+
|
424
|
+
static void AddC( TidyPrintImpl* pprint, uint c, uint string_index)
|
425
|
+
{
|
426
|
+
if ( string_index + 1 >= pprint->lbufsize )
|
427
|
+
expand( pprint, string_index + 1 );
|
428
|
+
pprint->linebuf[string_index] = c;
|
429
|
+
}
|
430
|
+
|
431
|
+
static uint AddChar( TidyPrintImpl* pprint, uint c )
|
432
|
+
{
|
433
|
+
AddC( pprint, c, pprint->linelen );
|
434
|
+
return ++pprint->linelen;
|
435
|
+
}
|
436
|
+
|
437
|
+
static uint AddAsciiString( TidyPrintImpl* pprint, ctmbstr str, uint string_index )
|
438
|
+
{
|
439
|
+
uint ix, len = TY_(tmbstrlen)( str );
|
440
|
+
if ( string_index + len >= pprint->lbufsize )
|
441
|
+
expand( pprint, string_index + len );
|
442
|
+
|
443
|
+
for ( ix=0; ix<len; ++ix )
|
444
|
+
pprint->linebuf[string_index + ix] = str[ ix ];
|
445
|
+
return string_index + len;
|
446
|
+
}
|
447
|
+
|
448
|
+
static uint AddString( TidyPrintImpl* pprint, ctmbstr str )
|
449
|
+
{
|
450
|
+
return pprint->linelen = AddAsciiString( pprint, str, pprint->linelen );
|
451
|
+
}
|
452
|
+
|
453
|
+
/* Saves current output point as the wrap point,
|
454
|
+
** but only if indentation would NOT overflow
|
455
|
+
** the current line. Otherwise keep previous wrap point.
|
456
|
+
*/
|
457
|
+
static Bool SetWrap( TidyDocImpl* doc, uint indent )
|
458
|
+
{
|
459
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
460
|
+
Bool wrap = ( indent + pprint->linelen < cfg(doc, TidyWrapLen) );
|
461
|
+
if ( wrap )
|
462
|
+
{
|
463
|
+
if ( pprint->indent[0].spaces < 0 )
|
464
|
+
pprint->indent[0].spaces = indent;
|
465
|
+
pprint->wraphere = pprint->linelen;
|
466
|
+
}
|
467
|
+
else if ( pprint->ixInd == 0 )
|
468
|
+
{
|
469
|
+
/* Save indent 1st time we pass the the wrap line */
|
470
|
+
pprint->indent[ 1 ].spaces = indent;
|
471
|
+
pprint->ixInd = 1;
|
472
|
+
}
|
473
|
+
return wrap;
|
474
|
+
}
|
475
|
+
|
476
|
+
static void CarryOver( int* valTo, int* valFrom, uint wrapPoint )
|
477
|
+
{
|
478
|
+
if ( *valFrom > (int) wrapPoint )
|
479
|
+
{
|
480
|
+
*valTo = *valFrom - wrapPoint;
|
481
|
+
*valFrom = -1;
|
482
|
+
}
|
483
|
+
}
|
484
|
+
|
485
|
+
|
486
|
+
static Bool SetWrapAttr( TidyDocImpl* doc,
|
487
|
+
uint indent, int attrStart, int strStart )
|
488
|
+
{
|
489
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
490
|
+
TidyIndent *ind = pprint->indent + 0;
|
491
|
+
|
492
|
+
Bool wrap = ( indent + pprint->linelen < cfg(doc, TidyWrapLen) );
|
493
|
+
if ( wrap )
|
494
|
+
{
|
495
|
+
if ( ind[0].spaces < 0 )
|
496
|
+
ind[0].spaces = indent;
|
497
|
+
pprint->wraphere = pprint->linelen;
|
498
|
+
}
|
499
|
+
else if ( pprint->ixInd == 0 )
|
500
|
+
{
|
501
|
+
/* Save indent 1st time we pass the the wrap line */
|
502
|
+
pprint->indent[ 1 ].spaces = indent;
|
503
|
+
pprint->ixInd = 1;
|
504
|
+
|
505
|
+
/* Carry over string state */
|
506
|
+
CarryOver( &ind[1].attrStringStart, &ind[0].attrStringStart, pprint->wraphere );
|
507
|
+
CarryOver( &ind[1].attrValStart, &ind[0].attrValStart, pprint->wraphere );
|
508
|
+
}
|
509
|
+
ind += doc->pprint.ixInd;
|
510
|
+
ind->attrValStart = attrStart;
|
511
|
+
ind->attrStringStart = strStart;
|
512
|
+
return wrap;
|
513
|
+
}
|
514
|
+
|
515
|
+
|
516
|
+
/* Reset indent state after flushing a new line
|
517
|
+
*/
|
518
|
+
static void ResetLine( TidyPrintImpl* pprint )
|
519
|
+
{
|
520
|
+
TidyIndent* ind = pprint->indent + 0;
|
521
|
+
if ( pprint->ixInd > 0 )
|
522
|
+
{
|
523
|
+
ind[0] = ind[1];
|
524
|
+
InitIndent( &ind[1] );
|
525
|
+
}
|
526
|
+
|
527
|
+
if ( pprint->wraphere > 0 )
|
528
|
+
{
|
529
|
+
int wrap = (int) pprint->wraphere;
|
530
|
+
if ( ind[0].attrStringStart > wrap )
|
531
|
+
ind[0].attrStringStart -= wrap;
|
532
|
+
if ( ind[0].attrValStart > wrap )
|
533
|
+
ind[0].attrValStart -= wrap;
|
534
|
+
}
|
535
|
+
else
|
536
|
+
{
|
537
|
+
if ( ind[0].attrStringStart > 0 )
|
538
|
+
ind[0].attrStringStart = 0;
|
539
|
+
if ( ind[0].attrValStart > 0 )
|
540
|
+
ind[0].attrValStart = 0;
|
541
|
+
}
|
542
|
+
pprint->wraphere = pprint->ixInd = 0;
|
543
|
+
}
|
544
|
+
|
545
|
+
/* Shift text after wrap point to
|
546
|
+
** beginning of next line.
|
547
|
+
*/
|
548
|
+
static void ResetLineAfterWrap( TidyPrintImpl* pprint )
|
549
|
+
{
|
550
|
+
if ( pprint->linelen > pprint->wraphere )
|
551
|
+
{
|
552
|
+
uint *p = pprint->linebuf;
|
553
|
+
uint *q = p + pprint->wraphere;
|
554
|
+
uint *end = p + pprint->linelen;
|
555
|
+
|
556
|
+
if ( ! IsWrapInAttrVal(pprint) )
|
557
|
+
{
|
558
|
+
while ( q < end && *q == ' ' )
|
559
|
+
++q, ++pprint->wraphere;
|
560
|
+
}
|
561
|
+
|
562
|
+
while ( q < end )
|
563
|
+
*p++ = *q++;
|
564
|
+
|
565
|
+
pprint->linelen -= pprint->wraphere;
|
566
|
+
}
|
567
|
+
else
|
568
|
+
{
|
569
|
+
pprint->linelen = 0;
|
570
|
+
}
|
571
|
+
|
572
|
+
ResetLine( pprint );
|
573
|
+
}
|
574
|
+
|
575
|
+
/* Goes ahead with writing current line up to
|
576
|
+
** previously saved wrap point. Shifts unwritten
|
577
|
+
** text in output buffer to beginning of next line.
|
578
|
+
*/
|
579
|
+
static void WrapLine( TidyDocImpl* doc )
|
580
|
+
{
|
581
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
582
|
+
uint i;
|
583
|
+
|
584
|
+
if ( pprint->wraphere == 0 )
|
585
|
+
return;
|
586
|
+
|
587
|
+
if ( WantIndent(doc) )
|
588
|
+
{
|
589
|
+
uint spaces = GetSpaces( pprint );
|
590
|
+
for ( i = 0; i < spaces; ++i )
|
591
|
+
TY_(WriteChar)( ' ', doc->docOut );
|
592
|
+
}
|
593
|
+
|
594
|
+
for ( i = 0; i < pprint->wraphere; ++i )
|
595
|
+
TY_(WriteChar)( pprint->linebuf[i], doc->docOut );
|
596
|
+
|
597
|
+
if ( IsWrapInString(pprint) )
|
598
|
+
TY_(WriteChar)( '\\', doc->docOut );
|
599
|
+
|
600
|
+
TY_(WriteChar)( '\n', doc->docOut );
|
601
|
+
ResetLineAfterWrap( pprint );
|
602
|
+
}
|
603
|
+
|
604
|
+
/* Checks current output line length along with current indent.
|
605
|
+
** If combined they overflow output line length, go ahead
|
606
|
+
** and flush output up to the current wrap point.
|
607
|
+
*/
|
608
|
+
static Bool CheckWrapLine( TidyDocImpl* doc )
|
609
|
+
{
|
610
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
611
|
+
if ( GetSpaces(pprint) + pprint->linelen >= cfg(doc, TidyWrapLen) )
|
612
|
+
{
|
613
|
+
WrapLine( doc );
|
614
|
+
return yes;
|
615
|
+
}
|
616
|
+
return no;
|
617
|
+
}
|
618
|
+
|
619
|
+
static Bool CheckWrapIndent( TidyDocImpl* doc, uint indent )
|
620
|
+
{
|
621
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
622
|
+
if ( GetSpaces(pprint) + pprint->linelen >= cfg(doc, TidyWrapLen) )
|
623
|
+
{
|
624
|
+
WrapLine( doc );
|
625
|
+
if ( pprint->indent[ 0 ].spaces < 0 )
|
626
|
+
pprint->indent[ 0 ].spaces = indent;
|
627
|
+
return yes;
|
628
|
+
}
|
629
|
+
return no;
|
630
|
+
}
|
631
|
+
|
632
|
+
static void WrapAttrVal( TidyDocImpl* doc )
|
633
|
+
{
|
634
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
635
|
+
uint i;
|
636
|
+
|
637
|
+
/* assert( IsWrapInAttrVal(pprint) ); */
|
638
|
+
if ( WantIndent(doc) )
|
639
|
+
{
|
640
|
+
uint spaces = GetSpaces( pprint );
|
641
|
+
for ( i = 0; i < spaces; ++i )
|
642
|
+
TY_(WriteChar)( ' ', doc->docOut );
|
643
|
+
}
|
644
|
+
|
645
|
+
for ( i = 0; i < pprint->wraphere; ++i )
|
646
|
+
TY_(WriteChar)( pprint->linebuf[i], doc->docOut );
|
647
|
+
|
648
|
+
if ( IsWrapInString(pprint) )
|
649
|
+
TY_(WriteChar)( '\\', doc->docOut );
|
650
|
+
else
|
651
|
+
TY_(WriteChar)( ' ', doc->docOut );
|
652
|
+
|
653
|
+
TY_(WriteChar)( '\n', doc->docOut );
|
654
|
+
ResetLineAfterWrap( pprint );
|
655
|
+
}
|
656
|
+
|
657
|
+
static void PFlushLineImpl( TidyDocImpl* doc )
|
658
|
+
{
|
659
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
660
|
+
|
661
|
+
uint i;
|
662
|
+
|
663
|
+
CheckWrapLine( doc );
|
664
|
+
|
665
|
+
if ( WantIndent(doc) )
|
666
|
+
{
|
667
|
+
uint spaces = GetSpaces( pprint );
|
668
|
+
for ( i = 0; i < spaces; ++i )
|
669
|
+
TY_(WriteChar)( ' ', doc->docOut );
|
670
|
+
}
|
671
|
+
|
672
|
+
for ( i = 0; i < pprint->linelen; ++i )
|
673
|
+
TY_(WriteChar)( pprint->linebuf[i], doc->docOut );
|
674
|
+
|
675
|
+
if ( IsInString(pprint) )
|
676
|
+
TY_(WriteChar)( '\\', doc->docOut );
|
677
|
+
ResetLine( pprint );
|
678
|
+
pprint->linelen = 0;
|
679
|
+
}
|
680
|
+
|
681
|
+
void TY_(PFlushLine)( TidyDocImpl* doc, uint indent )
|
682
|
+
{
|
683
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
684
|
+
|
685
|
+
if ( pprint->linelen > 0 )
|
686
|
+
PFlushLineImpl( doc );
|
687
|
+
|
688
|
+
TY_(WriteChar)( '\n', doc->docOut );
|
689
|
+
pprint->indent[ 0 ].spaces = indent;
|
690
|
+
}
|
691
|
+
|
692
|
+
static void PCondFlushLine( TidyDocImpl* doc, uint indent )
|
693
|
+
{
|
694
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
695
|
+
|
696
|
+
if ( pprint->linelen > 0 )
|
697
|
+
{
|
698
|
+
PFlushLineImpl( doc );
|
699
|
+
|
700
|
+
TY_(WriteChar)( '\n', doc->docOut );
|
701
|
+
pprint->indent[ 0 ].spaces = indent;
|
702
|
+
}
|
703
|
+
}
|
704
|
+
|
705
|
+
static void PPrintChar( TidyDocImpl* doc, uint c, uint mode )
|
706
|
+
{
|
707
|
+
tmbchar entity[128];
|
708
|
+
ctmbstr p;
|
709
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
710
|
+
uint outenc = cfg( doc, TidyOutCharEncoding );
|
711
|
+
Bool qmark = cfgBool( doc, TidyQuoteMarks );
|
712
|
+
|
713
|
+
if ( c == ' ' && !(mode & (PREFORMATTED | COMMENT | ATTRIBVALUE | CDATA)))
|
714
|
+
{
|
715
|
+
/* coerce a space character to a non-breaking space */
|
716
|
+
if (mode & NOWRAP)
|
717
|
+
{
|
718
|
+
ctmbstr ent = " ";
|
719
|
+
/* by default XML doesn't define */
|
720
|
+
if ( cfgBool(doc, TidyNumEntities) || cfgBool(doc, TidyXmlTags) )
|
721
|
+
ent = " ";
|
722
|
+
AddString( pprint, ent );
|
723
|
+
return;
|
724
|
+
}
|
725
|
+
else
|
726
|
+
pprint->wraphere = pprint->linelen;
|
727
|
+
}
|
728
|
+
|
729
|
+
/* comment characters are passed raw */
|
730
|
+
if ( mode & (COMMENT | CDATA) )
|
731
|
+
{
|
732
|
+
AddChar( pprint, c );
|
733
|
+
return;
|
734
|
+
}
|
735
|
+
|
736
|
+
/* except in CDATA map < to < etc. */
|
737
|
+
if ( !(mode & CDATA) )
|
738
|
+
{
|
739
|
+
if ( c == '<')
|
740
|
+
{
|
741
|
+
AddString( pprint, "<" );
|
742
|
+
return;
|
743
|
+
}
|
744
|
+
|
745
|
+
if ( c == '>')
|
746
|
+
{
|
747
|
+
AddString( pprint, ">" );
|
748
|
+
return;
|
749
|
+
}
|
750
|
+
|
751
|
+
/*
|
752
|
+
naked '&' chars can be left alone or
|
753
|
+
quoted as & The latter is required
|
754
|
+
for XML where naked '&' are illegal.
|
755
|
+
*/
|
756
|
+
if ( c == '&' && cfgBool(doc, TidyQuoteAmpersand)
|
757
|
+
&& !cfgBool(doc, TidyPreserveEntities) )
|
758
|
+
{
|
759
|
+
AddString( pprint, "&" );
|
760
|
+
return;
|
761
|
+
}
|
762
|
+
|
763
|
+
if ( c == '"' && qmark )
|
764
|
+
{
|
765
|
+
AddString( pprint, """ );
|
766
|
+
return;
|
767
|
+
}
|
768
|
+
|
769
|
+
if ( c == '\'' && qmark )
|
770
|
+
{
|
771
|
+
AddString( pprint, "'" );
|
772
|
+
return;
|
773
|
+
}
|
774
|
+
|
775
|
+
if ( c == 160 && outenc != RAW )
|
776
|
+
{
|
777
|
+
if ( cfgBool(doc, TidyQuoteNbsp) )
|
778
|
+
{
|
779
|
+
if ( cfgBool(doc, TidyNumEntities) ||
|
780
|
+
cfgBool(doc, TidyXmlTags) )
|
781
|
+
AddString( pprint, " " );
|
782
|
+
else
|
783
|
+
AddString( pprint, " " );
|
784
|
+
}
|
785
|
+
else
|
786
|
+
AddChar( pprint, c );
|
787
|
+
return;
|
788
|
+
}
|
789
|
+
}
|
790
|
+
|
791
|
+
#if SUPPORT_ASIAN_ENCODINGS
|
792
|
+
|
793
|
+
/* #431953 - start RJ */
|
794
|
+
/* Handle encoding-specific issues */
|
795
|
+
switch ( outenc )
|
796
|
+
{
|
797
|
+
case UTF8:
|
798
|
+
#if SUPPORT_UTF16_ENCODINGS
|
799
|
+
case UTF16:
|
800
|
+
case UTF16LE:
|
801
|
+
case UTF16BE:
|
802
|
+
#endif
|
803
|
+
if (!(mode & PREFORMATTED) && cfg(doc, TidyPunctWrap))
|
804
|
+
{
|
805
|
+
WrapPoint wp = CharacterWrapPoint(c);
|
806
|
+
if (wp == WrapBefore)
|
807
|
+
pprint->wraphere = pprint->linelen;
|
808
|
+
else if (wp == WrapAfter)
|
809
|
+
pprint->wraphere = pprint->linelen + 1;
|
810
|
+
}
|
811
|
+
break;
|
812
|
+
|
813
|
+
case BIG5:
|
814
|
+
/* Allow linebreak at Chinese punctuation characters */
|
815
|
+
/* There are not many spaces in Chinese */
|
816
|
+
AddChar( pprint, c );
|
817
|
+
if (!(mode & PREFORMATTED) && cfg(doc, TidyPunctWrap))
|
818
|
+
{
|
819
|
+
WrapPoint wp = Big5WrapPoint(c);
|
820
|
+
if (wp == WrapBefore)
|
821
|
+
pprint->wraphere = pprint->linelen;
|
822
|
+
else if (wp == WrapAfter)
|
823
|
+
pprint->wraphere = pprint->linelen + 1;
|
824
|
+
}
|
825
|
+
return;
|
826
|
+
|
827
|
+
case SHIFTJIS:
|
828
|
+
#ifndef NO_NATIVE_ISO2022_SUPPORT
|
829
|
+
case ISO2022: /* ISO 2022 characters are passed raw */
|
830
|
+
#endif
|
831
|
+
case RAW:
|
832
|
+
AddChar( pprint, c );
|
833
|
+
return;
|
834
|
+
}
|
835
|
+
/* #431953 - end RJ */
|
836
|
+
|
837
|
+
#else /* SUPPORT_ASIAN_ENCODINGS */
|
838
|
+
|
839
|
+
/* otherwise ISO 2022 characters are passed raw */
|
840
|
+
if (
|
841
|
+
#ifndef NO_NATIVE_ISO2022_SUPPORT
|
842
|
+
outenc == ISO2022 ||
|
843
|
+
#endif
|
844
|
+
outenc == RAW )
|
845
|
+
{
|
846
|
+
AddChar( pprint, c );
|
847
|
+
return;
|
848
|
+
}
|
849
|
+
|
850
|
+
#endif /* SUPPORT_ASIAN_ENCODINGS */
|
851
|
+
|
852
|
+
/* don't map latin-1 chars to entities */
|
853
|
+
if ( outenc == LATIN1 )
|
854
|
+
{
|
855
|
+
if (c > 255) /* multi byte chars */
|
856
|
+
{
|
857
|
+
uint vers = TY_(HTMLVersion)( doc );
|
858
|
+
if ( !cfgBool(doc, TidyNumEntities) && (p = TY_(EntityName)(c, vers)) )
|
859
|
+
TY_(tmbsnprintf)(entity, sizeof(entity), "&%s;", p);
|
860
|
+
else
|
861
|
+
TY_(tmbsnprintf)(entity, sizeof(entity), "&#%u;", c);
|
862
|
+
|
863
|
+
AddString( pprint, entity );
|
864
|
+
return;
|
865
|
+
}
|
866
|
+
|
867
|
+
if (c > 126 && c < 160)
|
868
|
+
{
|
869
|
+
TY_(tmbsnprintf)(entity, sizeof(entity), "&#%u;", c);
|
870
|
+
AddString( pprint, entity );
|
871
|
+
return;
|
872
|
+
}
|
873
|
+
|
874
|
+
AddChar( pprint, c );
|
875
|
+
return;
|
876
|
+
}
|
877
|
+
|
878
|
+
/* don't map UTF-8 chars to entities */
|
879
|
+
if ( outenc == UTF8 )
|
880
|
+
{
|
881
|
+
AddChar( pprint, c );
|
882
|
+
return;
|
883
|
+
}
|
884
|
+
|
885
|
+
#if SUPPORT_UTF16_ENCODINGS
|
886
|
+
/* don't map UTF-16 chars to entities */
|
887
|
+
if ( outenc == UTF16 || outenc == UTF16LE || outenc == UTF16BE )
|
888
|
+
{
|
889
|
+
AddChar( pprint, c );
|
890
|
+
return;
|
891
|
+
}
|
892
|
+
#endif
|
893
|
+
|
894
|
+
/* use numeric entities only for XML */
|
895
|
+
if ( cfgBool(doc, TidyXmlTags) )
|
896
|
+
{
|
897
|
+
/* if ASCII use numeric entities for chars > 127 */
|
898
|
+
if ( c > 127 && outenc == ASCII )
|
899
|
+
{
|
900
|
+
TY_(tmbsnprintf)(entity, sizeof(entity), "&#%u;", c);
|
901
|
+
AddString( pprint, entity );
|
902
|
+
return;
|
903
|
+
}
|
904
|
+
|
905
|
+
/* otherwise output char raw */
|
906
|
+
AddChar( pprint, c );
|
907
|
+
return;
|
908
|
+
}
|
909
|
+
|
910
|
+
/* default treatment for ASCII */
|
911
|
+
if ( outenc == ASCII && (c > 126 || (c < ' ' && c != '\t')) )
|
912
|
+
{
|
913
|
+
uint vers = TY_(HTMLVersion)( doc );
|
914
|
+
if (!cfgBool(doc, TidyNumEntities) && (p = TY_(EntityName)(c, vers)) )
|
915
|
+
TY_(tmbsnprintf)(entity, sizeof(entity), "&%s;", p);
|
916
|
+
else
|
917
|
+
TY_(tmbsnprintf)(entity, sizeof(entity), "&#%u;", c);
|
918
|
+
|
919
|
+
AddString( pprint, entity );
|
920
|
+
return;
|
921
|
+
}
|
922
|
+
|
923
|
+
AddChar( pprint, c );
|
924
|
+
}
|
925
|
+
|
926
|
+
static uint IncrWS( uint start, uint end, uint indent, int ixWS )
|
927
|
+
{
|
928
|
+
if ( ixWS > 0 )
|
929
|
+
{
|
930
|
+
uint st = start + MIN( (uint)ixWS, indent );
|
931
|
+
start = MIN( st, end );
|
932
|
+
}
|
933
|
+
return start;
|
934
|
+
}
|
935
|
+
/*
|
936
|
+
The line buffer is uint not char so we can
|
937
|
+
hold Unicode values unencoded. The translation
|
938
|
+
to UTF-8 is deferred to the TY_(WriteChar)() routine called
|
939
|
+
to flush the line buffer.
|
940
|
+
*/
|
941
|
+
static void PPrintText( TidyDocImpl* doc, uint mode, uint indent,
|
942
|
+
Node* node )
|
943
|
+
{
|
944
|
+
uint start = node->start;
|
945
|
+
uint end = node->end;
|
946
|
+
uint ix, c = 0;
|
947
|
+
int ixNL = TextEndsWithNewline( doc->lexer, node, mode );
|
948
|
+
int ixWS = TextStartsWithWhitespace( doc->lexer, node, start, mode );
|
949
|
+
if ( ixNL > 0 )
|
950
|
+
end -= ixNL;
|
951
|
+
start = IncrWS( start, end, indent, ixWS );
|
952
|
+
|
953
|
+
for ( ix = start; ix < end; ++ix )
|
954
|
+
{
|
955
|
+
CheckWrapIndent( doc, indent );
|
956
|
+
/*
|
957
|
+
if ( CheckWrapIndent(doc, indent) )
|
958
|
+
{
|
959
|
+
ixWS = TextStartsWithWhitespace( doc->lexer, node, ix );
|
960
|
+
ix = IncrWS( ix, end, indent, ixWS );
|
961
|
+
}
|
962
|
+
*/
|
963
|
+
c = (byte) doc->lexer->lexbuf[ix];
|
964
|
+
|
965
|
+
/* look for UTF-8 multibyte character */
|
966
|
+
if ( c > 0x7F )
|
967
|
+
ix += TY_(GetUTF8)( doc->lexer->lexbuf + ix, &c );
|
968
|
+
|
969
|
+
if ( c == '\n' )
|
970
|
+
{
|
971
|
+
TY_(PFlushLine)( doc, indent );
|
972
|
+
ixWS = TextStartsWithWhitespace( doc->lexer, node, ix+1, mode );
|
973
|
+
ix = IncrWS( ix, end, indent, ixWS );
|
974
|
+
}
|
975
|
+
else
|
976
|
+
{
|
977
|
+
PPrintChar( doc, c, mode );
|
978
|
+
}
|
979
|
+
}
|
980
|
+
}
|
981
|
+
|
982
|
+
#if 0
|
983
|
+
static void PPrintString( TidyDocImpl* doc, uint indent, ctmbstr str )
|
984
|
+
{
|
985
|
+
while ( *str != '\0' )
|
986
|
+
AddChar( &doc->pprint, *str++ );
|
987
|
+
}
|
988
|
+
#endif /* 0 */
|
989
|
+
|
990
|
+
|
991
|
+
static void PPrintAttrValue( TidyDocImpl* doc, uint indent,
|
992
|
+
ctmbstr value, uint delim, Bool wrappable, Bool scriptAttr )
|
993
|
+
{
|
994
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
995
|
+
Bool scriptlets = cfgBool(doc, TidyWrapScriptlets);
|
996
|
+
|
997
|
+
uint mode = PREFORMATTED | ATTRIBVALUE;
|
998
|
+
if ( wrappable )
|
999
|
+
mode = NORMAL | ATTRIBVALUE;
|
1000
|
+
|
1001
|
+
/* look for ASP, Tango or PHP instructions for computed attribute value */
|
1002
|
+
if ( value && value[0] == '<' )
|
1003
|
+
{
|
1004
|
+
if ( value[1] == '%' || value[1] == '@'||
|
1005
|
+
TY_(tmbstrncmp)(value, "<?php", 5) == 0 )
|
1006
|
+
mode |= CDATA;
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
if ( delim == 0 )
|
1010
|
+
delim = '"';
|
1011
|
+
|
1012
|
+
AddChar( pprint, '=' );
|
1013
|
+
|
1014
|
+
/* don't wrap after "=" for xml documents */
|
1015
|
+
if ( !cfgBool(doc, TidyXmlOut) || cfgBool(doc, TidyXhtmlOut) )
|
1016
|
+
{
|
1017
|
+
SetWrap( doc, indent );
|
1018
|
+
CheckWrapIndent( doc, indent );
|
1019
|
+
/*
|
1020
|
+
if ( !SetWrap(doc, indent) )
|
1021
|
+
PCondFlushLine( doc, indent );
|
1022
|
+
*/
|
1023
|
+
}
|
1024
|
+
|
1025
|
+
AddChar( pprint, delim );
|
1026
|
+
|
1027
|
+
if ( value )
|
1028
|
+
{
|
1029
|
+
uint wraplen = cfg( doc, TidyWrapLen );
|
1030
|
+
int attrStart = SetInAttrVal( pprint );
|
1031
|
+
int strStart = ClearInString( pprint );
|
1032
|
+
|
1033
|
+
while (*value != '\0')
|
1034
|
+
{
|
1035
|
+
uint c = *value;
|
1036
|
+
|
1037
|
+
if ( wrappable && c == ' ' )
|
1038
|
+
SetWrapAttr( doc, indent, attrStart, strStart );
|
1039
|
+
|
1040
|
+
if ( wrappable && pprint->wraphere > 0 &&
|
1041
|
+
GetSpaces(pprint) + pprint->linelen >= wraplen )
|
1042
|
+
WrapAttrVal( doc );
|
1043
|
+
|
1044
|
+
if ( c == delim )
|
1045
|
+
{
|
1046
|
+
ctmbstr entity = (c == '"' ? """ : "'");
|
1047
|
+
AddString( pprint, entity );
|
1048
|
+
++value;
|
1049
|
+
continue;
|
1050
|
+
}
|
1051
|
+
else if (c == '"')
|
1052
|
+
{
|
1053
|
+
if ( cfgBool(doc, TidyQuoteMarks) )
|
1054
|
+
AddString( pprint, """ );
|
1055
|
+
else
|
1056
|
+
AddChar( pprint, c );
|
1057
|
+
|
1058
|
+
if ( delim == '\'' && scriptAttr && scriptlets )
|
1059
|
+
strStart = ToggleInString( pprint );
|
1060
|
+
|
1061
|
+
++value;
|
1062
|
+
continue;
|
1063
|
+
}
|
1064
|
+
else if ( c == '\'' )
|
1065
|
+
{
|
1066
|
+
if ( cfgBool(doc, TidyQuoteMarks) )
|
1067
|
+
AddString( pprint, "'" );
|
1068
|
+
else
|
1069
|
+
AddChar( pprint, c );
|
1070
|
+
|
1071
|
+
if ( delim == '"' && scriptAttr && scriptlets )
|
1072
|
+
strStart = ToggleInString( pprint );
|
1073
|
+
|
1074
|
+
++value;
|
1075
|
+
continue;
|
1076
|
+
}
|
1077
|
+
|
1078
|
+
/* look for UTF-8 multibyte character */
|
1079
|
+
if ( c > 0x7F )
|
1080
|
+
value += TY_(GetUTF8)( value, &c );
|
1081
|
+
++value;
|
1082
|
+
|
1083
|
+
if ( c == '\n' )
|
1084
|
+
{
|
1085
|
+
/* No indent inside Javascript literals */
|
1086
|
+
TY_(PFlushLine)( doc, (strStart < 0
|
1087
|
+
&& !cfgBool(doc, TidyLiteralAttribs) ?
|
1088
|
+
indent : 0) );
|
1089
|
+
continue;
|
1090
|
+
}
|
1091
|
+
PPrintChar( doc, c, mode );
|
1092
|
+
}
|
1093
|
+
ClearInAttrVal( pprint );
|
1094
|
+
ClearInString( pprint );
|
1095
|
+
}
|
1096
|
+
AddChar( pprint, delim );
|
1097
|
+
}
|
1098
|
+
|
1099
|
+
static uint AttrIndent( TidyDocImpl* doc, Node* node, AttVal* ARG_UNUSED(attr) )
|
1100
|
+
{
|
1101
|
+
uint spaces = cfg( doc, TidyIndentSpaces );
|
1102
|
+
uint xtra = 2; /* 1 for the '<', another for the ' ' */
|
1103
|
+
if ( node->element == NULL )
|
1104
|
+
return spaces;
|
1105
|
+
|
1106
|
+
if ( !TY_(nodeHasCM)(node, CM_INLINE) ||
|
1107
|
+
!ShouldIndent(doc, node->parent ? node->parent: node) )
|
1108
|
+
return xtra + TY_(tmbstrlen)( node->element );
|
1109
|
+
|
1110
|
+
if ( NULL != (node = TY_(FindContainer)(node)) )
|
1111
|
+
return xtra + TY_(tmbstrlen)( node->element );
|
1112
|
+
return spaces;
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
static Bool AttrNoIndentFirst( /*TidyDocImpl* doc,*/ Node* node, AttVal* attr )
|
1116
|
+
{
|
1117
|
+
return ( attr==node->attributes );
|
1118
|
+
|
1119
|
+
/*&&
|
1120
|
+
( InsideHead(doc, node) ||
|
1121
|
+
!TY_(nodeHasCM)(node, CM_INLINE) ) );
|
1122
|
+
*/
|
1123
|
+
}
|
1124
|
+
|
1125
|
+
static void PPrintAttribute( TidyDocImpl* doc, uint indent,
|
1126
|
+
Node *node, AttVal *attr )
|
1127
|
+
{
|
1128
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1129
|
+
Bool xmlOut = cfgBool( doc, TidyXmlOut );
|
1130
|
+
Bool xhtmlOut = cfgBool( doc, TidyXhtmlOut );
|
1131
|
+
Bool wrapAttrs = cfgBool( doc, TidyWrapAttVals );
|
1132
|
+
Bool ucAttrs = cfgBool( doc, TidyUpperCaseAttrs );
|
1133
|
+
Bool indAttrs = cfgBool( doc, TidyIndentAttributes );
|
1134
|
+
uint xtra = AttrIndent( doc, node, attr );
|
1135
|
+
Bool first = AttrNoIndentFirst( /*doc,*/ node, attr );
|
1136
|
+
tmbstr name = attr->attribute;
|
1137
|
+
Bool wrappable = no;
|
1138
|
+
tchar c;
|
1139
|
+
|
1140
|
+
/* fix for odd attribute indentation bug triggered by long values */
|
1141
|
+
if (!indAttrs)
|
1142
|
+
xtra = 0;
|
1143
|
+
|
1144
|
+
if ( indAttrs )
|
1145
|
+
{
|
1146
|
+
if ( TY_(nodeIsElement)(node) && !first )
|
1147
|
+
{
|
1148
|
+
indent += xtra;
|
1149
|
+
PCondFlushLine( doc, indent );
|
1150
|
+
}
|
1151
|
+
else
|
1152
|
+
indAttrs = no;
|
1153
|
+
}
|
1154
|
+
|
1155
|
+
CheckWrapIndent( doc, indent );
|
1156
|
+
|
1157
|
+
if ( !xmlOut && !xhtmlOut && attr->dict )
|
1158
|
+
{
|
1159
|
+
if ( TY_(IsScript)(doc, name) )
|
1160
|
+
wrappable = cfgBool( doc, TidyWrapScriptlets );
|
1161
|
+
else if (!(attrIsCONTENT(attr) || attrIsVALUE(attr) || attrIsALT(attr)) && wrapAttrs )
|
1162
|
+
wrappable = yes;
|
1163
|
+
}
|
1164
|
+
|
1165
|
+
if ( !first && !SetWrap(doc, indent) )
|
1166
|
+
{
|
1167
|
+
TY_(PFlushLine)( doc, indent+xtra ); /* Put it on next line */
|
1168
|
+
}
|
1169
|
+
else if ( pprint->linelen > 0 )
|
1170
|
+
{
|
1171
|
+
AddChar( pprint, ' ' );
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
/* Attribute name */
|
1175
|
+
while (*name)
|
1176
|
+
{
|
1177
|
+
c = (unsigned char)*name;
|
1178
|
+
|
1179
|
+
if (c > 0x7F)
|
1180
|
+
name += TY_(GetUTF8)(name, &c);
|
1181
|
+
else if (ucAttrs)
|
1182
|
+
c = TY_(ToUpper)(c);
|
1183
|
+
|
1184
|
+
AddChar(pprint, c);
|
1185
|
+
++name;
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
/* fix for bug 732038 */
|
1189
|
+
#if 0
|
1190
|
+
/* If not indenting attributes, bump up indent for
|
1191
|
+
** value after putting out name.
|
1192
|
+
*/
|
1193
|
+
if ( !indAttrs )
|
1194
|
+
indent += xtra;
|
1195
|
+
#endif
|
1196
|
+
|
1197
|
+
CheckWrapIndent( doc, indent );
|
1198
|
+
|
1199
|
+
if ( attr->value == NULL )
|
1200
|
+
{
|
1201
|
+
Bool isB = TY_(IsBoolAttribute)(attr);
|
1202
|
+
Bool scriptAttr = TY_(attrIsEvent)(attr);
|
1203
|
+
|
1204
|
+
if ( xmlOut )
|
1205
|
+
PPrintAttrValue( doc, indent, isB ? attr->attribute : NULLSTR,
|
1206
|
+
attr->delim, no, scriptAttr );
|
1207
|
+
|
1208
|
+
else if ( !isB && !TY_(IsNewNode)(node) )
|
1209
|
+
PPrintAttrValue( doc, indent, "", attr->delim, yes, scriptAttr );
|
1210
|
+
|
1211
|
+
else
|
1212
|
+
SetWrap( doc, indent );
|
1213
|
+
}
|
1214
|
+
else
|
1215
|
+
PPrintAttrValue( doc, indent, attr->value, attr->delim, wrappable, no );
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
static void PPrintAttrs( TidyDocImpl* doc, uint indent, Node *node )
|
1219
|
+
{
|
1220
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1221
|
+
AttVal* av;
|
1222
|
+
|
1223
|
+
/* add xml:space attribute to pre and other elements */
|
1224
|
+
if ( cfgBool(doc, TidyXmlOut) && cfgBool(doc, TidyXmlSpace) &&
|
1225
|
+
!TY_(GetAttrByName)(node, "xml:space") &&
|
1226
|
+
TY_(XMLPreserveWhiteSpace)(doc, node) )
|
1227
|
+
{
|
1228
|
+
TY_(AddAttribute)( doc, node, "xml:space", "preserve" );
|
1229
|
+
}
|
1230
|
+
|
1231
|
+
for ( av = node->attributes; av; av = av->next )
|
1232
|
+
{
|
1233
|
+
if ( av->attribute != NULL )
|
1234
|
+
{
|
1235
|
+
PPrintAttribute( doc, indent, node, av );
|
1236
|
+
}
|
1237
|
+
else if ( av->asp != NULL )
|
1238
|
+
{
|
1239
|
+
AddChar( pprint, ' ' );
|
1240
|
+
PPrintAsp( doc, indent, av->asp );
|
1241
|
+
}
|
1242
|
+
else if ( av->php != NULL )
|
1243
|
+
{
|
1244
|
+
AddChar( pprint, ' ' );
|
1245
|
+
PPrintPhp( doc, indent, av->php );
|
1246
|
+
}
|
1247
|
+
}
|
1248
|
+
}
|
1249
|
+
|
1250
|
+
Bool TY_(TextNodeEndWithSpace)( Lexer *lexer, Node *node )
|
1251
|
+
{
|
1252
|
+
if (TY_(nodeIsText)(node) && node->end > node->start)
|
1253
|
+
{
|
1254
|
+
uint i, c = '\0'; /* initialised to avoid warnings */
|
1255
|
+
for (i = node->start; i < node->end; ++i)
|
1256
|
+
{
|
1257
|
+
c = (byte) lexer->lexbuf[i];
|
1258
|
+
if ( c > 0x7F )
|
1259
|
+
i += TY_(GetUTF8)( lexer->lexbuf + i, &c );
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
if ( c == ' ' || c == '\n' )
|
1263
|
+
return yes;
|
1264
|
+
}
|
1265
|
+
return no;
|
1266
|
+
}
|
1267
|
+
|
1268
|
+
/*
|
1269
|
+
Line can be wrapped immediately after inline start tag provided
|
1270
|
+
if follows a text node ending in a space, or it follows a <br>,
|
1271
|
+
or its parent is an inline element that that rule applies to.
|
1272
|
+
This behaviour was reverse engineered from Netscape 3.0.
|
1273
|
+
|
1274
|
+
Line wrapping can occur if an element is not empty and before a block
|
1275
|
+
level. For instance:
|
1276
|
+
<p><span>
|
1277
|
+
x</span>y</p>
|
1278
|
+
will display properly. Whereas
|
1279
|
+
<p><img />
|
1280
|
+
x</p> won't.
|
1281
|
+
*/
|
1282
|
+
static Bool AfterSpaceImp(Lexer *lexer, Node *node, Bool isEmpty)
|
1283
|
+
{
|
1284
|
+
Node *prev;
|
1285
|
+
|
1286
|
+
if ( !TY_(nodeCMIsInline)(node) )
|
1287
|
+
return yes;
|
1288
|
+
|
1289
|
+
prev = node->prev;
|
1290
|
+
if (prev)
|
1291
|
+
{
|
1292
|
+
if (TY_(nodeIsText)(prev))
|
1293
|
+
return TY_(TextNodeEndWithSpace)( lexer, prev );
|
1294
|
+
else if (nodeIsBR(prev))
|
1295
|
+
return yes;
|
1296
|
+
|
1297
|
+
return no;
|
1298
|
+
}
|
1299
|
+
|
1300
|
+
if ( isEmpty && !TY_(nodeCMIsInline)(node->parent) )
|
1301
|
+
return no;
|
1302
|
+
|
1303
|
+
return AfterSpaceImp(lexer, node->parent, isEmpty);
|
1304
|
+
}
|
1305
|
+
|
1306
|
+
static Bool AfterSpace(Lexer *lexer, Node *node)
|
1307
|
+
{
|
1308
|
+
return AfterSpaceImp(lexer, node, TY_(nodeCMIsEmpty)(node));
|
1309
|
+
}
|
1310
|
+
|
1311
|
+
static void PPrintTag( TidyDocImpl* doc,
|
1312
|
+
uint mode, uint indent, Node *node )
|
1313
|
+
{
|
1314
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1315
|
+
Bool uc = cfgBool( doc, TidyUpperCaseTags );
|
1316
|
+
Bool xhtmlOut = cfgBool( doc, TidyXhtmlOut );
|
1317
|
+
Bool xmlOut = cfgBool( doc, TidyXmlOut );
|
1318
|
+
tchar c;
|
1319
|
+
tmbstr s = node->element;
|
1320
|
+
|
1321
|
+
AddChar( pprint, '<' );
|
1322
|
+
|
1323
|
+
if ( node->type == EndTag )
|
1324
|
+
AddChar( pprint, '/' );
|
1325
|
+
|
1326
|
+
if (s)
|
1327
|
+
{
|
1328
|
+
while (*s)
|
1329
|
+
{
|
1330
|
+
c = (unsigned char)*s;
|
1331
|
+
|
1332
|
+
if (c > 0x7F)
|
1333
|
+
s += TY_(GetUTF8)(s, &c);
|
1334
|
+
else if (uc)
|
1335
|
+
c = TY_(ToUpper)(c);
|
1336
|
+
|
1337
|
+
AddChar(pprint, c);
|
1338
|
+
++s;
|
1339
|
+
}
|
1340
|
+
}
|
1341
|
+
|
1342
|
+
PPrintAttrs( doc, indent, node );
|
1343
|
+
|
1344
|
+
if ( (xmlOut || xhtmlOut) &&
|
1345
|
+
(node->type == StartEndTag || TY_(nodeCMIsEmpty)(node)) )
|
1346
|
+
{
|
1347
|
+
AddChar( pprint, ' ' ); /* Space is NS compatibility hack <br /> */
|
1348
|
+
AddChar( pprint, '/' ); /* Required end tag marker */
|
1349
|
+
}
|
1350
|
+
|
1351
|
+
AddChar( pprint, '>' );
|
1352
|
+
|
1353
|
+
if ( (node->type != StartEndTag || xhtmlOut) && !(mode & PREFORMATTED) )
|
1354
|
+
{
|
1355
|
+
uint wraplen = cfg( doc, TidyWrapLen );
|
1356
|
+
CheckWrapIndent( doc, indent );
|
1357
|
+
|
1358
|
+
if ( indent + pprint->linelen < wraplen )
|
1359
|
+
{
|
1360
|
+
/* wrap after start tag if is <br/> or if it's not inline.
|
1361
|
+
Technically, it would be safe to call only AfterSpace.
|
1362
|
+
However, it would disrupt the existing algorithm. So let's
|
1363
|
+
leave as is. Note that AfterSpace returns true for non inline
|
1364
|
+
elements but can still be false for some <br>. So it has to
|
1365
|
+
stay as well. */
|
1366
|
+
if (!(mode & NOWRAP)
|
1367
|
+
&& (!TY_(nodeCMIsInline)(node) || nodeIsBR(node))
|
1368
|
+
&& AfterSpace(doc->lexer, node))
|
1369
|
+
{
|
1370
|
+
pprint->wraphere = pprint->linelen;
|
1371
|
+
}
|
1372
|
+
}
|
1373
|
+
/* flush the current buffer only if it is known to be safe,
|
1374
|
+
i.e. it will not introduce some spurious white spaces.
|
1375
|
+
See bug #996484 */
|
1376
|
+
else if ( mode & NOWRAP ||
|
1377
|
+
nodeIsBR(node) || AfterSpace(doc->lexer, node))
|
1378
|
+
PCondFlushLine( doc, indent );
|
1379
|
+
}
|
1380
|
+
}
|
1381
|
+
|
1382
|
+
static void PPrintEndTag( TidyDocImpl* doc, uint ARG_UNUSED(mode),
|
1383
|
+
uint ARG_UNUSED(indent), Node *node )
|
1384
|
+
{
|
1385
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1386
|
+
Bool uc = cfgBool( doc, TidyUpperCaseTags );
|
1387
|
+
tmbstr s = node->element;
|
1388
|
+
tchar c;
|
1389
|
+
|
1390
|
+
/*
|
1391
|
+
Netscape ignores SGML standard by not ignoring a
|
1392
|
+
line break before </A> or </U> etc. To avoid rendering
|
1393
|
+
this as an underlined space, I disable line wrapping
|
1394
|
+
before inline end tags by the #if 0 ... #endif
|
1395
|
+
*/
|
1396
|
+
#if 0
|
1397
|
+
if ( !(mode & NOWRAP) )
|
1398
|
+
SetWrap( doc, indent );
|
1399
|
+
#endif
|
1400
|
+
|
1401
|
+
AddString( pprint, "</" );
|
1402
|
+
|
1403
|
+
if (s)
|
1404
|
+
{
|
1405
|
+
while (*s)
|
1406
|
+
{
|
1407
|
+
c = (unsigned char)*s;
|
1408
|
+
|
1409
|
+
if (c > 0x7F)
|
1410
|
+
s += TY_(GetUTF8)(s, &c);
|
1411
|
+
else if (uc)
|
1412
|
+
c = TY_(ToUpper)(c);
|
1413
|
+
|
1414
|
+
AddChar(pprint, c);
|
1415
|
+
++s;
|
1416
|
+
}
|
1417
|
+
}
|
1418
|
+
|
1419
|
+
AddChar( pprint, '>' );
|
1420
|
+
}
|
1421
|
+
|
1422
|
+
static void PPrintComment( TidyDocImpl* doc, uint indent, Node* node )
|
1423
|
+
{
|
1424
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1425
|
+
|
1426
|
+
SetWrap( doc, indent );
|
1427
|
+
AddString( pprint, "<!--" );
|
1428
|
+
|
1429
|
+
#if 0
|
1430
|
+
SetWrap( doc, indent );
|
1431
|
+
#endif
|
1432
|
+
|
1433
|
+
PPrintText(doc, COMMENT, 0, node);
|
1434
|
+
|
1435
|
+
#if 0
|
1436
|
+
SetWrap( doc, indent );
|
1437
|
+
AddString( pprint, "--" );
|
1438
|
+
#endif
|
1439
|
+
|
1440
|
+
AddString(pprint, "--");
|
1441
|
+
AddChar( pprint, '>' );
|
1442
|
+
if ( node->linebreak && node->next )
|
1443
|
+
TY_(PFlushLine)( doc, indent );
|
1444
|
+
}
|
1445
|
+
|
1446
|
+
static void PPrintDocType( TidyDocImpl* doc, uint indent, Node *node )
|
1447
|
+
{
|
1448
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1449
|
+
uint wraplen = cfg( doc, TidyWrapLen );
|
1450
|
+
uint spaces = cfg( doc, TidyIndentSpaces );
|
1451
|
+
AttVal* fpi = TY_(GetAttrByName)(node, "PUBLIC");
|
1452
|
+
AttVal* sys = TY_(GetAttrByName)(node, "SYSTEM");
|
1453
|
+
|
1454
|
+
/* todo: handle non-ASCII characters in FPI / SI / node->element */
|
1455
|
+
|
1456
|
+
SetWrap( doc, indent );
|
1457
|
+
PCondFlushLine( doc, indent );
|
1458
|
+
|
1459
|
+
AddString( pprint, "<!DOCTYPE " );
|
1460
|
+
SetWrap( doc, indent );
|
1461
|
+
if (node->element)
|
1462
|
+
{
|
1463
|
+
AddString(pprint, node->element);
|
1464
|
+
}
|
1465
|
+
|
1466
|
+
if (fpi && fpi->value)
|
1467
|
+
{
|
1468
|
+
AddString(pprint, " PUBLIC ");
|
1469
|
+
AddChar(pprint, fpi->delim);
|
1470
|
+
AddString(pprint, fpi->value);
|
1471
|
+
AddChar(pprint, fpi->delim);
|
1472
|
+
}
|
1473
|
+
|
1474
|
+
if (fpi && fpi->value && sys && sys->value)
|
1475
|
+
{
|
1476
|
+
uint i = pprint->linelen - (TY_(tmbstrlen)(sys->value) + 2) - 1;
|
1477
|
+
if (!(i>0&&TY_(tmbstrlen)(sys->value)+2+i<wraplen&&i<=(spaces?spaces:2)*2))
|
1478
|
+
i = 0;
|
1479
|
+
|
1480
|
+
PCondFlushLine(doc, i);
|
1481
|
+
if (pprint->linelen)
|
1482
|
+
AddChar(pprint, ' ');
|
1483
|
+
}
|
1484
|
+
else if (sys && sys->value)
|
1485
|
+
{
|
1486
|
+
AddString(pprint, " SYSTEM ");
|
1487
|
+
}
|
1488
|
+
|
1489
|
+
if (sys && sys->value)
|
1490
|
+
{
|
1491
|
+
AddChar(pprint, sys->delim);
|
1492
|
+
AddString(pprint, sys->value);
|
1493
|
+
AddChar(pprint, sys->delim);
|
1494
|
+
}
|
1495
|
+
|
1496
|
+
if (node->content)
|
1497
|
+
{
|
1498
|
+
PCondFlushLine(doc, indent);
|
1499
|
+
AddChar(pprint, '[');
|
1500
|
+
PPrintText(doc, CDATA, 0, node->content);
|
1501
|
+
AddChar(pprint, ']');
|
1502
|
+
}
|
1503
|
+
|
1504
|
+
SetWrap( doc, 0 );
|
1505
|
+
AddChar( pprint, '>' );
|
1506
|
+
PCondFlushLine( doc, indent );
|
1507
|
+
}
|
1508
|
+
|
1509
|
+
static void PPrintPI( TidyDocImpl* doc, uint indent, Node *node )
|
1510
|
+
{
|
1511
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1512
|
+
tchar c;
|
1513
|
+
tmbstr s;
|
1514
|
+
|
1515
|
+
SetWrap( doc, indent );
|
1516
|
+
AddString( pprint, "<?" );
|
1517
|
+
|
1518
|
+
s = node->element;
|
1519
|
+
|
1520
|
+
while (s && *s)
|
1521
|
+
{
|
1522
|
+
c = (unsigned char)*s;
|
1523
|
+
if (c > 0x7F)
|
1524
|
+
s += TY_(GetUTF8)(s, &c);
|
1525
|
+
AddChar(pprint, c);
|
1526
|
+
++s;
|
1527
|
+
}
|
1528
|
+
|
1529
|
+
/* set CDATA to pass < and > unescaped */
|
1530
|
+
PPrintText( doc, CDATA, indent, node );
|
1531
|
+
|
1532
|
+
if (cfgBool(doc, TidyXmlOut) ||
|
1533
|
+
cfgBool(doc, TidyXhtmlOut) || node->closed)
|
1534
|
+
AddChar( pprint, '?' );
|
1535
|
+
|
1536
|
+
AddChar( pprint, '>' );
|
1537
|
+
PCondFlushLine( doc, indent );
|
1538
|
+
}
|
1539
|
+
|
1540
|
+
static void PPrintXmlDecl( TidyDocImpl* doc, uint indent, Node *node )
|
1541
|
+
{
|
1542
|
+
AttVal* att;
|
1543
|
+
uint saveWrap;
|
1544
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1545
|
+
Bool ucAttrs;
|
1546
|
+
SetWrap( doc, indent );
|
1547
|
+
saveWrap = WrapOff( doc );
|
1548
|
+
|
1549
|
+
/* no case translation for XML declaration pseudo attributes */
|
1550
|
+
ucAttrs = cfgBool(doc, TidyUpperCaseAttrs);
|
1551
|
+
TY_(SetOptionBool)(doc, TidyUpperCaseAttrs, no);
|
1552
|
+
|
1553
|
+
AddString( pprint, "<?xml" );
|
1554
|
+
|
1555
|
+
/* Force order of XML declaration attributes */
|
1556
|
+
/* PPrintAttrs( doc, indent, node ); */
|
1557
|
+
if ( NULL != (att = TY_(AttrGetById)(node, TidyAttr_VERSION)) )
|
1558
|
+
PPrintAttribute( doc, indent, node, att );
|
1559
|
+
if ( NULL != (att = TY_(AttrGetById)(node, TidyAttr_ENCODING)) )
|
1560
|
+
PPrintAttribute( doc, indent, node, att );
|
1561
|
+
if ( NULL != (att = TY_(GetAttrByName)(node, "standalone")) )
|
1562
|
+
PPrintAttribute( doc, indent, node, att );
|
1563
|
+
|
1564
|
+
/* restore old config value */
|
1565
|
+
TY_(SetOptionBool)(doc, TidyUpperCaseAttrs, ucAttrs);
|
1566
|
+
|
1567
|
+
if ( node->end <= 0 || doc->lexer->lexbuf[node->end - 1] != '?' )
|
1568
|
+
AddChar( pprint, '?' );
|
1569
|
+
AddChar( pprint, '>' );
|
1570
|
+
WrapOn( doc, saveWrap );
|
1571
|
+
TY_(PFlushLine)( doc, indent );
|
1572
|
+
}
|
1573
|
+
|
1574
|
+
/* note ASP and JSTE share <% ... %> syntax */
|
1575
|
+
static void PPrintAsp( TidyDocImpl* doc, uint indent, Node *node )
|
1576
|
+
{
|
1577
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1578
|
+
Bool wrapAsp = cfgBool( doc, TidyWrapAsp );
|
1579
|
+
Bool wrapJste = cfgBool( doc, TidyWrapJste );
|
1580
|
+
uint saveWrap = WrapOffCond( doc, !wrapAsp || !wrapJste );
|
1581
|
+
|
1582
|
+
#if 0
|
1583
|
+
SetWrap( doc, indent );
|
1584
|
+
#endif
|
1585
|
+
AddString( pprint, "<%" );
|
1586
|
+
PPrintText( doc, (wrapAsp ? CDATA : COMMENT), indent, node );
|
1587
|
+
AddString( pprint, "%>" );
|
1588
|
+
|
1589
|
+
/* PCondFlushLine( doc, indent ); */
|
1590
|
+
WrapOn( doc, saveWrap );
|
1591
|
+
}
|
1592
|
+
|
1593
|
+
/* JSTE also supports <# ... #> syntax */
|
1594
|
+
static void PPrintJste( TidyDocImpl* doc, uint indent, Node *node )
|
1595
|
+
{
|
1596
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1597
|
+
Bool wrapAsp = cfgBool( doc, TidyWrapAsp );
|
1598
|
+
uint saveWrap = WrapOffCond( doc, !wrapAsp );
|
1599
|
+
|
1600
|
+
AddString( pprint, "<#" );
|
1601
|
+
PPrintText( doc, (cfgBool(doc, TidyWrapJste) ? CDATA : COMMENT),
|
1602
|
+
indent, node );
|
1603
|
+
AddString( pprint, "#>" );
|
1604
|
+
|
1605
|
+
/* PCondFlushLine( doc, indent ); */
|
1606
|
+
WrapOn( doc, saveWrap );
|
1607
|
+
}
|
1608
|
+
|
1609
|
+
/* PHP is based on XML processing instructions */
|
1610
|
+
static void PPrintPhp( TidyDocImpl* doc, uint indent, Node *node )
|
1611
|
+
{
|
1612
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1613
|
+
Bool wrapPhp = cfgBool( doc, TidyWrapPhp );
|
1614
|
+
uint saveWrap = WrapOffCond( doc, !wrapPhp );
|
1615
|
+
#if 0
|
1616
|
+
SetWrap( doc, indent );
|
1617
|
+
#endif
|
1618
|
+
|
1619
|
+
AddString( pprint, "<?" );
|
1620
|
+
PPrintText( doc, (wrapPhp ? CDATA : COMMENT),
|
1621
|
+
indent, node );
|
1622
|
+
AddString( pprint, "?>" );
|
1623
|
+
|
1624
|
+
/* PCondFlushLine( doc, indent ); */
|
1625
|
+
WrapOn( doc, saveWrap );
|
1626
|
+
}
|
1627
|
+
|
1628
|
+
static void PPrintCDATA( TidyDocImpl* doc, uint indent, Node *node )
|
1629
|
+
{
|
1630
|
+
uint saveWrap;
|
1631
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1632
|
+
Bool indentCData = cfgBool( doc, TidyIndentCdata );
|
1633
|
+
if ( !indentCData )
|
1634
|
+
indent = 0;
|
1635
|
+
|
1636
|
+
PCondFlushLine( doc, indent );
|
1637
|
+
saveWrap = WrapOff( doc ); /* disable wrapping */
|
1638
|
+
|
1639
|
+
AddString( pprint, "<![CDATA[" );
|
1640
|
+
PPrintText( doc, COMMENT, indent, node );
|
1641
|
+
AddString( pprint, "]]>" );
|
1642
|
+
|
1643
|
+
PCondFlushLine( doc, indent );
|
1644
|
+
WrapOn( doc, saveWrap ); /* restore wrapping */
|
1645
|
+
}
|
1646
|
+
|
1647
|
+
static void PPrintSection( TidyDocImpl* doc, uint indent, Node *node )
|
1648
|
+
{
|
1649
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1650
|
+
Bool wrapSect = cfgBool( doc, TidyWrapSection );
|
1651
|
+
uint saveWrap = WrapOffCond( doc, !wrapSect );
|
1652
|
+
#if 0
|
1653
|
+
SetWrap( doc, indent );
|
1654
|
+
#endif
|
1655
|
+
|
1656
|
+
AddString( pprint, "<![" );
|
1657
|
+
PPrintText( doc, (wrapSect ? CDATA : COMMENT),
|
1658
|
+
indent, node );
|
1659
|
+
AddString( pprint, "]>" );
|
1660
|
+
|
1661
|
+
/* PCondFlushLine( doc, indent ); */
|
1662
|
+
WrapOn( doc, saveWrap );
|
1663
|
+
}
|
1664
|
+
|
1665
|
+
|
1666
|
+
#if 0
|
1667
|
+
/*
|
1668
|
+
** Print script and style elements. For XHTML, wrap the content as follows:
|
1669
|
+
**
|
1670
|
+
** JavaScript:
|
1671
|
+
** //<![CDATA[
|
1672
|
+
** content
|
1673
|
+
** //]]>
|
1674
|
+
** VBScript:
|
1675
|
+
** '<![CDATA[
|
1676
|
+
** content
|
1677
|
+
** ']]>
|
1678
|
+
** CSS:
|
1679
|
+
** / *<![CDATA[* / Extra spaces to keep compiler happy
|
1680
|
+
** content
|
1681
|
+
** / *]]>* /
|
1682
|
+
** other:
|
1683
|
+
** <![CDATA[
|
1684
|
+
** content
|
1685
|
+
** ]]>
|
1686
|
+
*/
|
1687
|
+
#endif
|
1688
|
+
|
1689
|
+
static ctmbstr CDATA_START = "<![CDATA[";
|
1690
|
+
static ctmbstr CDATA_END = "]]>";
|
1691
|
+
static ctmbstr JS_COMMENT_START = "//";
|
1692
|
+
static ctmbstr JS_COMMENT_END = "";
|
1693
|
+
static ctmbstr VB_COMMENT_START = "\'";
|
1694
|
+
static ctmbstr VB_COMMENT_END = "";
|
1695
|
+
static ctmbstr CSS_COMMENT_START = "/*";
|
1696
|
+
static ctmbstr CSS_COMMENT_END = "*/";
|
1697
|
+
static ctmbstr DEFAULT_COMMENT_START = "";
|
1698
|
+
static ctmbstr DEFAULT_COMMENT_END = "";
|
1699
|
+
|
1700
|
+
static Bool InsideHead( TidyDocImpl* doc, Node *node )
|
1701
|
+
{
|
1702
|
+
if ( nodeIsHEAD(node) )
|
1703
|
+
return yes;
|
1704
|
+
|
1705
|
+
if ( node->parent != NULL )
|
1706
|
+
return InsideHead( doc, node->parent );
|
1707
|
+
|
1708
|
+
return no;
|
1709
|
+
}
|
1710
|
+
|
1711
|
+
/* Is text node and already ends w/ a newline?
|
1712
|
+
|
1713
|
+
Used to pretty print CDATA/PRE text content.
|
1714
|
+
If it already ends on a newline, it is not
|
1715
|
+
necessary to print another before printing end tag.
|
1716
|
+
*/
|
1717
|
+
static int TextEndsWithNewline(Lexer *lexer, Node *node, uint mode )
|
1718
|
+
{
|
1719
|
+
if ( (mode & (CDATA|COMMENT)) && TY_(nodeIsText)(node) && node->end > node->start )
|
1720
|
+
{
|
1721
|
+
uint ch, ix = node->end - 1;
|
1722
|
+
/* Skip non-newline whitespace. */
|
1723
|
+
while ( ix >= node->start && (ch = (lexer->lexbuf[ix] & 0xff))
|
1724
|
+
&& ( ch == ' ' || ch == '\t' || ch == '\r' ) )
|
1725
|
+
--ix;
|
1726
|
+
|
1727
|
+
if ( lexer->lexbuf[ ix ] == '\n' )
|
1728
|
+
return node->end - ix - 1; /* #543262 tidy eats all memory */
|
1729
|
+
}
|
1730
|
+
return -1;
|
1731
|
+
}
|
1732
|
+
|
1733
|
+
static int TextStartsWithWhitespace( Lexer *lexer, Node *node, uint start, uint mode )
|
1734
|
+
{
|
1735
|
+
assert( node != NULL );
|
1736
|
+
if ( (mode & (CDATA|COMMENT)) && TY_(nodeIsText)(node) && node->end > node->start && start >= node->start )
|
1737
|
+
{
|
1738
|
+
uint ch, ix = start;
|
1739
|
+
/* Skip whitespace. */
|
1740
|
+
while ( ix < node->end && (ch = (lexer->lexbuf[ix] & 0xff))
|
1741
|
+
&& ( ch==' ' || ch=='\t' || ch=='\r' ) )
|
1742
|
+
++ix;
|
1743
|
+
|
1744
|
+
if ( ix > start )
|
1745
|
+
return ix - start;
|
1746
|
+
}
|
1747
|
+
return -1;
|
1748
|
+
}
|
1749
|
+
|
1750
|
+
static Bool HasCDATA( Lexer* lexer, Node* node )
|
1751
|
+
{
|
1752
|
+
/* Scan forward through the textarray. Since the characters we're
|
1753
|
+
** looking for are < 0x7f, we don't have to do any UTF-8 decoding.
|
1754
|
+
*/
|
1755
|
+
ctmbstr start = lexer->lexbuf + node->start;
|
1756
|
+
int len = node->end - node->start + 1;
|
1757
|
+
|
1758
|
+
if ( node->type != TextNode )
|
1759
|
+
return no;
|
1760
|
+
|
1761
|
+
return ( NULL != TY_(tmbsubstrn)( start, len, CDATA_START ));
|
1762
|
+
}
|
1763
|
+
|
1764
|
+
|
1765
|
+
static
|
1766
|
+
void PPrintScriptStyle( TidyDocImpl* doc, uint mode, uint indent, Node *node )
|
1767
|
+
{
|
1768
|
+
TidyPrintImpl* pprint = &doc->pprint;
|
1769
|
+
Node* content;
|
1770
|
+
ctmbstr commentStart = DEFAULT_COMMENT_START;
|
1771
|
+
ctmbstr commentEnd = DEFAULT_COMMENT_END;
|
1772
|
+
Bool hasCData = no;
|
1773
|
+
int contentIndent = -1;
|
1774
|
+
Bool xhtmlOut = cfgBool( doc, TidyXhtmlOut );
|
1775
|
+
|
1776
|
+
if ( InsideHead(doc, node) )
|
1777
|
+
TY_(PFlushLine)( doc, indent );
|
1778
|
+
|
1779
|
+
PPrintTag( doc, mode, indent, node );
|
1780
|
+
|
1781
|
+
/* use zero indent here, see http://tidy.sf.net/bug/729972 */
|
1782
|
+
TY_(PFlushLine)(doc, 0);
|
1783
|
+
|
1784
|
+
if ( xhtmlOut && node->content != NULL )
|
1785
|
+
{
|
1786
|
+
AttVal* type = attrGetTYPE(node);
|
1787
|
+
|
1788
|
+
if (AttrValueIs(type, "text/javascript"))
|
1789
|
+
{
|
1790
|
+
commentStart = JS_COMMENT_START;
|
1791
|
+
commentEnd = JS_COMMENT_END;
|
1792
|
+
}
|
1793
|
+
else if (AttrValueIs(type, "text/css"))
|
1794
|
+
{
|
1795
|
+
commentStart = CSS_COMMENT_START;
|
1796
|
+
commentEnd = CSS_COMMENT_END;
|
1797
|
+
}
|
1798
|
+
else if (AttrValueIs(type, "text/vbscript"))
|
1799
|
+
{
|
1800
|
+
commentStart = VB_COMMENT_START;
|
1801
|
+
commentEnd = VB_COMMENT_END;
|
1802
|
+
}
|
1803
|
+
|
1804
|
+
hasCData = HasCDATA(doc->lexer, node->content);
|
1805
|
+
|
1806
|
+
if (!hasCData)
|
1807
|
+
{
|
1808
|
+
uint saveWrap = WrapOff( doc );
|
1809
|
+
|
1810
|
+
AddString( pprint, commentStart );
|
1811
|
+
AddString( pprint, CDATA_START );
|
1812
|
+
AddString( pprint, commentEnd );
|
1813
|
+
PCondFlushLine( doc, indent );
|
1814
|
+
|
1815
|
+
WrapOn( doc, saveWrap );
|
1816
|
+
}
|
1817
|
+
}
|
1818
|
+
|
1819
|
+
for ( content = node->content;
|
1820
|
+
content != NULL;
|
1821
|
+
content = content->next )
|
1822
|
+
{
|
1823
|
+
/*
|
1824
|
+
This is a bit odd, with the current code there can only
|
1825
|
+
be one child and the only caller of this function defines
|
1826
|
+
all these modes already...
|
1827
|
+
*/
|
1828
|
+
TY_(PPrintTree)( doc, (mode | PREFORMATTED | NOWRAP | CDATA),
|
1829
|
+
indent, content );
|
1830
|
+
|
1831
|
+
if ( content == node->last )
|
1832
|
+
contentIndent = TextEndsWithNewline( doc->lexer, content, CDATA );
|
1833
|
+
}
|
1834
|
+
|
1835
|
+
if ( contentIndent < 0 )
|
1836
|
+
{
|
1837
|
+
PCondFlushLine( doc, indent );
|
1838
|
+
contentIndent = 0;
|
1839
|
+
}
|
1840
|
+
|
1841
|
+
if ( xhtmlOut && node->content != NULL )
|
1842
|
+
{
|
1843
|
+
if ( ! hasCData )
|
1844
|
+
{
|
1845
|
+
uint saveWrap = WrapOff( doc );
|
1846
|
+
|
1847
|
+
AddString( pprint, commentStart );
|
1848
|
+
AddString( pprint, CDATA_END );
|
1849
|
+
AddString( pprint, commentEnd );
|
1850
|
+
|
1851
|
+
WrapOn( doc, saveWrap );
|
1852
|
+
PCondFlushLine( doc, indent );
|
1853
|
+
}
|
1854
|
+
}
|
1855
|
+
|
1856
|
+
if ( node->content && pprint->indent[ 0 ].spaces != (int)indent )
|
1857
|
+
{
|
1858
|
+
pprint->indent[ 0 ].spaces = indent;
|
1859
|
+
}
|
1860
|
+
PPrintEndTag( doc, mode, indent, node );
|
1861
|
+
if ( cfgAutoBool(doc, TidyIndentContent) == TidyNoState
|
1862
|
+
&& node->next != NULL &&
|
1863
|
+
!( TY_(nodeHasCM)(node, CM_INLINE) || TY_(nodeIsText)(node) ) )
|
1864
|
+
TY_(PFlushLine)( doc, indent );
|
1865
|
+
}
|
1866
|
+
|
1867
|
+
|
1868
|
+
|
1869
|
+
static Bool ShouldIndent( TidyDocImpl* doc, Node *node )
|
1870
|
+
{
|
1871
|
+
TidyTriState indentContent = cfgAutoBool( doc, TidyIndentContent );
|
1872
|
+
if ( indentContent == TidyNoState )
|
1873
|
+
return no;
|
1874
|
+
|
1875
|
+
if ( nodeIsTEXTAREA(node) )
|
1876
|
+
return no;
|
1877
|
+
|
1878
|
+
if ( indentContent == TidyAutoState )
|
1879
|
+
{
|
1880
|
+
if ( node->content && TY_(nodeHasCM)(node, CM_NO_INDENT) )
|
1881
|
+
{
|
1882
|
+
for ( node = node->content; node; node = node->next )
|
1883
|
+
if ( TY_(nodeHasCM)(node, CM_BLOCK) )
|
1884
|
+
return yes;
|
1885
|
+
return no;
|
1886
|
+
}
|
1887
|
+
|
1888
|
+
if ( TY_(nodeHasCM)(node, CM_HEADING) )
|
1889
|
+
return no;
|
1890
|
+
|
1891
|
+
if ( nodeIsHTML(node) )
|
1892
|
+
return no;
|
1893
|
+
|
1894
|
+
if ( nodeIsP(node) )
|
1895
|
+
return no;
|
1896
|
+
|
1897
|
+
if ( nodeIsTITLE(node) )
|
1898
|
+
return no;
|
1899
|
+
|
1900
|
+
/* http://tidy.sf.net/issue/1610888
|
1901
|
+
Indenting <div><img /></div> produces spurious lines with IE 6.x */
|
1902
|
+
if ( nodeIsDIV(node) && node->last && nodeIsIMG(node->last) )
|
1903
|
+
return no;
|
1904
|
+
}
|
1905
|
+
|
1906
|
+
if ( TY_(nodeHasCM)(node, CM_FIELD | CM_OBJECT) )
|
1907
|
+
return yes;
|
1908
|
+
|
1909
|
+
if ( nodeIsMAP(node) )
|
1910
|
+
return yes;
|
1911
|
+
|
1912
|
+
return ( !TY_(nodeHasCM)( node, CM_INLINE ) && node->content );
|
1913
|
+
}
|
1914
|
+
|
1915
|
+
/*
|
1916
|
+
Feature request #434940 - fix by Dave Raggett/Ignacio Vazquez-Abrams 21 Jun 01
|
1917
|
+
print just the content of the body element.
|
1918
|
+
useful when you want to reuse material from
|
1919
|
+
other documents.
|
1920
|
+
|
1921
|
+
-- Sebastiano Vigna <vigna@dsi.unimi.it>
|
1922
|
+
*/
|
1923
|
+
void TY_(PrintBody)( TidyDocImpl* doc )
|
1924
|
+
{
|
1925
|
+
Node *node = TY_(FindBody)( doc );
|
1926
|
+
|
1927
|
+
if ( node )
|
1928
|
+
{
|
1929
|
+
for ( node = node->content; node != NULL; node = node->next )
|
1930
|
+
TY_(PPrintTree)( doc, NORMAL, 0, node );
|
1931
|
+
}
|
1932
|
+
}
|
1933
|
+
|
1934
|
+
void TY_(PPrintTree)( TidyDocImpl* doc, uint mode, uint indent, Node *node )
|
1935
|
+
{
|
1936
|
+
Node *content, *last;
|
1937
|
+
uint spaces = cfg( doc, TidyIndentSpaces );
|
1938
|
+
Bool xhtml = cfgBool( doc, TidyXhtmlOut );
|
1939
|
+
|
1940
|
+
if ( node == NULL )
|
1941
|
+
return;
|
1942
|
+
|
1943
|
+
if (node->type == TextNode)
|
1944
|
+
{
|
1945
|
+
PPrintText( doc, mode, indent, node );
|
1946
|
+
}
|
1947
|
+
else if ( node->type == CommentTag )
|
1948
|
+
{
|
1949
|
+
PPrintComment( doc, indent, node );
|
1950
|
+
}
|
1951
|
+
else if ( node->type == RootNode )
|
1952
|
+
{
|
1953
|
+
for ( content = node->content; content; content = content->next )
|
1954
|
+
TY_(PPrintTree)( doc, mode, indent, content );
|
1955
|
+
}
|
1956
|
+
else if ( node->type == DocTypeTag )
|
1957
|
+
PPrintDocType( doc, indent, node );
|
1958
|
+
else if ( node->type == ProcInsTag)
|
1959
|
+
PPrintPI( doc, indent, node );
|
1960
|
+
else if ( node->type == XmlDecl)
|
1961
|
+
PPrintXmlDecl( doc, indent, node );
|
1962
|
+
else if ( node->type == CDATATag)
|
1963
|
+
PPrintCDATA( doc, indent, node );
|
1964
|
+
else if ( node->type == SectionTag)
|
1965
|
+
PPrintSection( doc, indent, node );
|
1966
|
+
else if ( node->type == AspTag)
|
1967
|
+
PPrintAsp( doc, indent, node );
|
1968
|
+
else if ( node->type == JsteTag)
|
1969
|
+
PPrintJste( doc, indent, node );
|
1970
|
+
else if ( node->type == PhpTag)
|
1971
|
+
PPrintPhp( doc, indent, node );
|
1972
|
+
else if ( TY_(nodeCMIsEmpty)(node) ||
|
1973
|
+
(node->type == StartEndTag && !xhtml) )
|
1974
|
+
{
|
1975
|
+
if ( ! TY_(nodeHasCM)(node, CM_INLINE) )
|
1976
|
+
PCondFlushLine( doc, indent );
|
1977
|
+
|
1978
|
+
if ( nodeIsBR(node) && node->prev &&
|
1979
|
+
!(nodeIsBR(node->prev) || (mode & PREFORMATTED)) &&
|
1980
|
+
cfgBool(doc, TidyBreakBeforeBR) )
|
1981
|
+
TY_(PFlushLine)( doc, indent );
|
1982
|
+
|
1983
|
+
if ( nodeIsHR(node) )
|
1984
|
+
{
|
1985
|
+
/* insert extra newline for classic formatting */
|
1986
|
+
Bool classic = cfgBool( doc, TidyVertSpace );
|
1987
|
+
if (classic && node->parent && node->parent->content != node)
|
1988
|
+
{
|
1989
|
+
TY_(PFlushLine)( doc, indent );
|
1990
|
+
}
|
1991
|
+
}
|
1992
|
+
|
1993
|
+
PPrintTag( doc, mode, indent, node );
|
1994
|
+
|
1995
|
+
if (node->next)
|
1996
|
+
{
|
1997
|
+
if (nodeIsPARAM(node) || nodeIsAREA(node))
|
1998
|
+
PCondFlushLine(doc, indent);
|
1999
|
+
else if ((nodeIsBR(node) && !(mode & PREFORMATTED))
|
2000
|
+
|| nodeIsHR(node))
|
2001
|
+
TY_(PFlushLine)(doc, indent);
|
2002
|
+
}
|
2003
|
+
}
|
2004
|
+
else /* some kind of container element */
|
2005
|
+
{
|
2006
|
+
if ( node->type == StartEndTag )
|
2007
|
+
node->type = StartTag;
|
2008
|
+
|
2009
|
+
if ( node->tag &&
|
2010
|
+
(node->tag->parser == TY_(ParsePre) || nodeIsTEXTAREA(node)) )
|
2011
|
+
{
|
2012
|
+
Bool classic = cfgBool( doc, TidyVertSpace );
|
2013
|
+
uint indprev = indent;
|
2014
|
+
PCondFlushLine( doc, indent );
|
2015
|
+
|
2016
|
+
PCondFlushLine( doc, indent );
|
2017
|
+
|
2018
|
+
/* insert extra newline for classic formatting */
|
2019
|
+
if (classic && node->parent && node->parent->content != node)
|
2020
|
+
{
|
2021
|
+
TY_(PFlushLine)( doc, indent );
|
2022
|
+
}
|
2023
|
+
PPrintTag( doc, mode, indent, node );
|
2024
|
+
|
2025
|
+
indent = 0;
|
2026
|
+
TY_(PFlushLine)( doc, indent );
|
2027
|
+
|
2028
|
+
for ( content = node->content; content; content = content->next )
|
2029
|
+
{
|
2030
|
+
TY_(PPrintTree)( doc, (mode | PREFORMATTED | NOWRAP),
|
2031
|
+
indent, content );
|
2032
|
+
}
|
2033
|
+
PCondFlushLine( doc, indent );
|
2034
|
+
indent = indprev;
|
2035
|
+
PPrintEndTag( doc, mode, indent, node );
|
2036
|
+
|
2037
|
+
if ( cfgAutoBool(doc, TidyIndentContent) == TidyNoState
|
2038
|
+
&& node->next != NULL )
|
2039
|
+
TY_(PFlushLine)( doc, indent );
|
2040
|
+
}
|
2041
|
+
else if ( nodeIsSTYLE(node) || nodeIsSCRIPT(node) )
|
2042
|
+
{
|
2043
|
+
PPrintScriptStyle( doc, (mode | PREFORMATTED | NOWRAP | CDATA),
|
2044
|
+
indent, node );
|
2045
|
+
}
|
2046
|
+
else if ( TY_(nodeCMIsInline)(node) )
|
2047
|
+
{
|
2048
|
+
if ( cfgBool(doc, TidyMakeClean) )
|
2049
|
+
{
|
2050
|
+
/* replace <nobr>...</nobr> by or   etc. */
|
2051
|
+
if ( nodeIsNOBR(node) )
|
2052
|
+
{
|
2053
|
+
for ( content = node->content;
|
2054
|
+
content != NULL;
|
2055
|
+
content = content->next)
|
2056
|
+
TY_(PPrintTree)( doc, mode|NOWRAP, indent, content );
|
2057
|
+
return;
|
2058
|
+
}
|
2059
|
+
}
|
2060
|
+
|
2061
|
+
/* otherwise a normal inline element */
|
2062
|
+
PPrintTag( doc, mode, indent, node );
|
2063
|
+
|
2064
|
+
/* indent content for SELECT, TEXTAREA, MAP, OBJECT and APPLET */
|
2065
|
+
if ( ShouldIndent(doc, node) )
|
2066
|
+
{
|
2067
|
+
indent += spaces;
|
2068
|
+
PCondFlushLine( doc, indent );
|
2069
|
+
|
2070
|
+
for ( content = node->content;
|
2071
|
+
content != NULL;
|
2072
|
+
content = content->next )
|
2073
|
+
TY_(PPrintTree)( doc, mode, indent, content );
|
2074
|
+
|
2075
|
+
indent -= spaces;
|
2076
|
+
PCondFlushLine( doc, indent );
|
2077
|
+
/* PCondFlushLine( doc, indent ); */
|
2078
|
+
}
|
2079
|
+
else
|
2080
|
+
{
|
2081
|
+
for ( content = node->content;
|
2082
|
+
content != NULL;
|
2083
|
+
content = content->next )
|
2084
|
+
TY_(PPrintTree)( doc, mode, indent, content );
|
2085
|
+
}
|
2086
|
+
PPrintEndTag( doc, mode, indent, node );
|
2087
|
+
}
|
2088
|
+
else /* other tags */
|
2089
|
+
{
|
2090
|
+
Bool indcont = ( cfgAutoBool(doc, TidyIndentContent) != TidyNoState );
|
2091
|
+
Bool indsmart = ( cfgAutoBool(doc, TidyIndentContent) == TidyAutoState );
|
2092
|
+
Bool hideend = cfgBool( doc, TidyHideEndTags );
|
2093
|
+
Bool classic = cfgBool( doc, TidyVertSpace );
|
2094
|
+
uint contentIndent = indent;
|
2095
|
+
|
2096
|
+
/* insert extra newline for classic formatting */
|
2097
|
+
if (classic && node->parent && node->parent->content != node && !nodeIsHTML(node))
|
2098
|
+
{
|
2099
|
+
TY_(PFlushLine)( doc, indent );
|
2100
|
+
}
|
2101
|
+
|
2102
|
+
if ( ShouldIndent(doc, node) )
|
2103
|
+
contentIndent += spaces;
|
2104
|
+
|
2105
|
+
PCondFlushLine( doc, indent );
|
2106
|
+
if ( indsmart && node->prev != NULL )
|
2107
|
+
TY_(PFlushLine)( doc, indent );
|
2108
|
+
|
2109
|
+
/* do not omit elements with attributes */
|
2110
|
+
if ( !hideend || !TY_(nodeHasCM)(node, CM_OMITST) ||
|
2111
|
+
node->attributes != NULL )
|
2112
|
+
{
|
2113
|
+
PPrintTag( doc, mode, indent, node );
|
2114
|
+
|
2115
|
+
if ( ShouldIndent(doc, node) )
|
2116
|
+
{
|
2117
|
+
/* fix for bug 530791, don't wrap after */
|
2118
|
+
/* <li> if first child is text node */
|
2119
|
+
if (!(nodeIsLI(node) && TY_(nodeIsText)(node->content)))
|
2120
|
+
PCondFlushLine( doc, contentIndent );
|
2121
|
+
}
|
2122
|
+
else if ( TY_(nodeHasCM)(node, CM_HTML) || nodeIsNOFRAMES(node) ||
|
2123
|
+
(TY_(nodeHasCM)(node, CM_HEAD) && !nodeIsTITLE(node)) )
|
2124
|
+
TY_(PFlushLine)( doc, contentIndent );
|
2125
|
+
}
|
2126
|
+
|
2127
|
+
last = NULL;
|
2128
|
+
for ( content = node->content; content; content = content->next )
|
2129
|
+
{
|
2130
|
+
/* kludge for naked text before block level tag */
|
2131
|
+
if ( last && !indcont && TY_(nodeIsText)(last) &&
|
2132
|
+
content->tag && !TY_(nodeHasCM)(content, CM_INLINE) )
|
2133
|
+
{
|
2134
|
+
/* TY_(PFlushLine)(fout, indent); */
|
2135
|
+
TY_(PFlushLine)( doc, contentIndent );
|
2136
|
+
}
|
2137
|
+
|
2138
|
+
TY_(PPrintTree)( doc, mode, contentIndent, content );
|
2139
|
+
last = content;
|
2140
|
+
}
|
2141
|
+
|
2142
|
+
/* don't flush line for td and th */
|
2143
|
+
if ( ShouldIndent(doc, node) ||
|
2144
|
+
( !hideend &&
|
2145
|
+
( TY_(nodeHasCM)(node, CM_HTML) ||
|
2146
|
+
nodeIsNOFRAMES(node) ||
|
2147
|
+
(TY_(nodeHasCM)(node, CM_HEAD) && !nodeIsTITLE(node))
|
2148
|
+
)
|
2149
|
+
)
|
2150
|
+
)
|
2151
|
+
{
|
2152
|
+
PCondFlushLine( doc, indent );
|
2153
|
+
if ( !hideend || !TY_(nodeHasCM)(node, CM_OPT) )
|
2154
|
+
{
|
2155
|
+
PPrintEndTag( doc, mode, indent, node );
|
2156
|
+
/* TY_(PFlushLine)( doc, indent ); */
|
2157
|
+
}
|
2158
|
+
}
|
2159
|
+
else
|
2160
|
+
{
|
2161
|
+
if ( !hideend || !TY_(nodeHasCM)(node, CM_OPT) )
|
2162
|
+
{
|
2163
|
+
/* newline before endtag for classic formatting */
|
2164
|
+
if ( classic && !HasMixedContent(node) )
|
2165
|
+
TY_(PFlushLine)( doc, indent );
|
2166
|
+
PPrintEndTag( doc, mode, indent, node );
|
2167
|
+
}
|
2168
|
+
}
|
2169
|
+
|
2170
|
+
if (!indcont && !hideend && !nodeIsHTML(node) && !classic)
|
2171
|
+
TY_(PFlushLine)( doc, indent );
|
2172
|
+
else if (classic && node->next != NULL && TY_(nodeHasCM)(node, CM_LIST|CM_DEFLIST|CM_TABLE|CM_BLOCK/*|CM_HEADING*/))
|
2173
|
+
TY_(PFlushLine)( doc, indent );
|
2174
|
+
}
|
2175
|
+
}
|
2176
|
+
}
|
2177
|
+
|
2178
|
+
void TY_(PPrintXMLTree)( TidyDocImpl* doc, uint mode, uint indent, Node *node )
|
2179
|
+
{
|
2180
|
+
Bool xhtmlOut = cfgBool( doc, TidyXhtmlOut );
|
2181
|
+
if (node == NULL)
|
2182
|
+
return;
|
2183
|
+
|
2184
|
+
if ( node->type == TextNode)
|
2185
|
+
{
|
2186
|
+
PPrintText( doc, mode, indent, node );
|
2187
|
+
}
|
2188
|
+
else if ( node->type == CommentTag )
|
2189
|
+
{
|
2190
|
+
PCondFlushLine( doc, indent );
|
2191
|
+
PPrintComment( doc, indent, node);
|
2192
|
+
/* PCondFlushLine( doc, 0 ); */
|
2193
|
+
}
|
2194
|
+
else if ( node->type == RootNode )
|
2195
|
+
{
|
2196
|
+
Node *content;
|
2197
|
+
for ( content = node->content;
|
2198
|
+
content != NULL;
|
2199
|
+
content = content->next )
|
2200
|
+
TY_(PPrintXMLTree)( doc, mode, indent, content );
|
2201
|
+
}
|
2202
|
+
else if ( node->type == DocTypeTag )
|
2203
|
+
PPrintDocType( doc, indent, node );
|
2204
|
+
else if ( node->type == ProcInsTag )
|
2205
|
+
PPrintPI( doc, indent, node );
|
2206
|
+
else if ( node->type == XmlDecl )
|
2207
|
+
PPrintXmlDecl( doc, indent, node );
|
2208
|
+
else if ( node->type == CDATATag )
|
2209
|
+
PPrintCDATA( doc, indent, node );
|
2210
|
+
else if ( node->type == SectionTag )
|
2211
|
+
PPrintSection( doc, indent, node );
|
2212
|
+
else if ( node->type == AspTag )
|
2213
|
+
PPrintAsp( doc, indent, node );
|
2214
|
+
else if ( node->type == JsteTag)
|
2215
|
+
PPrintJste( doc, indent, node );
|
2216
|
+
else if ( node->type == PhpTag)
|
2217
|
+
PPrintPhp( doc, indent, node );
|
2218
|
+
else if ( TY_(nodeHasCM)(node, CM_EMPTY) ||
|
2219
|
+
(node->type == StartEndTag && !xhtmlOut) )
|
2220
|
+
{
|
2221
|
+
PCondFlushLine( doc, indent );
|
2222
|
+
PPrintTag( doc, mode, indent, node );
|
2223
|
+
/* TY_(PFlushLine)( doc, indent ); */
|
2224
|
+
}
|
2225
|
+
else /* some kind of container element */
|
2226
|
+
{
|
2227
|
+
uint spaces = cfg( doc, TidyIndentSpaces );
|
2228
|
+
Node *content;
|
2229
|
+
Bool mixed = no;
|
2230
|
+
uint cindent;
|
2231
|
+
|
2232
|
+
for ( content = node->content; content; content = content->next )
|
2233
|
+
{
|
2234
|
+
if ( TY_(nodeIsText)(content) )
|
2235
|
+
{
|
2236
|
+
mixed = yes;
|
2237
|
+
break;
|
2238
|
+
}
|
2239
|
+
}
|
2240
|
+
|
2241
|
+
PCondFlushLine( doc, indent );
|
2242
|
+
|
2243
|
+
if ( TY_(XMLPreserveWhiteSpace)(doc, node) )
|
2244
|
+
{
|
2245
|
+
indent = 0;
|
2246
|
+
mixed = no;
|
2247
|
+
cindent = 0;
|
2248
|
+
}
|
2249
|
+
else if (mixed)
|
2250
|
+
cindent = indent;
|
2251
|
+
else
|
2252
|
+
cindent = indent + spaces;
|
2253
|
+
|
2254
|
+
PPrintTag( doc, mode, indent, node );
|
2255
|
+
if ( !mixed && node->content )
|
2256
|
+
TY_(PFlushLine)( doc, cindent );
|
2257
|
+
|
2258
|
+
for ( content = node->content; content; content = content->next )
|
2259
|
+
TY_(PPrintXMLTree)( doc, mode, cindent, content );
|
2260
|
+
|
2261
|
+
if ( !mixed && node->content )
|
2262
|
+
PCondFlushLine( doc, indent );
|
2263
|
+
|
2264
|
+
PPrintEndTag( doc, mode, indent, node );
|
2265
|
+
/* PCondFlushLine( doc, indent ); */
|
2266
|
+
}
|
2267
|
+
}
|
2268
|
+
|
2269
|
+
/*
|
2270
|
+
* local variables:
|
2271
|
+
* mode: c
|
2272
|
+
* indent-tabs-mode: nil
|
2273
|
+
* c-basic-offset: 4
|
2274
|
+
* eval: (c-set-offset 'substatement-open 0)
|
2275
|
+
* end:
|
2276
|
+
*/
|