Version:
~ [ 1.0 ] ~
1 /* localize.c -- text strings and routines to handle errors and general messages
2
3 (c) 1998-2005 (W3C) MIT, ERCIM, Keio University
4 Portions Copyright University of Toronto
5 See tidy.h and access.h for the copyright notice.
6
7 You should only need to edit this file and tidy.c
8 to localize HTML tidy. *** This needs checking ***
9
10 CVS Info :
11
12 $Author: arnaud02 $
13 $Date: 2005/10/25 15:57:27 $
14 $Revision: 1.145 $
15
16 */
17
18 #include "tidy-int.h"
19 #include "lexer.h"
20 #include "streamio.h"
21 #include "message.h"
22 #include "tmbstr.h"
23 #include "utf8.h"
24
25 /* used to point to Web Accessibility Guidelines */
26 #define ACCESS_URL "http://www.w3.org/WAI/GL"
27
28 /* points to the Adaptive Technology Resource Centre at the
29 ** University of Toronto
30 */
31 #define ATRC_ACCESS_URL "http://www.aprompt.ca/Tidy/accessibilitychecks.html"
32
33 static const char release_date[] = "1 September 2005";
34
35 ctmbstr ReleaseDate(void)
36 {
37 return release_date;
38 }
39
40 static struct _msgfmt
41 {
42 uint code;
43 ctmbstr fmt;
44 } const msgFormat[] =
45 {
46 /* ReportEncodingWarning */
47 { ENCODING_MISMATCH, "specified input encoding (%s) does not match actual input encoding (%s)" }, /* Warning */
48
49 /* ReportEncodingError */
50 { VENDOR_SPECIFIC_CHARS, "%s invalid character code %s" }, /* Error */
51 { INVALID_SGML_CHARS, "%s invalid character code %s" }, /* Error */
52 { INVALID_UTF8, "%s invalid UTF-8 bytes (char. code %s)" }, /* Error */
53 { INVALID_UTF16, "%s invalid UTF-16 surrogate pair (char. code %s)" }, /* Error */
54 { INVALID_NCR, "%s invalid numeric character reference %s" }, /* Error */
55
56 /* ReportEntityError */
57 { MISSING_SEMICOLON, "entity \"%s\" doesn't end in ';'" }, /* Warning in HTML, Error in XML/XHTML */
58 { MISSING_SEMICOLON_NCR, "numeric character reference \"%s\" doesn't end in ';'" }, /* Warning in HTML, Error in XML/XHTML */
59 { UNESCAPED_AMPERSAND, "unescaped & which should be written as &" }, /* Warning in HTML, Error in XHTML */
60 { UNKNOWN_ENTITY, "unescaped & or unknown entity \"%s\"" }, /* Error */
61 { APOS_UNDEFINED, "named entity ' only defined in XML/XHTML" }, /* Error in HTML (should only occur for HTML input) */
62
63 /* ReportAttrError */
64
65 /* attribute name */
66 { INSERTING_ATTRIBUTE, "%s inserting \"%s\" attribute" }, /* Warning in CheckLINK, Error otherwise */
67 { MISSING_ATTR_VALUE, "%s attribute \"%s\" lacks value" }, /* Warning in CheckUrl, Error otherwise */
68 { UNKNOWN_ATTRIBUTE, "%s unknown attribute \"%s\"" }, /* Error */
69 { PROPRIETARY_ATTRIBUTE, "%s proprietary attribute \"%s\"" }, /* Error */
70 { JOINING_ATTRIBUTE, "%s joining values of repeated attribute \"%s\"" }, /* Error */
71 { XML_ATTRIBUTE_VALUE, "%s has XML attribute \"%s\"" }, /* Error (but deprecated) */
72
73 /* attribute value */
74 { XML_ID_SYNTAX, "%s ID \"%s\" uses XML ID syntax" }, /* Warning if XHTML, Error if HTML */
75 { ATTR_VALUE_NOT_LCASE, "%s attribute value \"%s\" must be lower case for XHTML" }, /* Error if XHTML input, Notice if HTML input and XHTML outout */
76 { PROPRIETARY_ATTR_VALUE, "%s proprietary attribute value \"%s\"" }, /* Error */
77 { ANCHOR_NOT_UNIQUE, "%s anchor \"%s\" already defined" }, /* Error */
78
79 /* attribute name, attribute value */
80 { BAD_ATTRIBUTE_VALUE, "%s attribute \"%s\" has invalid value \"%s\"" }, /* Error */
81 { BAD_ATTRIBUTE_VALUE_REPLACED, "%s attribute \"%s\" had invalid value \"%s\" and has been replaced" }, /* Error */
82 { INVALID_ATTRIBUTE, "%s attribute name \"%s\" (value=\"%s\") is invalid" }, /* Error */
83
84 /* attribute value, attribute name */
85 { REPEATED_ATTRIBUTE, "%s dropping value \"%s\" for repeated attribute \"%s\"" }, /* Error */
86
87 /* no arguments */
88 { INVALID_XML_ID, "%s cannot copy name attribute to id" }, /* Warning */
89 { UNEXPECTED_GT, "%s missing '>' for end of tag" }, /* Warning if HTML, Error if XML/XHTML */
90 { UNEXPECTED_QUOTEMARK, "%s unexpected or duplicate quote mark" }, /* Error */
91 { MISSING_QUOTEMARK, "%s attribute with missing trailing quote mark" }, /* Error */
92 { UNEXPECTED_END_OF_FILE_ATTR, "%s end of file while parsing attributes" }, /* Error */
93 { ID_NAME_MISMATCH, "%s id and name attribute value mismatch" }, /* Error */
94 { BACKSLASH_IN_URI, "%s URI reference contains backslash. Typo?" }, /* Error */
95 { FIXED_BACKSLASH, "%s converting backslash in URI to slash" }, /* Error */
96 { ILLEGAL_URI_REFERENCE, "%s improperly escaped URI reference" }, /* Error */
97 { ESCAPED_ILLEGAL_URI, "%s escaping malformed URI reference" }, /* Error */
98 { NEWLINE_IN_URI, "%s discarding newline in URI reference" }, /* Error */
99 { UNEXPECTED_EQUALSIGN, "%s unexpected '=', expected attribute name" }, /* Error */
100 { MISSING_IMAGEMAP, "%s should use client-side image map" }, /* Warning (but deprecated) */
101
102 /* ReportMissingAttr */
103 { MISSING_ATTRIBUTE, "%s lacks \"%s\" attribute" }, /* Error */
104 /* ReportWarning */
105 { NESTED_EMPHASIS, "nested emphasis %s" }, /* Warning */
106 { NESTED_QUOTATION, "nested q elements, possible typo." }, /* Warning */
107 { OBSOLETE_ELEMENT, "replacing obsolete element %s by %s" }, /* Warning */
108 { COERCE_TO_ENDTAG_WARN, "<%s> is probably intended as </%s>" }, /* Warning */
109
110 /* ReportNotice */
111 { TRIM_EMPTY_ELEMENT, "trimming empty %s" }, /* Notice */
112 { REPLACING_ELEMENT, "replacing %s by %s" }, /* Notice */
113
114 /* ReportError */
115 { COERCE_TO_ENDTAG, "<%s> is probably intended as </%s>" }, /* Error */
116 { REPLACING_UNEX_ELEMENT, "replacing unexpected %s by %s" }, /* Error */
117 { MISSING_ENDTAG_FOR, "missing </%s>" }, /* Error */
118 { MISSING_ENDTAG_BEFORE, "missing </%s> before %s" }, /* Error */
119 { DISCARDING_UNEXPECTED, "discarding unexpected %s" }, /* Error */
120 { NON_MATCHING_ENDTAG, "replacing unexpected %s by </%s>" }, /* Error */
121 { TAG_NOT_ALLOWED_IN, "%s isn't allowed in <%s> elements" }, /* Error */
122 { MISSING_STARTTAG, "missing <%s>" }, /* Error */
123 { UNEXPECTED_ENDTAG, "unexpected </%s>" }, /* Error */
124 { TOO_MANY_ELEMENTS, "too many %s elements" }, /* Error */
125 { USING_BR_INPLACE_OF, "using <br> in place of %s" }, /* Error */
126 { INSERTING_TAG, "inserting implicit <%s>" }, /* Error */
127 { CANT_BE_NESTED, "%s can't be nested" }, /* Error */
128 { PROPRIETARY_ELEMENT, "%s is not approved by W3C" }, /* Error */
129 { ILLEGAL_NESTING, "%s shouldn't be nested" }, /* Error */
130 { NOFRAMES_CONTENT, "%s not inside 'noframes' element" }, /* Error */
131 { UNEXPECTED_END_OF_FILE, "unexpected end of file %s" }, /* Error */
132 { ELEMENT_NOT_EMPTY, "%s element not empty or not closed" }, /* Error */
133 { UNEXPECTED_ENDTAG_IN, "unexpected </%s> in <%s>" }, /* Error */
134 { TOO_MANY_ELEMENTS_IN, "too many %s elements in <%s>" }, /* Error */
135 { UNESCAPED_ELEMENT, "unescaped %s in pre content" }, /* Error (but deprecated) */
136
137 /* no arguments */
138 { DOCTYPE_AFTER_TAGS, "<!DOCTYPE> isn't allowed after elements" }, /* Error */
139 { MISSING_TITLE_ELEMENT, "inserting missing 'title' element" }, /* Error */
140 { INCONSISTENT_VERSION, "HTML DOCTYPE doesn't match content" }, /* Error */
141 { MISSING_DOCTYPE, "missing <!DOCTYPE> declaration" }, /* Error */
142 { CONTENT_AFTER_BODY, "content occurs after end of body" }, /* Error */
143 { MALFORMED_COMMENT, "adjacent hyphens within comment" }, /* Error */
144 { BAD_COMMENT_CHARS, "expecting -- or >" }, /* Error */
145 { BAD_CDATA_CONTENT, "'<' + '/' + letter not allowed here" }, /* Error */
146 { INCONSISTENT_NAMESPACE, "HTML namespace doesn't match content" }, /* Error */
147 { SPACE_PRECEDING_XMLDECL, "removing whitespace preceding XML Declaration" }, /* Error */
148 { MALFORMED_DOCTYPE, "discarding malformed <!DOCTYPE>" }, /* Error */
149 { BAD_XML_COMMENT, "XML comments can't contain --" }, /* Error (but deprecated) */
150 { DTYPE_NOT_UPPER_CASE, "SYSTEM, PUBLIC, W3C, DTD, EN must be upper case" }, /* Error (but deprecated) */
151 { ENCODING_IO_CONFLICT, "Output encoding does not work with standard output" }, /* Error (but deprecated) */
152
153 /* ReportFatal */
154 { SUSPECTED_MISSING_QUOTE, "missing quote mark for attribute value" }, /* Error? (not really sometimes) */
155 { DUPLICATE_FRAMESET, "repeated FRAMESET element" }, /* Error */
156 { UNKNOWN_ELEMENT, "%s is not recognized!" }, /* Error */
157 { UNEXPECTED_ENDTAG, "unexpected </%s>" }, /* Error */
158
159 #if SUPPORT_ACCESSIBILITY_CHECKS
160
161 /* ReportAccess */
162 /*
163 List of error/warning messages. The error code corresponds to
164 the check that is listed in the AERT (HTML specifications).
165 */
166 { IMG_MISSING_ALT, "[1.1.1.1]: <img> missing 'alt' text." }, /* Access */
167 { IMG_ALT_SUSPICIOUS_FILENAME, "[1.1.1.2]: suspicious 'alt' text (filename)." }, /* Access */
168 { IMG_ALT_SUSPICIOUS_FILE_SIZE, "[1.1.1.3]: suspicious 'alt' text (file size)." }, /* Access */
169 { IMG_ALT_SUSPICIOUS_PLACEHOLDER, "[1.1.1.4]: suspicious 'alt' text (placeholder)." }, /* Access */
170 { IMG_ALT_SUSPICIOUS_TOO_LONG, "[1.1.1.10]: suspicious 'alt' text (too long)." }, /* Access */
171 { IMG_MISSING_LONGDESC_DLINK, "[1.1.2.1]: <img> missing 'longdesc' and d-link." }, /* Access */
172 { IMG_MISSING_DLINK, "[1.1.2.2]: <img> missing d-link." }, /* Access */
173 { IMG_MISSING_LONGDESC, "[1.1.2.3]: <img> missing 'longdesc'." }, /* Access */
174 { IMG_BUTTON_MISSING_ALT, "[1.1.3.1]: <img> (button) missing 'alt' text." }, /* Access */
175 { APPLET_MISSING_ALT, "[1.1.4.1]: <applet> missing alternate content." }, /* Access */
176 { OBJECT_MISSING_ALT, "[1.1.5.1]: <object> missing alternate content." }, /* Access */
177 { AUDIO_MISSING_TEXT_WAV, "[1.1.6.1]: audio missing text transcript (wav)." }, /* Access */
178 { AUDIO_MISSING_TEXT_AU, "[1.1.6.2]: audio missing text transcript (au)." }, /* Access */
179 { AUDIO_MISSING_TEXT_AIFF, "[1.1.6.3]: audio missing text transcript (aiff)." }, /* Access */
180 { AUDIO_MISSING_TEXT_SND, "[1.1.6.4]: audio missing text transcript (snd)." }, /* Access */
181 { AUDIO_MISSING_TEXT_RA, "[1.1.6.5]: audio missing text transcript (ra)." }, /* Access */
182 { AUDIO_MISSING_TEXT_RM, "[1.1.6.6]: audio missing text transcript (rm)." }, /* Access */
183 { FRAME_MISSING_LONGDESC, "[1.1.8.1]: <frame> may require 'longdesc'." }, /* Access */
184 { AREA_MISSING_ALT, "[1.1.9.1]: <area> missing 'alt' text." }, /* Access */
185 { SCRIPT_MISSING_NOSCRIPT, "[1.1.10.1]: <script> missing <noscript> section." }, /* Access */
186 { ASCII_REQUIRES_DESCRIPTION, "[1.1.12.1]: ascii art requires description." }, /* Access */
187 { IMG_MAP_SERVER_REQUIRES_TEXT_LINKS, "[1.2.1.1]: image map (server-side) requires text links." }, /* Access */
188 { MULTIMEDIA_REQUIRES_TEXT, "[1.4.1.1]: multimedia requires synchronized text equivalents." }, /* Access */
189 { IMG_MAP_CLIENT_MISSING_TEXT_LINKS, "[1.5.1.1]: image map (client-side) missing text links." }, /* Access */
190 { INFORMATION_NOT_CONVEYED_IMAGE, "[2.1.1.1]: ensure information not conveyed through color alone (image)." }, /* Access */
191 { INFORMATION_NOT_CONVEYED_APPLET, "[2.1.1.2]: ensure information not conveyed through color alone (applet)." }, /* Access */
192 { INFORMATION_NOT_CONVEYED_OBJECT, "[2.1.1.3]: ensure information not conveyed through color alone (object)." }, /* Access */
193 { INFORMATION_NOT_CONVEYED_SCRIPT, "[2.1.1.4]: ensure information not conveyed through color alone (script)." }, /* Access */
194 { INFORMATION_NOT_CONVEYED_INPUT, "[2.1.1.5]: ensure information not conveyed through color alone (input)." }, /* Access */
195 { COLOR_CONTRAST_TEXT, "[2.2.1.1]: poor color contrast (text)." }, /* Access */
196 { COLOR_CONTRAST_LINK, "[2.2.1.2]: poor color contrast (link)." }, /* Access */
197 { COLOR_CONTRAST_ACTIVE_LINK, "[2.2.1.3]: poor color contrast (active link)." }, /* Access */
198 { COLOR_CONTRAST_VISITED_LINK, "[2.2.1.4]: poor color contrast (visited link)." }, /* Access */
199 { DOCTYPE_MISSING, "[3.2.1.1]: <doctype> missing." }, /* Access */
200 { STYLE_SHEET_CONTROL_PRESENTATION, "[3.3.1.1]: use style sheets to control presentation." }, /* Access */
201 { HEADERS_IMPROPERLY_NESTED, "[3.5.1.1]: headers improperly nested." }, /* Access */
202 { POTENTIAL_HEADER_BOLD, "[3.5.2.1]: potential header (bold)." }, /* Access */
203 { POTENTIAL_HEADER_ITALICS, "[3.5.2.2]: potential header (italics)." }, /* Access */
204 { POTENTIAL_HEADER_UNDERLINE, "[3.5.2.3]: potential header (underline)." }, /* Access */
205 { HEADER_USED_FORMAT_TEXT, "[3.5.3.1]: header used to format text." }, /* Access */
206 { LIST_USAGE_INVALID_UL, "[3.6.1.1]: list usage invalid <ul>." }, /* Access */
207 { LIST_USAGE_INVALID_OL, "[3.6.1.2]: list usage invalid <ol>." }, /* Access */
208 { LIST_USAGE_INVALID_LI, "[3.6.1.4]: list usage invalid <li>." }, /* Access */
209 { INDICATE_CHANGES_IN_LANGUAGE, "[4.1.1.1]: indicate changes in language." }, /* Access */
210 { LANGUAGE_NOT_IDENTIFIED, "[4.3.1.1]: language not identified." }, /* Access */
211 { LANGUAGE_INVALID, "[4.3.1.2]: language attribute invalid." }, /* Access */
212 { DATA_TABLE_MISSING_HEADERS, "[5.1.2.1]: data <table> missing row/column headers (all)." }, /* Access */
213 { DATA_TABLE_MISSING_HEADERS_COLUMN, "[5.1.2.2]: data <table> missing row/column headers (1 col)." }, /* Access */
214 { DATA_TABLE_MISSING_HEADERS_ROW, "[5.1.2.3]: data <table> missing row/column headers (1 row)." }, /* Access */
215 { DATA_TABLE_REQUIRE_MARKUP_COLUMN_HEADERS, "[5.2.1.1]: data <table> may require markup (column headers)." }, /* Access */
216 { DATA_TABLE_REQUIRE_MARKUP_ROW_HEADERS, "[5.2.1.2]: data <table> may require markup (row headers)." }, /* Access */
217 { LAYOUT_TABLES_LINEARIZE_PROPERLY, "[5.3.1.1]: verify layout tables linearize properly." }, /* Access */
218 { LAYOUT_TABLE_INVALID_MARKUP, "[5.4.1.1]: invalid markup used in layout <table>." }, /* Access */
219 { TABLE_MISSING_SUMMARY, "[5.5.1.1]: <table> missing summary." }, /* Access */
220 { TABLE_SUMMARY_INVALID_NULL, "[5.5.1.2]: <table> summary invalid (null)." }, /* Access */
221 { TABLE_SUMMARY_INVALID_SPACES, "[5.5.1.3]: <table> summary invalid (spaces)." }, /* Access */
222 { TABLE_SUMMARY_INVALID_PLACEHOLDER, "[5.5.1.6]: <table> summary invalid (placeholder text)." }, /* Access */
223 { TABLE_MISSING_CAPTION, "[5.5.2.1]: <table> missing <caption>." }, /* Access */
224 { TABLE_MAY_REQUIRE_HEADER_ABBR, "[5.6.1.1]: <table> may require header abbreviations." }, /* Access */
225 { TABLE_MAY_REQUIRE_HEADER_ABBR_NULL, "[5.6.1.2]: <table> header abbreviations invalid (null)." }, /* Access */
226 { TABLE_MAY_REQUIRE_HEADER_ABBR_SPACES, "[5.6.1.3]: <table> header abbreviations invalid (spaces)." }, /* Access */
227 { STYLESHEETS_REQUIRE_TESTING_LINK, "[6.1.1.1]: style sheets require testing (link)." }, /* Access */
228 { STYLESHEETS_REQUIRE_TESTING_STYLE_ELEMENT, "[6.1.1.2]: style sheets require testing (style element)." }, /* Access */
229 { STYLESHEETS_REQUIRE_TESTING_STYLE_ATTR, "[6.1.1.3]: style sheets require testing (style attribute)." }, /* Access */
230 { FRAME_SRC_INVALID, "[6.2.1.1]: <frame> source invalid." }, /* Access */
231 { TEXT_EQUIVALENTS_REQUIRE_UPDATING_APPLET, "[6.2.2.1]: text equivalents require updating (applet)." }, /* Access */
232 { TEXT_EQUIVALENTS_REQUIRE_UPDATING_SCRIPT, "[6.2.2.2]: text equivalents require updating (script)." }, /* Access */
233 { TEXT_EQUIVALENTS_REQUIRE_UPDATING_OBJECT, "[6.2.2.3]: text equivalents require updating (object)." }, /* Access */
234 { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_SCRIPT, "[6.3.1.1]: programmatic objects require testing (script)." }, /* Access */
235 { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_OBJECT, "[6.3.1.2]: programmatic objects require testing (object)." }, /* Access */
236 { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_EMBED, "[6.3.1.3]: programmatic objects require testing (embed)." }, /* Access */
237 { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_APPLET, "[6.3.1.4]: programmatic objects require testing (applet)." }, /* Access */
238 { FRAME_MISSING_NOFRAMES, "[6.5.1.1]: <frameset> missing <noframes> section." }, /* Access */
239 { NOFRAMES_INVALID_NO_VALUE, "[6.5.1.2]: <noframes> section invalid (no value)." }, /* Access */
240 { NOFRAMES_INVALID_CONTENT, "[6.5.1.3]: <noframes> section invalid (content)." }, /* Access */
241 { NOFRAMES_INVALID_LINK, "[6.5.1.4]: <noframes> section invalid (link)." }, /* Access */
242 { REMOVE_FLICKER_SCRIPT, "[7.1.1.1]: remove flicker (script)." }, /* Access */
243 { REMOVE_FLICKER_OBJECT, "[7.1.1.2]: remove flicker (object)." }, /* Access */
244 { REMOVE_FLICKER_EMBED, "[7.1.1.3]: remove flicker (embed)." }, /* Access */
245 { REMOVE_FLICKER_APPLET, "[7.1.1.4]: remove flicker (applet)." }, /* Access */
246 { REMOVE_FLICKER_ANIMATED_GIF, "[7.1.1.5]: remove flicker (animated gif)." }, /* Access */
247 { REMOVE_BLINK_MARQUEE, "[7.2.1.1]: remove blink/marquee." }, /* Access */
248 { REMOVE_AUTO_REFRESH, "[7.4.1.1]: remove auto-refresh." }, /* Access */
249 { REMOVE_AUTO_REDIRECT, "[7.5.1.1]: remove auto-redirect." }, /* Access */
250 { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_SCRIPT, "[8.1.1.1]: ensure programmatic objects are accessible (script)." }, /* Access */
251 { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_OBJECT, "[8.1.1.2]: ensure programmatic objects are accessible (object)." }, /* Access */
252 { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_APPLET, "[8.1.1.3]: ensure programmatic objects are accessible (applet)." }, /* Access */
253 { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_EMBED, "[8.1.1.4]: ensure programmatic objects are accessible (embed)." }, /* Access */
254 { IMAGE_MAP_SERVER_SIDE_REQUIRES_CONVERSION, "[9.1.1.1]: image map (server-side) requires conversion." }, /* Access */
255 { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_DOWN, "[9.3.1.1]: <script> not keyboard accessible (onMouseDown)." }, /* Access */
256 { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_UP, "[9.3.1.2]: <script> not keyboard accessible (onMouseUp)." }, /* Access */
257 { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_CLICK, "[9.3.1.3]: <script> not keyboard accessible (onClick)." }, /* Access */
258 { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OVER, "[9.3.1.4]: <script> not keyboard accessible (onMouseOver)." }, /* Access */
259 { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OUT, "[9.3.1.5]: <script> not keyboard accessible (onMouseOut)." }, /* Access */
260 { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_MOVE, "[9.3.1.6]: <script> not keyboard accessible (onMouseMove)." }, /* Access */
261 { NEW_WINDOWS_REQUIRE_WARNING_NEW, "[10.1.1.1]: new windows require warning (_new)." }, /* Access */
262 { NEW_WINDOWS_REQUIRE_WARNING_BLANK, "[10.1.1.2]: new windows require warning (_blank)." }, /* Access */
263 { FORM_CONTROL_REQUIRES_DEFAULT_TEXT, "[10.4.1.1]: form control requires default text." }, /* Access */
264 { FORM_CONTROL_DEFAULT_TEXT_INVALID_NULL, "[10.4.1.2]: form control default text invalid (null)." }, /* Access */
265 { FORM_CONTROL_DEFAULT_TEXT_INVALID_SPACES, "[10.4.1.3]: form control default text invalid (spaces)." }, /* Access */
266 { REPLACE_DEPRECATED_HTML_APPLET, "[11.2.1.1]: replace deprecated html <applet>." }, /* Access */
267 { REPLACE_DEPRECATED_HTML_BASEFONT, "[11.2.1.2]: replace deprecated html <basefont>." }, /* Access */
268 { REPLACE_DEPRECATED_HTML_CENTER, "[11.2.1.3]: replace deprecated html <center>." }, /* Access */
269 { REPLACE_DEPRECATED_HTML_DIR, "[11.2.1.4]: replace deprecated html <dir>." }, /* Access */
270 { REPLACE_DEPRECATED_HTML_FONT, "[11.2.1.5]: replace deprecated html <font>." }, /* Access */
271 { REPLACE_DEPRECATED_HTML_ISINDEX, "[11.2.1.6]: replace deprecated html <isindex>." }, /* Access */
272 { REPLACE_DEPRECATED_HTML_MENU, "[11.2.1.7]: replace deprecated html <menu>." }, /* Access */
273 { REPLACE_DEPRECATED_HTML_S, "[11.2.1.8]: replace deprecated html <s>." }, /* Access */
274 { REPLACE_DEPRECATED_HTML_STRIKE, "[11.2.1.9]: replace deprecated html <strike>." }, /* Access */
275 { REPLACE_DEPRECATED_HTML_U, "[11.2.1.10]: replace deprecated html <u>." }, /* Access */
276 { FRAME_MISSING_TITLE, "[12.1.1.1]: <frame> missing title." }, /* Access */
277 { FRAME_TITLE_INVALID_NULL, "[12.1.1.2]: <frame> title invalid (null)." }, /* Access */
278 { FRAME_TITLE_INVALID_SPACES, "[12.1.1.3]: <frame> title invalid (spaces)." }, /* Access */
279 { ASSOCIATE_LABELS_EXPLICITLY, "[12.4.1.1]: associate labels explicitly with form controls." }, /* Access */
280 { ASSOCIATE_LABELS_EXPLICITLY_FOR, "[12.4.1.2]: associate labels explicitly with form controls (for)." }, /* Access */
281 { ASSOCIATE_LABELS_EXPLICITLY_ID, "[12.4.1.3]: associate labels explicitly with form controls (id)." }, /* Access */
282 { LINK_TEXT_NOT_MEANINGFUL, "[13.1.1.1]: link text not meaningful." }, /* Access */
283 { LINK_TEXT_MISSING, "[13.1.1.2]: link text missing." }, /* Access */
284 { LINK_TEXT_TOO_LONG, "[13.1.1.3]: link text too long." }, /* Access */
285 { LINK_TEXT_NOT_MEANINGFUL_CLICK_HERE, "[13.1.1.4]: link text not meaningful (click here)." }, /* Access */
286 { METADATA_MISSING, "[13.2.1.1]: Metadata missing." }, /* Access */
287 { METADATA_MISSING_LINK, "[13.2.1.2]: Metadata missing (link element)." }, /* Access */
288 { METADATA_MISSING_REDIRECT_AUTOREFRESH, "[13.2.1.3]: Metadata missing (redirect/auto-refresh)." }, /* Access */
289 { SKIPOVER_ASCII_ART, "[13.10.1.1]: skip over ascii art." }, /* Access */
290
291 #endif /* SUPPORT_ACCESSIBILITY_CHECKS */
292
293 /* must be last */
294 { 0, NULL }
295 };
296
297 static ctmbstr GetFormatFromCode(uint code)
298 {
299 uint i;
300
301 for (i = 0; msgFormat[i].fmt; ++i)
302 if (msgFormat[i].code == code)
303 return msgFormat[i].fmt;
304
305 return NULL;
306 }
307
308 /*
309 Documentation of configuration options
310 */
311
312 /* Cross references */
313 static const TidyOptionId TidyXmlDeclLinks[] =
314 { TidyCharEncoding, TidyOutCharEncoding, TidyUnknownOption };
315 static const TidyOptionId TidyJoinClassesLinks[] =
316 { TidyJoinStyles, TidyDuplicateAttrs, TidyUnknownOption };
317 static const TidyOptionId TidyJoinStylesLinks[] =
318 { TidyJoinClasses, TidyDuplicateAttrs, TidyUnknownOption };
319 static const TidyOptionId TidyDuplicateAttrsLinks[] =
320 { TidyJoinClasses, TidyJoinStyles, TidyUnknownOption };
321 static const TidyOptionId TidyIndentContentLinks[] =
322 { TidyIndentSpaces, TidyUnknownOption };
323 static const TidyOptionId TidyIndentSpacesLinks[] =
324 { TidyIndentContent, TidyUnknownOption };
325 static const TidyOptionId TidyWrapAttValsLinks[] =
326 { TidyWrapScriptlets, TidyUnknownOption };
327 static const TidyOptionId TidyWrapScriptletsLinks[] =
328 { TidyWrapAttVals, TidyUnknownOption };
329 static const TidyOptionId TidyCharEncodingLinks[] =
330 { TidyInCharEncoding, TidyOutCharEncoding, TidyUnknownOption };
331 static const TidyOptionId TidyInCharEncodingLinks[] =
332 { TidyCharEncoding, TidyUnknownOption };
333 static const TidyOptionId TidyOutCharEncodingLinks[] =
334 { TidyCharEncoding, TidyUnknownOption };
335 static const TidyOptionId TidyErrFileLinks[] =
336 { TidyOutFile, TidyUnknownOption };
337 static const TidyOptionId TidyOutFileLinks[] =
338 { TidyErrFile, TidyUnknownOption };
339 static const TidyOptionId TidyBlockTagsLinks[] =
340 { TidyEmptyTags, TidyInlineTags, TidyPreTags, TidyUnknownOption };
341 static const TidyOptionId TidyEmptyTagsLinks[] =
342 { TidyBlockTags, TidyInlineTags, TidyPreTags, TidyUnknownOption };
343 static const TidyOptionId TidyInlineTagsLinks[] =
344 { TidyBlockTags, TidyEmptyTags, TidyPreTags, TidyUnknownOption };
345 static const TidyOptionId TidyPreTagsLinks[] =
346 { TidyBlockTags, TidyEmptyTags, TidyInlineTags, TidyUnknownOption };
347 static const TidyOptionId TidyMergeDivsLinks[] =
348 { TidyMakeClean, TidyUnknownOption };
349 static const TidyOptionId TidyAsciiCharsLinks[] =
350 { TidyMakeClean, TidyUnknownOption };
351 static const TidyOptionId TidyNumEntitiesLinks[] =
352 { TidyDoctype, TidyUnknownOption };
353
354 /* Documentation of options */
355 static const TidyOptionDoc option_docs[] =
356 {
357 {TidyXmlDecl,
358 "This option specifies if Tidy should add the XML declaration when "
359 "outputting XML or XHTML. Note that if the input already includes an "
360 "<?xml ... ?> declaration then this option will be ignored. "
361 "If the encoding for the output is different from \"ascii\", one of the "
362 "utf encodings or \"raw\", the declaration is always added as required by "
363 "the XML standard. "
364 , TidyXmlDeclLinks
365 },
366 {TidyXmlSpace,
367 "This option specifies if Tidy should add xml:space=\"preserve\" to "
368 "elements such as <PRE>, <STYLE> and <SCRIPT> when "
369 "generating XML. This is needed if the whitespace in such elements is to "
370 "be parsed appropriately without having access to the DTD. "
371 },
372 {TidyAltText,
373 "This option specifies the default \"alt=\" text Tidy uses for "
374 "<IMG> attributes. This feature is dangerous as it suppresses "
375 "further accessibility warnings. You are responsible for making your "
376 "documents accessible to people who can not see the images! "
377 },
378 {TidyXmlPIs,
379 "This option specifies if Tidy should change the parsing of processing "
380 "instructions to require ?> as the terminator rather than >. This "
381 "option is automatically set if the input is in XML. "
382 },
383 {TidyMakeBare,
384 "This option specifies if Tidy should strip Microsoft specific HTML "
385 "from Word 2000 documents, and output spaces rather than non-breaking "
386 "spaces where they exist in the input. "
387 },
388 {TidyCSSPrefix,
389 "This option specifies the prefix that Tidy uses for styles rules. By "
390 "default, \"c\" will be used. "
391 },
392 {TidyMakeClean,
393 "This option specifies if Tidy "
394 "should strip out surplus presentational tags and attributes replacing "
395 "them by style rules and structural markup as appropriate. It works well "
396 "on the HTML saved by Microsoft Office products. "
397 },
398 {TidyDoctype,
399 "This option specifies the DOCTYPE declaration generated by Tidy. If set "
400 "to \"omit\" the output won't contain a DOCTYPE declaration. If set to "
401 "\"auto\" (the default) Tidy will use an educated guess based upon the "
402 "contents of the document. If set to \"strict\", Tidy will set the DOCTYPE "
403 "to the strict DTD. If set to \"loose\", the DOCTYPE is set to the loose "
404 "(transitional) DTD. Alternatively, you can supply a string for the formal "
405 "public identifier (FPI).<br />"
406 "<br />"
407 "For example: <br />"
408 "doctype: \"-//ACME//DTD HTML 3.14159//EN\"<br />"
409 "<br />"
410 "If you specify the FPI for an XHTML document, Tidy will set the "
411 "system identifier to the empty string. For an HTML document, Tidy adds a "
412 "system identifier only if one was already present in order to preserve "
413 "the processing mode of some browsers. Tidy leaves the DOCTYPE for "
414 "generic XML documents unchanged. <code>--doctype omit</code> implies "
415 "<code>--numeric-entities yes</code>. "
416 },
417 {TidyDropEmptyParas,
418 "This option specifies if Tidy should discard empty paragraphs. "
419 },
420 {TidyDropFontTags,
421 "This option specifies if Tidy should discard <FONT> and "
422 "<CENTER> tags without creating the corresponding style rules. This "
423 "option can be set independently of the clean option. "
424 },
425 {TidyDropPropAttrs,
426 "This option specifies if Tidy should strip out proprietary attributes, "
427 "such as MS data binding attributes. "
428 },
429 {TidyEncloseBlockText,
430 "This option specifies if Tidy should insert a <P> element to "
431 "enclose any text it finds in any element that allows mixed content for "
432 "HTML transitional but not HTML strict. "
433 },
434 {TidyEncloseBodyText,
435 "This option specifies if Tidy should enclose any text it finds in the "
436 "body element within a <P> element. This is useful when you want to "
437 "take existing HTML and use it with a style sheet. "
438 },
439 {TidyEscapeCdata,
440 "This option specifies if Tidy should convert <![CDATA[]]> "
441 "sections to normal text. "
442 },
443 {TidyFixComments,
444 "This option specifies if Tidy should replace unexpected hyphens with "
445 "\"=\" characters when it comes across adjacent hyphens. The default is "
446 "yes. This option is provided for users of Cold Fusion which uses the "
447 "comment syntax: <!--- ---> "
448 },
449 {TidyFixUri,
450 "This option specifies if Tidy should check attribute values that carry "
451 "URIs for illegal characters and if such are found, escape them as HTML 4 "
452 "recommends. "
453 },
454 {TidyHideComments,
455 "This option specifies if Tidy should print out comments. "
456 },
457 {TidyHideEndTags,
458 "This option specifies if Tidy should omit optional end-tags when "
459 "generating the pretty printed markup. This option is ignored if you are "
460 "outputting to XML. "
461 },
462 {TidyIndentCdata,
463 "This option specifies if Tidy should indent <![CDATA[]]> sections. "
464 },
465 {TidyXmlTags,
466 "This option specifies if Tidy should use the XML parser rather than the "
467 "error correcting HTML parser. "
468 },
469 {TidyJoinClasses,
470 "This option specifies if Tidy should combine class names to generate "
471 "a single new class name, if multiple class assignments are detected on "
472 "an element. "
473 , TidyJoinClassesLinks
474 },
475 {TidyJoinStyles,
476 "This option specifies if Tidy should combine styles to generate a single "
477 "new style, if multiple style values are detected on an element. "
478 , TidyJoinStylesLinks
479 },
480 {TidyLogicalEmphasis,
481 "This option specifies if Tidy should replace any occurrence of <I> "
482 "by <EM> and any occurrence of <B> by <STRONG>. In both "
483 "cases, the attributes are preserved unchanged. This option can be set "
484 "independently of the clean and drop-font-tags options. "
485 },
486 {TidyLowerLiterals,
487 "This option specifies if Tidy should convert the value of an attribute "
488 "that takes a list of predefined values to lower case. This is required "
489 "for XHTML documents. "
490 },
491 {TidyMergeDivs,
492 "Can be used to modify behavior of -c (--clean yes) option. "
493 "This option specifies if Tidy should merge nested <div> such as "
494 "\"<div><div>...</div></div>\". If set to "
495 "\"auto\", the attributes of the inner <div> are moved to the "
496 "outer one. As well, nested <div> with ID attributes are not "
497 "merged. If set to \"yes\", the attributes of the inner <div> "
498 "are discarded with the exception of \"class\" and \"style\". "
499 ,TidyMergeDivsLinks
500 },
501 #if SUPPORT_ASIAN_ENCODINGS
502 {TidyNCR,
503 "This option specifies if Tidy should allow numeric character references. "
504 },
505 #endif
506 {TidyBlockTags,
507 "This option specifies new block-level tags. This option takes a space or "
508 "comma separated list of tag names. Unless you declare new tags, Tidy will "
509 "refuse to generate a tidied file if the input includes previously unknown "
510 "tags. Note you can't change the content model for elements such as "
511 "<TABLE>, <UL>, <OL> and <DL>. "
512 ,TidyBlockTagsLinks
513 },
514 {TidyEmptyTags,
515 "This option specifies new empty inline tags. This option takes a space "
516 "or comma separated list of tag names. Unless you declare new tags, Tidy "
517 "will refuse to generate a tidied file if the input includes previously "
518 "unknown tags. Remember to also declare empty tags as either inline or "
519 "blocklevel. "
520 ,TidyEmptyTagsLinks
521 },
522 {TidyInlineTags,
523 "This option specifies new non-empty inline tags. This option takes a "
524 "space or comma separated list of tag names. Unless you declare new tags, "
525 "Tidy will refuse to generate a tidied file if the input includes "
526 "previously unknown tags. "
527 ,TidyInlineTagsLinks
528 },
529 { TidyPreTags,
530 "This option specifies "
531 "new tags that are to be processed in exactly the same way as HTML's "
532 "<PRE> element. This option takes a space or comma separated list "
533 "of tag names. Unless you declare new tags, Tidy will refuse to generate "
534 "a tidied file if the input includes previously unknown tags. Note you "
535 "can not as yet add new CDATA elements (similar to <SCRIPT>). "
536 ,TidyPreTagsLinks
537 },
538 {TidyNumEntities,
539 "This option specifies if Tidy should output entities other than the "
540 "built-in HTML entities (&amp;, &lt;, &gt; and &quot;) in "
541 "the numeric rather than the named entity form. "
542 ,TidyNumEntitiesLinks
543 },
544 {TidyHtmlOut,
545 "This option specifies if Tidy should generate pretty printed output, "
546 "writing it as HTML. "
547 },
548 {TidyXhtmlOut,
549 "This option specifies if Tidy should generate pretty printed output, "
550 "writing it as extensible HTML. "
551 "This option causes Tidy to set the DOCTYPE and default namespace as "
552 "appropriate to XHTML. If a DOCTYPE or namespace is given they will "
553 "checked for consistency with the content of the document. In the case of "
554 "an inconsistency, the corrected values will appear in the output. For "
555 "XHTML, entities can be written as named or numeric entities according to "
556 "the setting of the \"numeric-entities\" option. The original case of tags "
557 "and attributes will be preserved, regardless of other options. "
558 },
559 {TidyXmlOut,
560 "This option specifies if Tidy should pretty print output, writing it as "
561 "well-formed XML. Any entities not defined in XML 1.0 will be written as "
562 "numeric entities to allow them to be parsed by a XML parser. The original "
563 "case of tags and attributes will be preserved, regardless of other "
564 "options. "
565 },
566 {TidyQuoteAmpersand,
567 "This option specifies if Tidy should output unadorned & characters as "
568 "&amp;. "
569 },
570 {TidyQuoteMarks,
571 "This option specifies if Tidy should output " characters as "
572 "&quot; as is preferred by some editing environments. The apostrophe "
573 "character ' is written out as &#39; since many web browsers don't yet "
574 "support &apos;. "
575 },
576 {TidyQuoteNbsp,
577 "This option specifies if Tidy should output non-breaking space characters "
578 "as entities, rather than as the Unicode character value 160 (decimal). "
579 },
580 {TidyDuplicateAttrs,
581 "This option specifies if Tidy should keep the first or last attribute, if "
582 "an attribute is repeated, e.g. has two align attributes. "
583 , TidyDuplicateAttrsLinks
584 },
585 {TidyReplaceColor,
586 "This option specifies if Tidy should replace numeric values in color "
587 "attributes by HTML/XHTML color names where defined, e.g. replace "
588 "\"#ffffff\" with \"white\". "
589 },
590 {TidyBodyOnly,
591 "This option specifies if Tidy should print only the contents of the "
592 "body tag as an HTML fragment. Useful for incorporating existing whole "
593 "pages as a portion of another page. "
594 },
595 {TidyUpperCaseAttrs,
596 "This option specifies if Tidy should output attribute names in upper "
597 "case. The default is no, which results in lower case attribute names, "
598 "except for XML input, where the original case is preserved. "
599 },
600 {TidyUpperCaseTags,
601 "This option specifies if Tidy should output tag names in upper case. "
602 "The default is no, which results in lower case tag names, except for XML "
603 "input, where the original case is preserved. "
604 },
605 {TidyWord2000,
606 "This option specifies if Tidy should go to great pains to strip out all "
607 "the surplus stuff Microsoft Word 2000 inserts when you save Word "
608 "documents as \"Web pages\". Doesn't handle embedded images or VML. "
609 "You should consider using Word's \"Save As: Web Page, Filtered\". "
610 },
611 {TidyAccessibilityCheckLevel,
612 "This option specifies what level of accessibility checking, if any, "
613 "that Tidy should do. Level 0 is equivalent to Tidy Classic's "
614 "accessibility checking. "
615 "For more information on Tidy's accessibility checking, visit the "
616 "<a href=\"http://www.aprompt.ca/Tidy/accessibilitychecks.html\" "
617 ">Adaptive Technology Resource Centre at the University of Toronto</a>. "
618 },
619 {TidyShowErrors,
620 "This option specifies the number Tidy uses to determine if further errors "
621 "should be shown. If set to 0, then no errors are shown. "
622 },
623 {TidyShowWarnings,
624 "This option specifies if Tidy should suppress warnings. This can be "
625 "useful when a few errors are hidden in a flurry of warnings. "
626 },
627 {TidyBreakBeforeBR,
628 "This option specifies if Tidy should output a line break before each "
629 "<BR> element. "
630 },
631 {TidyIndentContent,
632 "This option specifies if Tidy should indent block-level tags. If set to "
633 "\"auto\", this option causes Tidy to decide whether or not to indent the "
634 "content of tags such as TITLE, H1-H6, LI, TD, TD, or P depending on "
635 "whether or not the content includes a block-level element. You are "
636 "advised to avoid setting indent to yes as this can expose layout bugs in "
637 "some browsers. "
638 ,TidyIndentContentLinks
639 },
640 {TidyIndentAttributes,
641 "This option specifies if Tidy should begin each attribute on a new line. "
642 },
643 {TidyIndentSpaces,
644 "This option specifies the number of spaces Tidy uses to indent content, "
645 "when indentation is enabled. "
646 ,TidyIndentSpacesLinks
647 },
648 {TidyLiteralAttribs,
649 "This option specifies if Tidy should ensure that whitespace characters "
650 "within attribute values are passed through unchanged. "
651 },
652 {TidyShowMarkup,
653 "This option specifies if Tidy should generate a pretty printed version "
654 "of the markup. Note that Tidy won't generate a pretty printed version if "
655 "it finds significant errors (see force-output). "
656 },
657 #if SUPPORT_ASIAN_ENCODINGS
658 {TidyPunctWrap,
659 "This option specifies if Tidy should line wrap after some Unicode or "
660 "Chinese punctuation characters. "
661 },
662 #endif
663 {TidyBurstSlides,
664 "Currently not used. Tidy Classic only. "
665 },
666 {TidyTabSize,
667 "This option specifies the number of columns that Tidy uses between "
668 "successive tab stops. It is used to map tabs to spaces when reading the "
669 "input. Tidy never outputs tabs. "
670 },
671 {TidyVertSpace,
672 "This option specifies if Tidy should add some empty lines for "
673 "readability. "
674 },
675 {TidyWrapLen,
676 "This option specifies the right margin Tidy uses for line wrapping. Tidy "
677 "tries to wrap lines so that they do not exceed this length. Set wrap to "
678 "zero if you want to disable line wrapping. "
679 },
680 {TidyWrapAsp,
681 "This option specifies if Tidy should line wrap text contained within ASP "
682 "pseudo elements, which look like: <% ... %>. "
683 },
684 {TidyWrapAttVals,
685 "This option specifies if Tidy should line wrap attribute values, for "
686 "easier editing. This option can be set independently of "
687 "wrap-script-literals. "
688 ,TidyWrapAttValsLinks
689 },
690 {TidyWrapJste,
691 "This option specifies if Tidy should line wrap text contained within "
692 "JSTE pseudo elements, which look like: <# ... #>. "
693 },
694 {TidyWrapPhp,
695 "This option specifies if Tidy should line wrap text contained within PHP "
696 "pseudo elements, which look like: <?php ... ?>. "
697 },
698 {TidyWrapScriptlets,
699 "This option specifies if Tidy should line wrap string literals that "
700 "appear in script attributes. Tidy wraps long script string literals by "
701 "inserting a backslash character before the line break. "
702 ,TidyWrapScriptletsLinks
703 },
704 {TidyWrapSection,
705 "This option specifies if Tidy should line wrap text contained within "
706 "<![ ... ]> section tags. "
707 },
708 {TidyAsciiChars,
709 "Can be used to modify behavior of -c (--clean yes) option. If set "
710 "to \"yes\" when using -c, &emdash;, &rdquo;, and other named "
711 "character entities are downgraded to their closest ascii equivalents. "
712 ,TidyAsciiCharsLinks
713 },
714 {TidyCharEncoding,
715 "This option specifies the character encoding Tidy uses for both the input "
716 "and output. For ascii, Tidy will accept Latin-1 (ISO-8859-1) character "
717 "values, but will use entities for all characters whose value > 127. "
718 "For raw, Tidy will output values above 127 without translating them into "
719 "entities. For latin1, characters above 255 will be written as entities. "
720 "For utf8, Tidy assumes that both input and output is encoded as UTF-8. "
721 "You can use iso2022 for files encoded using the ISO-2022 family of "
722 "encodings e.g. ISO-2022-JP. For mac and win1252, Tidy will accept vendor "
723 "specific character values, but will use entities for all characters whose "
724 "value > 127. "
725 ,TidyCharEncodingLinks
726 },
727 {TidyInCharEncoding,
728 "This option specifies the character encoding Tidy uses for the input. See "
729 "char-encoding for more info. "
730 ,TidyInCharEncodingLinks
731 },
732 #if SUPPORT_ASIAN_ENCODINGS
733 {TidyLanguage,
734 "Currently not used, but this option specifies the language Tidy uses "
735 "(for instance \"en\"). "
736 },
737 #endif
738 #if SUPPORT_UTF16_ENCODINGS
739 {TidyOutputBOM,
740 "This option specifies if Tidy should write a Unicode Byte Order Mark "
741 "character (BOM; also known as Zero Width No-Break Space; has value of "
742 "U+FEFF) to the beginning of the output; only for UTF-8 and UTF-16 output "
743 "encodings. If set to \"auto\", this option causes Tidy to write a BOM to "
744 "the output only if a BOM was present at the beginning of the input. A BOM "
745 "is always written for XML/XHTML output using UTF-16 output encodings. "
746 },
747 #endif
748 {TidyOutCharEncoding,
749 "This option specifies the character encoding Tidy uses for the output. "
750 "See char-encoding for more info. May only be different from "
751 "input-encoding for Latin encodings (ascii, latin0, latin1, mac, win1252, "
752 "ibm858). "
753 ,TidyOutCharEncodingLinks
754 },
755 {TidyNewline,
756 "The default is appropriate to the current platform: CRLF on PC-DOS, "
757 "MS-Windows and OS/2, CR on Classic Mac OS, and LF everywhere else "
758 "(Unix and Linux). "
759 },
760 {TidyErrFile,
761 "This option specifies the error file Tidy uses for errors and warnings. "
762 "Normally errors and warnings are output to \"stderr\". "
763 ,TidyErrFileLinks
764 },
765 {TidyFixBackslash,
766 "This option specifies if Tidy should replace backslash characters "
767 "\"<code>\\</code>\" in URLs by forward slashes \"<code>/</code>\". "
768 },
769 {TidyForceOutput,
770 "This option specifies if Tidy should produce output even if errors are "
771 "encountered. Use this option with care - if Tidy reports an error, this "
772 "means Tidy was not able to, or is not sure how to, fix the error, so the "
773 "resulting output may not reflect your intention. "
774 },
775 {TidyEmacs,
776 "This option specifies if Tidy should change the format for reporting "
777 "errors and warnings to a format that is more easily parsed by GNU Emacs. "
778 },
779 {TidyEmacsFile,
780 "Used internally. "
781 },
782 {TidyKeepFileTimes,
783 "This option specifies if Tidy should keep the original modification time "
784 "of files that Tidy modifies in place. The default is no. Setting the "
785 "option to yes allows you to tidy files without causing these files to be "
786 "uploaded to a web server when using a tool such as SiteCopy. Note this "
787 "feature is not supported on some platforms. "
788 },
789 {TidyOutFile,
790 "This option specifies the output file Tidy uses for markup. Normally "
791 "markup is written to \"stdout\". "
792 ,TidyOutFileLinks
793 },
794 {TidyQuiet,
795 "This option specifies if Tidy should output the summary of the numbers "
796 "of errors and warnings, or the welcome or informational messages. "
797 },
798 {TidySlideStyle,
799 "Currently not used. Tidy Classic only. "
800 },
801 {TidyMark,
802 "This option specifies if Tidy should add a meta element to the document "
803 "head to indicate that the document has been tidied. Tidy won't add a meta "
804 "element if one is already present. "
805 },
806 {TidyWriteBack,
807 "This option specifies if Tidy should write back the tidied markup to the "
808 "same file it read from. You are advised to keep copies of important files "
809 "before tidying them, as on rare occasions the result may not be what you "
810 "expect. "
811 },
812 {N_TIDY_OPTIONS,
813 NULL
814 }
815 };
816
817 const TidyOptionDoc* tidyOptGetDocDesc( TidyOptionId optId )
818 {
819 uint i = 0;
820
821 while( option_docs[i].opt != N_TIDY_OPTIONS )
822 {
823 if ( option_docs[i].opt == optId )
824 return &option_docs[i];
825 ++i;
826 }
827 return NULL;
828 }
829
830
831 static char* LevelPrefix( TidyReportLevel level, char* buf, size_t count )
832 {
833 *buf = 0;
834 switch ( level )
835 {
836 case TidyInfo:
837 tmbstrncpy( buf, "Info: ", count );
838 break;
839 case TidyWarning:
840 tmbstrncpy( buf, "Warning: ", count );
841 break;
842 case TidyConfig:
843 tmbstrncpy( buf, "Config: ", count );
844 break;
845 case TidyAccess:
846 tmbstrncpy( buf, "Access: ", count );
847 break;
848 case TidyError:
849 tmbstrncpy( buf, "Error: ", count );
850 break;
851 case TidyBadDocument:
852 tmbstrncpy( buf, "Document: ", count );
853 break;
854 case TidyFatal:
855 tmbstrncpy( buf, "panic: ", count );
856 break;
857 }
858 return buf + tmbstrlen( buf );
859 }
860
861 /* Updates document message counts and
862 ** compares counts to options to see if message
863 ** display should go forward.
864 */
865 static Bool UpdateCount( TidyDocImpl* doc, TidyReportLevel level )
866 {
867 /* keep quiet after <ShowErrors> errors */
868 Bool go = ( doc->errors < cfg(doc, TidyShowErrors) );
869
870 switch ( level )
871 {
872 case TidyInfo:
873 doc->infoMessages++;
874 break;
875 case TidyWarning:
876 doc->warnings++;
877 go = go && cfgBool( doc, TidyShowWarnings );
878 break;
879 case TidyConfig:
880 doc->optionErrors++;
881 break;
882 case TidyAccess:
883 doc->accessErrors++;
884 break;
885 case TidyError:
886 doc->errors++;
887 break;
888 case TidyBadDocument:
889 doc->docErrors++;
890 break;
891 case TidyFatal:
892 /* Ack! */;
893 break;
894 }
895
896 return go;
897 }
898
899 static char* ReportPosition(TidyDocImpl* doc, int line, int col, char* buf, size_t count)
900 {
901 *buf = 0;
902
903 /* Change formatting to be parsable by GNU Emacs */
904 if ( cfgBool(doc, TidyEmacs) && cfgStr(doc, TidyEmacsFile) )
905 tmbsnprintf(buf, count, "%s:%d:%d: ",
906 cfgStr(doc, TidyEmacsFile), line, col);
907 else /* traditional format */
908 tmbsnprintf(buf, count, "line %d column %d - ", line, col);
909 return buf + tmbstrlen( buf );
910 }
911
912 /* General message writing routine.
913 ** Each message is a single warning, error, etc.
914 **
915 ** This routine will keep track of counts and,
916 ** if the caller has set a filter, it will be
917 ** called. The new preferred way of handling
918 ** Tidy diagnostics output is either a) define
919 ** a new output sink or b) install a message
920 ** filter routine.
921 */
922
923 static void messagePos( TidyDocImpl* doc, TidyReportLevel level,
924 int line, int col, ctmbstr msg, va_list args )
925 #ifdef __GNUC__
926 __attribute__((format(printf, 5, 0)))
927 #endif
928 ;
929 static void messagePos( TidyDocImpl* doc, TidyReportLevel level,
930 int line, int col, ctmbstr msg, va_list args )
931 {
932 char messageBuf[ 2048 ];
933 Bool go = UpdateCount( doc, level );
934
935 if ( go )
936 {
937 tmbvsnprintf(messageBuf, sizeof(messageBuf), msg, args);
938 if ( doc->mssgFilt )
939 {
940 TidyDoc tdoc = tidyImplToDoc( doc );
941 go = doc->mssgFilt( tdoc, level, line, col, messageBuf );
942 }
943 }
944
945 if ( go )
946 {
947 char buf[ 64 ];
948 const char *cp;
949 if ( line > 0 && col > 0 )
950 {
951 ReportPosition(doc, line, col, buf, sizeof(buf));
952 for ( cp = buf; *cp; ++cp )
953 WriteChar( *cp, doc->errout );
954 }
955
956 LevelPrefix( level, buf, sizeof(buf) );
957 for ( cp = buf; *cp; ++cp )
958 WriteChar( *cp, doc->errout );
959
960 for ( cp = messageBuf; *cp; ++cp )
961 WriteChar( *cp, doc->errout );
962 WriteChar( '\n', doc->errout );
963 }
964 }
965
966 void message( TidyDocImpl* doc, TidyReportLevel level, ctmbstr msg, ... )
967 {
968 va_list args;
969 va_start( args, msg );
970 messagePos( doc, level, 0, 0, msg, args );
971 va_end( args );
972 }
973
974
975 void messageLexer( TidyDocImpl* doc, TidyReportLevel level, ctmbstr msg, ... )
976 {
977 int line = ( doc->lexer ? doc->lexer->lines : 0 );
978 int col = ( doc->lexer ? doc->lexer->columns : 0 );
979
980 va_list args;
981 va_start( args, msg );
982 messagePos( doc, level, line, col, msg, args );
983 va_end( args );
984 }
985
986 void messageNode( TidyDocImpl* doc, TidyReportLevel level, Node* node,
987 ctmbstr msg, ... )
988 {
989 int line = ( node ? node->line :
990 ( doc->lexer ? doc->lexer->lines : 0 ) );
991 int col = ( node ? node->column :
992 ( doc->lexer ? doc->lexer->columns : 0 ) );
993
994 va_list args;
995 va_start( args, msg );
996 messagePos( doc, level, line, col, msg, args );
997 va_end( args );
998 }
999
1000 void tidy_out( TidyDocImpl* doc, ctmbstr msg, ... )
1001 {
1002 if ( !cfgBool(doc, TidyQuiet) )
1003 {
1004 ctmbstr cp;
1005 char buf[ 2048 ];
1006
1007 va_list args;
1008 va_start( args, msg );
1009 tmbvsnprintf(buf, sizeof(buf), msg, args);
1010 va_end( args );
1011
1012 for ( cp=buf; *cp; ++cp )
1013 WriteChar( *cp, doc->errout );
1014 }
1015 }
1016
1017 void ShowVersion( TidyDocImpl* doc )
1018 {