tidy-ext 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/.gitignore +4 -0
  2. data/LICENSE +50 -0
  3. data/README +12 -0
  4. data/Rakefile +60 -0
  5. data/VERSION +1 -0
  6. data/ext/tidy/access.c +3310 -0
  7. data/ext/tidy/access.h +279 -0
  8. data/ext/tidy/alloc.c +107 -0
  9. data/ext/tidy/attrask.c +209 -0
  10. data/ext/tidy/attrdict.c +2398 -0
  11. data/ext/tidy/attrdict.h +122 -0
  12. data/ext/tidy/attrget.c +213 -0
  13. data/ext/tidy/attrs.c +1911 -0
  14. data/ext/tidy/attrs.h +374 -0
  15. data/ext/tidy/buffio.c +232 -0
  16. data/ext/tidy/buffio.h +118 -0
  17. data/ext/tidy/charsets.c +1032 -0
  18. data/ext/tidy/charsets.h +14 -0
  19. data/ext/tidy/clean.c +2674 -0
  20. data/ext/tidy/clean.h +87 -0
  21. data/ext/tidy/config.c +1746 -0
  22. data/ext/tidy/config.h +153 -0
  23. data/ext/tidy/entities.c +419 -0
  24. data/ext/tidy/entities.h +24 -0
  25. data/ext/tidy/extconf.rb +5 -0
  26. data/ext/tidy/fileio.c +106 -0
  27. data/ext/tidy/fileio.h +46 -0
  28. data/ext/tidy/forward.h +69 -0
  29. data/ext/tidy/iconvtc.c +105 -0
  30. data/ext/tidy/iconvtc.h +15 -0
  31. data/ext/tidy/istack.c +373 -0
  32. data/ext/tidy/lexer.c +3825 -0
  33. data/ext/tidy/lexer.h +617 -0
  34. data/ext/tidy/localize.c +1882 -0
  35. data/ext/tidy/mappedio.c +329 -0
  36. data/ext/tidy/mappedio.h +16 -0
  37. data/ext/tidy/message.h +207 -0
  38. data/ext/tidy/parser.c +4408 -0
  39. data/ext/tidy/parser.h +76 -0
  40. data/ext/tidy/platform.h +636 -0
  41. data/ext/tidy/pprint.c +2276 -0
  42. data/ext/tidy/pprint.h +93 -0
  43. data/ext/tidy/ruby-tidy.c +195 -0
  44. data/ext/tidy/streamio.c +1407 -0
  45. data/ext/tidy/streamio.h +222 -0
  46. data/ext/tidy/tagask.c +286 -0
  47. data/ext/tidy/tags.c +955 -0
  48. data/ext/tidy/tags.h +235 -0
  49. data/ext/tidy/tidy-int.h +129 -0
  50. data/ext/tidy/tidy.h +1097 -0
  51. data/ext/tidy/tidyenum.h +622 -0
  52. data/ext/tidy/tidylib.c +1751 -0
  53. data/ext/tidy/tmbstr.c +306 -0
  54. data/ext/tidy/tmbstr.h +92 -0
  55. data/ext/tidy/utf8.c +539 -0
  56. data/ext/tidy/utf8.h +52 -0
  57. data/ext/tidy/version.h +14 -0
  58. data/ext/tidy/win32tc.c +795 -0
  59. data/ext/tidy/win32tc.h +19 -0
  60. data/spec/spec_helper.rb +5 -0
  61. data/spec/tidy/compat_spec.rb +44 -0
  62. data/spec/tidy/remote_uri_spec.rb +14 -0
  63. data/spec/tidy/test1.html +5 -0
  64. data/spec/tidy/tidy_spec.rb +34 -0
  65. 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>....................&ldquo;...quote...&rdquo;...</p>
247
+ as
248
+ <p>....................\n&ldquo;...quote...&rdquo;...</p>
249
+ or
250
+ <p>....................&ldquo;...quote...&rdquo;\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 = "&nbsp;";
719
+ /* by default XML doesn't define &nbsp; */
720
+ if ( cfgBool(doc, TidyNumEntities) || cfgBool(doc, TidyXmlTags) )
721
+ ent = "&#160;";
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 &lt; etc. */
737
+ if ( !(mode & CDATA) )
738
+ {
739
+ if ( c == '<')
740
+ {
741
+ AddString( pprint, "&lt;" );
742
+ return;
743
+ }
744
+
745
+ if ( c == '>')
746
+ {
747
+ AddString( pprint, "&gt;" );
748
+ return;
749
+ }
750
+
751
+ /*
752
+ naked '&' chars can be left alone or
753
+ quoted as &amp; 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, "&amp;" );
760
+ return;
761
+ }
762
+
763
+ if ( c == '"' && qmark )
764
+ {
765
+ AddString( pprint, "&quot;" );
766
+ return;
767
+ }
768
+
769
+ if ( c == '\'' && qmark )
770
+ {
771
+ AddString( pprint, "&#39;" );
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, "&#160;" );
782
+ else
783
+ AddString( pprint, "&nbsp;" );
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 == '"' ? "&quot;" : "&#39;");
1047
+ AddString( pprint, entity );
1048
+ ++value;
1049
+ continue;
1050
+ }
1051
+ else if (c == '"')
1052
+ {
1053
+ if ( cfgBool(doc, TidyQuoteMarks) )
1054
+ AddString( pprint, "&quot;" );
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, "&#39;" );
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 &nbsp; or &#160; 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
+ */