OSDN Git Service

フォルダ名変更
[wordring-tm/wordring-tm.git] / third-party / tidy-html5-master / src / localize.c
1 /* localize.c -- text strings and routines to handle errors and general messages
2
3   (c) 1998-2008 (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 */
11
12 #include "tidy-int.h"
13 #include "lexer.h"
14 #include "streamio.h"
15 #include "message.h"
16 #include "tmbstr.h"
17 #include "utf8.h"
18 #if !defined(NDEBUG) && defined(_MSC_VER)
19 #include "sprtf.h"
20 #endif
21
22 /* used to point to Web Accessibility Guidelines */
23 #define ACCESS_URL  "http://www.w3.org/WAI/GL"
24
25 /* points to the Adaptive Technology Resource Centre at the
26 ** University of Toronto
27 */
28 #define ATRC_ACCESS_URL  "http://www.aprompt.ca/Tidy/accessibilitychecks.html"
29
30 #include "version.h"
31
32 ctmbstr TY_(ReleaseDate)(void)
33 {
34   return TY_(release_date);
35 }
36
37 ctmbstr tidyLibraryVersion(void)
38 {
39   return TY_(library_version);
40 }
41
42
43 static struct _msgfmt
44 {
45     uint code;
46     ctmbstr fmt;
47 } const msgFormat[] = 
48 {
49 /* ReportEncodingWarning */
50   { ENCODING_MISMATCH,            "specified input encoding (%s) does not match actual input encoding (%s)" }, /* Warning */
51
52 /* ReportEncodingError */
53   { VENDOR_SPECIFIC_CHARS,        "%s invalid character code %s"                                            }, /* Error */
54   { INVALID_SGML_CHARS,           "%s invalid character code %s"                                            }, /* Error */
55   { INVALID_UTF8,                 "%s invalid UTF-8 bytes (char. code %s)"                                  }, /* Error */
56   { INVALID_UTF16,                "%s invalid UTF-16 surrogate pair (char. code %s)"                        }, /* Error */
57   { INVALID_NCR,                  "%s invalid numeric character reference %s"                               }, /* Error */
58
59 /* ReportEntityError */
60   { MISSING_SEMICOLON,            "entity \"%s\" doesn't end in ';'"                                        }, /* Warning in HTML, Error in XML/XHTML */
61   { MISSING_SEMICOLON_NCR,        "numeric character reference \"%s\" doesn't end in ';'"                   }, /* Warning in HTML, Error in XML/XHTML */
62   { UNESCAPED_AMPERSAND,          "unescaped & which should be written as &"                            }, /* Warning in HTML, Error in XHTML */
63   { UNKNOWN_ENTITY,               "unescaped & or unknown entity \"%s\""                                    }, /* Error */
64   { APOS_UNDEFINED,               "named entity ' only defined in XML/XHTML"                           }, /* Error in HTML (should only occur for HTML input) */
65
66 /* ReportAttrError */
67
68   /* attribute name */
69   { INSERTING_ATTRIBUTE,          "%s inserting \"%s\" attribute"                                           }, /* Warning in CheckLINK, Error otherwise */
70   { MISSING_ATTR_VALUE,           "%s attribute \"%s\" lacks value"                                         }, /* Warning in CheckUrl, Error otherwise */
71   { UNKNOWN_ATTRIBUTE,            "%s unknown attribute \"%s\""                                             }, /* Error */
72   { PROPRIETARY_ATTRIBUTE,        "%s proprietary attribute \"%s\""                                         }, /* Error */
73   { JOINING_ATTRIBUTE,            "%s joining values of repeated attribute \"%s\""                          }, /* Error */
74   { XML_ATTRIBUTE_VALUE,          "%s has XML attribute \"%s\""                                             }, /* Error (but deprecated) */
75
76   /* attribute value */
77   { XML_ID_SYNTAX,                "%s ID \"%s\" uses XML ID syntax"                                         }, /* Warning if XHTML, Error if HTML */
78   { 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 */
79   { PROPRIETARY_ATTR_VALUE,       "%s proprietary attribute value \"%s\""                                   }, /* Error */
80   { ANCHOR_NOT_UNIQUE,            "%s anchor \"%s\" already defined"                                        }, /* Error */
81
82   /* attribute name, attribute value */
83   { BAD_ATTRIBUTE_VALUE,          "%s attribute \"%s\" has invalid value \"%s\""                            }, /* Error */
84   { BAD_ATTRIBUTE_VALUE_REPLACED, "%s attribute \"%s\" had invalid value \"%s\" and has been replaced"      }, /* Error */
85   { INVALID_ATTRIBUTE,            "%s attribute name \"%s\" (value=\"%s\") is invalid"                      }, /* Error */
86
87   /* attribute value, attribute name */
88   { REPEATED_ATTRIBUTE,           "%s dropping value \"%s\" for repeated attribute \"%s\""                  }, /* Error */
89
90   /* no arguments */
91   { INVALID_XML_ID,               "%s cannot copy name attribute to id"                                     }, /* Warning */
92   { UNEXPECTED_GT,                "%s missing '>' for end of tag"                                           }, /* Warning if HTML, Error if XML/XHTML */
93   { UNEXPECTED_QUOTEMARK,         "%s unexpected or duplicate quote mark"                                   }, /* Error */
94   { MISSING_QUOTEMARK,            "%s attribute with missing trailing quote mark"                           }, /* Error */
95   { UNEXPECTED_END_OF_FILE_ATTR,  "%s end of file while parsing attributes"                                 }, /* Error */
96   { ID_NAME_MISMATCH,             "%s id and name attribute value mismatch"                                 }, /* Error */
97   { BACKSLASH_IN_URI,             "%s URI reference contains backslash. Typo?"                              }, /* Error */
98   { FIXED_BACKSLASH,              "%s converting backslash in URI to slash"                                 }, /* Error */
99   { ILLEGAL_URI_REFERENCE,        "%s improperly escaped URI reference"                                     }, /* Error */
100   { ESCAPED_ILLEGAL_URI,          "%s escaping malformed URI reference"                                     }, /* Error */
101   { NEWLINE_IN_URI,               "%s discarding newline in URI reference"                                  }, /* Error */
102   { WHITE_IN_URI,                 "%s discarding whitespace in URI reference"                               }, /* Error */
103   { UNEXPECTED_EQUALSIGN,         "%s unexpected '=', expected attribute name"                              }, /* Error */
104   { MISSING_IMAGEMAP,             "%s should use client-side image map"                                     }, /* Warning (but deprecated) */
105
106 /* ReportMissingAttr */
107   { MISSING_ATTRIBUTE,            "%s lacks \"%s\" attribute"                                               }, /* Error */
108 /* ReportWarning */
109   { NESTED_EMPHASIS,              "nested emphasis %s"                                                      }, /* Warning */
110   { NESTED_QUOTATION,             "nested q elements, possible typo."                                       }, /* Warning */
111   { OBSOLETE_ELEMENT,             "replacing obsolete element %s by %s"                                     }, /* Warning */
112   { COERCE_TO_ENDTAG_WARN,        "<%s> is probably intended as </%s>"                                      }, /* Warning */
113   /* HTML5 */
114   { REMOVED_HTML5,                "%s element removed from HTML5"                                           }, /* Warning */
115   { BAD_BODY_HTML5,               "Found attribute on body that is obsolete in HTML5. Use CSS"              }, /* Warning */
116   { BAD_ALIGN_HTML5,              "The align attribute on the %s element is obsolete, Use CSS"              }, /* Wanring */
117
118 /* ReportNotice */
119   { TRIM_EMPTY_ELEMENT,           "trimming empty %s"                                                       }, /* Notice */
120   { REPLACING_ELEMENT,            "replacing %s by %s"                                                      }, /* Notice */
121
122 /* ReportError */
123   { COERCE_TO_ENDTAG,             "<%s> is probably intended as </%s>"                                      }, /* Error */
124   { REPLACING_UNEX_ELEMENT,       "replacing unexpected %s by %s"                                           }, /* Error */
125   { MISSING_ENDTAG_FOR,           "missing </%s>"                                                           }, /* Error */
126   { MISSING_ENDTAG_BEFORE,        "missing </%s> before %s"                                                 }, /* Error */
127   { DISCARDING_UNEXPECTED,        "discarding unexpected %s"                                                }, /* Error */
128   { NON_MATCHING_ENDTAG,          "replacing unexpected %s by </%s>"                                        }, /* Error */
129   { TAG_NOT_ALLOWED_IN,           "%s isn't allowed in <%s> elements"                                       }, /* Error */
130   { MISSING_STARTTAG,             "missing <%s>"                                                            }, /* Error */
131   { UNEXPECTED_ENDTAG,            "unexpected </%s>"                                                }, /* Error */
132   { TOO_MANY_ELEMENTS,            "too many %s elements"                                            }, /* Error */
133   { USING_BR_INPLACE_OF,          "using <br> in place of %s"                                               }, /* Error */
134   { INSERTING_TAG,                "inserting implicit <%s>"                                                 }, /* Error */
135   { CANT_BE_NESTED,               "%s can't be nested"                                                      }, /* Error */
136   { PROPRIETARY_ELEMENT,          "%s is not approved by W3C"                                               }, /* Error */
137   { ILLEGAL_NESTING,              "%s shouldn't be nested"                                                  }, /* Error */
138   { NOFRAMES_CONTENT,             "%s not inside 'noframes' element"                                        }, /* Error */
139   { UNEXPECTED_END_OF_FILE,       "unexpected end of file %s"                                               }, /* Error */
140   { ELEMENT_NOT_EMPTY,            "%s element not empty or not closed"                                      }, /* Error */
141   { UNEXPECTED_ENDTAG_IN,         "unexpected </%s> in <%s>"                                                }, /* Error */
142   { TOO_MANY_ELEMENTS_IN,         "too many %s elements in <%s>"                                            }, /* Error */
143   { UNESCAPED_ELEMENT,            "unescaped %s in pre content"                                             }, /* Error (but deprecated) */
144
145   /* no arguments */
146   { DOCTYPE_AFTER_TAGS,           "<!DOCTYPE> isn't allowed after elements"                                 }, /* Error */
147   { MISSING_TITLE_ELEMENT,        "inserting missing 'title' element"                                       }, /* Error */
148   { INCONSISTENT_VERSION,         "HTML DOCTYPE doesn't match content"                                      }, /* Error */
149   { MISSING_DOCTYPE,              "missing <!DOCTYPE> declaration"                                          }, /* Error */
150   { CONTENT_AFTER_BODY,           "content occurs after end of body"                                        }, /* Error */
151   { MALFORMED_COMMENT,            "adjacent hyphens within comment"                                         }, /* Error */
152   { BAD_COMMENT_CHARS,            "expecting -- or >"                                                       }, /* Error */
153   { BAD_CDATA_CONTENT,            "'<' + '/' + letter not allowed here"                                     }, /* Error */
154   { INCONSISTENT_NAMESPACE,       "HTML namespace doesn't match content"                                    }, /* Error */
155   { SPACE_PRECEDING_XMLDECL,      "removing whitespace preceding XML Declaration"                           }, /* Error */
156   { MALFORMED_DOCTYPE,            "discarding malformed <!DOCTYPE>"                                         }, /* Error */
157   { BAD_XML_COMMENT,              "XML comments can't contain --"                                           }, /* Error (but deprecated) */
158   { DTYPE_NOT_UPPER_CASE,         "SYSTEM, PUBLIC, W3C, DTD, EN must be upper case"                         }, /* Error (but deprecated) */
159   { ENCODING_IO_CONFLICT,         "Output encoding does not work with standard output"                      }, /* Error (but deprecated) */
160
161 /* ReportFatal */
162   { SUSPECTED_MISSING_QUOTE,      "missing quote mark for attribute value"                                  }, /* Error? (not really sometimes) */
163   { DUPLICATE_FRAMESET,           "repeated FRAMESET element"                                               }, /* Error */
164   { UNKNOWN_ELEMENT,              "%s is not recognized!"                                                   }, /* Error */
165   { UNEXPECTED_ENDTAG,            "unexpected </%s>"                                                }, /* Error */
166
167 /* */
168   { PREVIOUS_LOCATION,            "<%s> previously mentioned"                                               }, /* Info */
169
170 #if SUPPORT_ACCESSIBILITY_CHECKS
171
172 /* ReportAccess */
173 /* 
174     List of error/warning messages.  The error code corresponds to
175     the check that is listed in the AERT (HTML specifications).
176 */
177   { IMG_MISSING_ALT,                               "[1.1.1.1]: <img> missing 'alt' text."                                     }, /* Access */
178   { IMG_ALT_SUSPICIOUS_FILENAME,                   "[1.1.1.2]: suspicious 'alt' text (filename)."                             }, /* Access */
179   { IMG_ALT_SUSPICIOUS_FILE_SIZE,                  "[1.1.1.3]: suspicious 'alt' text (file size)."                            }, /* Access */
180   { IMG_ALT_SUSPICIOUS_PLACEHOLDER,                "[1.1.1.4]: suspicious 'alt' text (placeholder)."                          }, /* Access */
181   { IMG_ALT_SUSPICIOUS_TOO_LONG,                   "[1.1.1.10]: suspicious 'alt' text (too long)."                            }, /* Access */
182   { IMG_MISSING_LONGDESC_DLINK,                    "[1.1.2.1]: <img> missing 'longdesc' and d-link."                          }, /* Access */
183   { IMG_MISSING_DLINK,                             "[1.1.2.2]: <img> missing d-link."                                         }, /* Access */
184   { IMG_MISSING_LONGDESC,                          "[1.1.2.3]: <img> missing 'longdesc'."                                     }, /* Access */
185   { IMG_BUTTON_MISSING_ALT,                        "[1.1.3.1]: <img> (button) missing 'alt' text."                            }, /* Access */
186   { APPLET_MISSING_ALT,                            "[1.1.4.1]: <applet> missing alternate content."                           }, /* Access */
187   { OBJECT_MISSING_ALT,                            "[1.1.5.1]: <object> missing alternate content."                           }, /* Access */
188   { AUDIO_MISSING_TEXT_WAV,                        "[1.1.6.1]: audio missing text transcript (wav)."                          }, /* Access */
189   { AUDIO_MISSING_TEXT_AU,                         "[1.1.6.2]: audio missing text transcript (au)."                           }, /* Access */
190   { AUDIO_MISSING_TEXT_AIFF,                       "[1.1.6.3]: audio missing text transcript (aiff)."                         }, /* Access */
191   { AUDIO_MISSING_TEXT_SND,                        "[1.1.6.4]: audio missing text transcript (snd)."                          }, /* Access */
192   { AUDIO_MISSING_TEXT_RA,                         "[1.1.6.5]: audio missing text transcript (ra)."                           }, /* Access */
193   { AUDIO_MISSING_TEXT_RM,                         "[1.1.6.6]: audio missing text transcript (rm)."                           }, /* Access */
194   { FRAME_MISSING_LONGDESC,                        "[1.1.8.1]: <frame> may require 'longdesc'."                               }, /* Access */
195   { AREA_MISSING_ALT,                              "[1.1.9.1]: <area> missing 'alt' text."                                    }, /* Access */
196   { SCRIPT_MISSING_NOSCRIPT,                       "[1.1.10.1]: <script> missing <noscript> section."                         }, /* Access */
197   { ASCII_REQUIRES_DESCRIPTION,                    "[1.1.12.1]: ascii art requires description."                              }, /* Access */
198   { IMG_MAP_SERVER_REQUIRES_TEXT_LINKS,            "[1.2.1.1]: image map (server-side) requires text links."                  }, /* Access */
199   { MULTIMEDIA_REQUIRES_TEXT,                      "[1.4.1.1]: multimedia requires synchronized text equivalents."            }, /* Access */
200   { IMG_MAP_CLIENT_MISSING_TEXT_LINKS,             "[1.5.1.1]: image map (client-side) missing text links."                   }, /* Access */
201   { INFORMATION_NOT_CONVEYED_IMAGE,                "[2.1.1.1]: ensure information not conveyed through color alone (image)."  }, /* Access */
202   { INFORMATION_NOT_CONVEYED_APPLET,               "[2.1.1.2]: ensure information not conveyed through color alone (applet)." }, /* Access */
203   { INFORMATION_NOT_CONVEYED_OBJECT,               "[2.1.1.3]: ensure information not conveyed through color alone (object)." }, /* Access */
204   { INFORMATION_NOT_CONVEYED_SCRIPT,               "[2.1.1.4]: ensure information not conveyed through color alone (script)." }, /* Access */
205   { INFORMATION_NOT_CONVEYED_INPUT,                "[2.1.1.5]: ensure information not conveyed through color alone (input)."  }, /* Access */
206   { COLOR_CONTRAST_TEXT,                           "[2.2.1.1]: poor color contrast (text)."                                   }, /* Access */
207   { COLOR_CONTRAST_LINK,                           "[2.2.1.2]: poor color contrast (link)."                                   }, /* Access */
208   { COLOR_CONTRAST_ACTIVE_LINK,                    "[2.2.1.3]: poor color contrast (active link)."                            }, /* Access */
209   { COLOR_CONTRAST_VISITED_LINK,                   "[2.2.1.4]: poor color contrast (visited link)."                           }, /* Access */
210   { DOCTYPE_MISSING,                               "[3.2.1.1]: <doctype> missing."                                            }, /* Access */
211   { STYLE_SHEET_CONTROL_PRESENTATION,              "[3.3.1.1]: use style sheets to control presentation."                     }, /* Access */
212   { HEADERS_IMPROPERLY_NESTED,                     "[3.5.1.1]: headers improperly nested."                                    }, /* Access */
213   { POTENTIAL_HEADER_BOLD,                         "[3.5.2.1]: potential header (bold)."                                      }, /* Access */
214   { POTENTIAL_HEADER_ITALICS,                      "[3.5.2.2]: potential header (italics)."                                   }, /* Access */
215   { POTENTIAL_HEADER_UNDERLINE,                    "[3.5.2.3]: potential header (underline)."                                 }, /* Access */
216   { HEADER_USED_FORMAT_TEXT,                       "[3.5.3.1]: header used to format text."                                   }, /* Access */
217   { LIST_USAGE_INVALID_UL,                         "[3.6.1.1]: list usage invalid <ul>."                                      }, /* Access */
218   { LIST_USAGE_INVALID_OL,                         "[3.6.1.2]: list usage invalid <ol>."                                      }, /* Access */
219   { LIST_USAGE_INVALID_LI,                         "[3.6.1.4]: list usage invalid <li>."                                      }, /* Access */
220   { INDICATE_CHANGES_IN_LANGUAGE,                  "[4.1.1.1]: indicate changes in language."                                 }, /* Access */
221   { LANGUAGE_NOT_IDENTIFIED,                       "[4.3.1.1]: language not identified."                                      }, /* Access */
222   { LANGUAGE_INVALID,                              "[4.3.1.2]: language attribute invalid."                                   }, /* Access */
223   { DATA_TABLE_MISSING_HEADERS,                    "[5.1.2.1]: data <table> missing row/column headers (all)."                }, /* Access */
224   { DATA_TABLE_MISSING_HEADERS_COLUMN,             "[5.1.2.2]: data <table> missing row/column headers (1 col)."              }, /* Access */
225   { DATA_TABLE_MISSING_HEADERS_ROW,                "[5.1.2.3]: data <table> missing row/column headers (1 row)."              }, /* Access */
226   { DATA_TABLE_REQUIRE_MARKUP_COLUMN_HEADERS,      "[5.2.1.1]: data <table> may require markup (column headers)."             }, /* Access */
227   { DATA_TABLE_REQUIRE_MARKUP_ROW_HEADERS,         "[5.2.1.2]: data <table> may require markup (row headers)."                }, /* Access */
228   { LAYOUT_TABLES_LINEARIZE_PROPERLY,              "[5.3.1.1]: verify layout tables linearize properly."                      }, /* Access */
229   { LAYOUT_TABLE_INVALID_MARKUP,                   "[5.4.1.1]: invalid markup used in layout <table>."                        }, /* Access */
230   { TABLE_MISSING_SUMMARY,                         "[5.5.1.1]: <table> missing summary."                                      }, /* Access */
231   { TABLE_SUMMARY_INVALID_NULL,                    "[5.5.1.2]: <table> summary invalid (null)."                               }, /* Access */
232   { TABLE_SUMMARY_INVALID_SPACES,                  "[5.5.1.3]: <table> summary invalid (spaces)."                             }, /* Access */
233   { TABLE_SUMMARY_INVALID_PLACEHOLDER,             "[5.5.1.6]: <table> summary invalid (placeholder text)."                   }, /* Access */
234   { TABLE_MISSING_CAPTION,                         "[5.5.2.1]: <table> missing <caption>."                                    }, /* Access */
235   { TABLE_MAY_REQUIRE_HEADER_ABBR,                 "[5.6.1.1]: <table> may require header abbreviations."                     }, /* Access */
236   { TABLE_MAY_REQUIRE_HEADER_ABBR_NULL,            "[5.6.1.2]: <table> header abbreviations invalid (null)."                  }, /* Access */
237   { TABLE_MAY_REQUIRE_HEADER_ABBR_SPACES,          "[5.6.1.3]: <table> header abbreviations invalid (spaces)."                }, /* Access */
238   { STYLESHEETS_REQUIRE_TESTING_LINK,              "[6.1.1.1]: style sheets require testing (link)."                          }, /* Access */
239   { STYLESHEETS_REQUIRE_TESTING_STYLE_ELEMENT,     "[6.1.1.2]: style sheets require testing (style element)."                 }, /* Access */
240   { STYLESHEETS_REQUIRE_TESTING_STYLE_ATTR,        "[6.1.1.3]: style sheets require testing (style attribute)."               }, /* Access */
241   { FRAME_SRC_INVALID,                             "[6.2.1.1]: <frame> source invalid."                                       }, /* Access */
242   { TEXT_EQUIVALENTS_REQUIRE_UPDATING_APPLET,      "[6.2.2.1]: text equivalents require updating (applet)."                   }, /* Access */
243   { TEXT_EQUIVALENTS_REQUIRE_UPDATING_SCRIPT,      "[6.2.2.2]: text equivalents require updating (script)."                   }, /* Access */
244   { TEXT_EQUIVALENTS_REQUIRE_UPDATING_OBJECT,      "[6.2.2.3]: text equivalents require updating (object)."                   }, /* Access */
245   { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_SCRIPT,   "[6.3.1.1]: programmatic objects require testing (script)."                }, /* Access */
246   { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_OBJECT,   "[6.3.1.2]: programmatic objects require testing (object)."                }, /* Access */
247   { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_EMBED,    "[6.3.1.3]: programmatic objects require testing (embed)."                 }, /* Access */
248   { PROGRAMMATIC_OBJECTS_REQUIRE_TESTING_APPLET,   "[6.3.1.4]: programmatic objects require testing (applet)."                }, /* Access */
249   { FRAME_MISSING_NOFRAMES,                        "[6.5.1.1]: <frameset> missing <noframes> section."                        }, /* Access */
250   { NOFRAMES_INVALID_NO_VALUE,                     "[6.5.1.2]: <noframes> section invalid (no value)."                        }, /* Access */
251   { NOFRAMES_INVALID_CONTENT,                      "[6.5.1.3]: <noframes> section invalid (content)."                         }, /* Access */
252   { NOFRAMES_INVALID_LINK,                         "[6.5.1.4]: <noframes> section invalid (link)."                            }, /* Access */
253   { REMOVE_FLICKER_SCRIPT,                         "[7.1.1.1]: remove flicker (script)."                                      }, /* Access */
254   { REMOVE_FLICKER_OBJECT,                         "[7.1.1.2]: remove flicker (object)."                                      }, /* Access */
255   { REMOVE_FLICKER_EMBED,                          "[7.1.1.3]: remove flicker (embed)."                                       }, /* Access */
256   { REMOVE_FLICKER_APPLET,                         "[7.1.1.4]: remove flicker (applet)."                                      }, /* Access */
257   { REMOVE_FLICKER_ANIMATED_GIF,                   "[7.1.1.5]: remove flicker (animated gif)."                                }, /* Access */
258   { REMOVE_BLINK_MARQUEE,                          "[7.2.1.1]: remove blink/marquee."                                         }, /* Access */
259   { REMOVE_AUTO_REFRESH,                           "[7.4.1.1]: remove auto-refresh."                                          }, /* Access */
260   { REMOVE_AUTO_REDIRECT,                          "[7.5.1.1]: remove auto-redirect."                                         }, /* Access */
261   { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_SCRIPT, "[8.1.1.1]: ensure programmatic objects are accessible (script)."          }, /* Access */
262   { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_OBJECT, "[8.1.1.2]: ensure programmatic objects are accessible (object)."          }, /* Access */
263   { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_APPLET, "[8.1.1.3]: ensure programmatic objects are accessible (applet)."          }, /* Access */
264   { ENSURE_PROGRAMMATIC_OBJECTS_ACCESSIBLE_EMBED,  "[8.1.1.4]: ensure programmatic objects are accessible (embed)."           }, /* Access */
265   { IMAGE_MAP_SERVER_SIDE_REQUIRES_CONVERSION,     "[9.1.1.1]: image map (server-side) requires conversion."                  }, /* Access */
266   { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_DOWN,  "[9.3.1.1]: <script> not keyboard accessible (onMouseDown)."               }, /* Access */
267   { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_UP,    "[9.3.1.2]: <script> not keyboard accessible (onMouseUp)."                 }, /* Access */
268   { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_CLICK,       "[9.3.1.3]: <script> not keyboard accessible (onClick)."                   }, /* Access */
269   { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OVER,  "[9.3.1.4]: <script> not keyboard accessible (onMouseOver)."               }, /* Access */
270   { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_OUT,   "[9.3.1.5]: <script> not keyboard accessible (onMouseOut)."                }, /* Access */
271   { SCRIPT_NOT_KEYBOARD_ACCESSIBLE_ON_MOUSE_MOVE,  "[9.3.1.6]: <script> not keyboard accessible (onMouseMove)."               }, /* Access */
272   { NEW_WINDOWS_REQUIRE_WARNING_NEW,               "[10.1.1.1]: new windows require warning (_new)."                          }, /* Access */
273   { NEW_WINDOWS_REQUIRE_WARNING_BLANK,             "[10.1.1.2]: new windows require warning (_blank)."                        }, /* Access */
274   { FORM_CONTROL_REQUIRES_DEFAULT_TEXT,            "[10.4.1.1]: form control requires default text."                          }, /* Access */
275   { FORM_CONTROL_DEFAULT_TEXT_INVALID_NULL,        "[10.4.1.2]: form control default text invalid (null)."                    }, /* Access */
276   { FORM_CONTROL_DEFAULT_TEXT_INVALID_SPACES,      "[10.4.1.3]: form control default text invalid (spaces)."                  }, /* Access */
277   { REPLACE_DEPRECATED_HTML_APPLET,                "[11.2.1.1]: replace deprecated html <applet>."                            }, /* Access */
278   { REPLACE_DEPRECATED_HTML_BASEFONT,              "[11.2.1.2]: replace deprecated html <basefont>."                          }, /* Access */
279   { REPLACE_DEPRECATED_HTML_CENTER,                "[11.2.1.3]: replace deprecated html <center>."                            }, /* Access */
280   { REPLACE_DEPRECATED_HTML_DIR,                   "[11.2.1.4]: replace deprecated html <dir>."                               }, /* Access */
281   { REPLACE_DEPRECATED_HTML_FONT,                  "[11.2.1.5]: replace deprecated html <font>."                              }, /* Access */
282   { REPLACE_DEPRECATED_HTML_ISINDEX,               "[11.2.1.6]: replace deprecated html <isindex>."                           }, /* Access */
283   { REPLACE_DEPRECATED_HTML_MENU,                  "[11.2.1.7]: replace deprecated html <menu>."                              }, /* Access */
284   { REPLACE_DEPRECATED_HTML_S,                     "[11.2.1.8]: replace deprecated html <s>."                                 }, /* Access */
285   { REPLACE_DEPRECATED_HTML_STRIKE,                "[11.2.1.9]: replace deprecated html <strike>."                            }, /* Access */
286   { REPLACE_DEPRECATED_HTML_U,                     "[11.2.1.10]: replace deprecated html <u>."                                }, /* Access */
287   { FRAME_MISSING_TITLE,                           "[12.1.1.1]: <frame> missing title."                                       }, /* Access */
288   { FRAME_TITLE_INVALID_NULL,                      "[12.1.1.2]: <frame> title invalid (null)."                                }, /* Access */
289   { FRAME_TITLE_INVALID_SPACES,                    "[12.1.1.3]: <frame> title invalid (spaces)."                              }, /* Access */
290   { ASSOCIATE_LABELS_EXPLICITLY,                   "[12.4.1.1]: associate labels explicitly with form controls."              }, /* Access */
291   { ASSOCIATE_LABELS_EXPLICITLY_FOR,               "[12.4.1.2]: associate labels explicitly with form controls (for)."        }, /* Access */
292   { ASSOCIATE_LABELS_EXPLICITLY_ID,                "[12.4.1.3]: associate labels explicitly with form controls (id)."         }, /* Access */
293   { LINK_TEXT_NOT_MEANINGFUL,                      "[13.1.1.1]: link text not meaningful."                                    }, /* Access */
294   { LINK_TEXT_MISSING,                             "[13.1.1.2]: link text missing."                                           }, /* Access */
295   { LINK_TEXT_TOO_LONG,                            "[13.1.1.3]: link text too long."                                          }, /* Access */
296   { LINK_TEXT_NOT_MEANINGFUL_CLICK_HERE,           "[13.1.1.4]: link text not meaningful (click here)."                       }, /* Access */
297   { METADATA_MISSING,                              "[13.2.1.1]: Metadata missing."                                            }, /* Access */
298   { METADATA_MISSING_REDIRECT_AUTOREFRESH,         "[13.2.1.3]: Metadata missing (redirect/auto-refresh)."                    }, /* Access */
299   { SKIPOVER_ASCII_ART,                            "[13.10.1.1]: skip over ascii art."                                        }, /* Access */
300
301 #endif /* SUPPORT_ACCESSIBILITY_CHECKS */
302
303   /* must be last */
304   { 0,                                             NULL                                                                       }
305 };
306
307 static ctmbstr GetFormatFromCode(uint code)
308 {
309     uint i;
310
311     for (i = 0; msgFormat[i].fmt; ++i)
312         if (msgFormat[i].code == code)
313             return msgFormat[i].fmt;
314
315     return NULL;
316 }
317
318 /*
319   Documentation of configuration options
320 */
321
322 /* Cross references */
323 static const TidyOptionId TidyXmlDeclLinks[] =
324   { TidyCharEncoding, TidyOutCharEncoding, TidyUnknownOption };
325 static const TidyOptionId TidyJoinClassesLinks[] =
326   { TidyJoinStyles, TidyDuplicateAttrs, TidyUnknownOption };
327 static const TidyOptionId TidyJoinStylesLinks[] =
328   { TidyJoinClasses, TidyDuplicateAttrs, TidyUnknownOption };
329 static const TidyOptionId TidyDuplicateAttrsLinks[] =
330   { TidyJoinClasses, TidyJoinStyles, TidyUnknownOption };
331 static const TidyOptionId TidyIndentContentLinks[] =
332   { TidyIndentSpaces, TidyUnknownOption };
333 static const TidyOptionId TidyIndentSpacesLinks[] =
334   { TidyIndentContent, TidyUnknownOption };
335 static const TidyOptionId TidyWrapAttValsLinks[] =
336   { TidyWrapScriptlets, TidyLiteralAttribs, TidyUnknownOption };
337 static const TidyOptionId TidyWrapScriptletsLinks[] =
338   { TidyWrapAttVals, TidyUnknownOption };
339 static const TidyOptionId TidyCharEncodingLinks[] =
340   { TidyInCharEncoding, TidyOutCharEncoding, TidyUnknownOption };
341 static const TidyOptionId TidyInCharEncodingLinks[] =
342   { TidyCharEncoding, TidyUnknownOption };
343 static const TidyOptionId TidyOutCharEncodingLinks[] =
344   { TidyCharEncoding, TidyUnknownOption };
345 static const TidyOptionId TidyErrFileLinks[] =
346   { TidyOutFile, TidyUnknownOption };
347 static const TidyOptionId TidyOutFileLinks[] =
348   { TidyErrFile, TidyUnknownOption };
349 static const TidyOptionId TidyBlockTagsLinks[] =
350   { TidyEmptyTags, TidyInlineTags, TidyPreTags, TidyUnknownOption };
351 static const TidyOptionId TidyEmptyTagsLinks[] =
352   { TidyBlockTags, TidyInlineTags, TidyPreTags, TidyUnknownOption };
353 static const TidyOptionId TidyInlineTagsLinks[] =
354   { TidyBlockTags, TidyEmptyTags, TidyPreTags, TidyUnknownOption };
355 static const TidyOptionId TidyPreTagsLinks[] =
356   { TidyBlockTags, TidyEmptyTags, TidyInlineTags, TidyUnknownOption };
357 static const TidyOptionId TidyMergeDivsLinks[] =
358   { TidyMakeClean, TidyMergeSpans, TidyUnknownOption };
359 static const TidyOptionId TidyMergeSpansLinks[] =
360   { TidyMakeClean, TidyMergeDivs, TidyUnknownOption };
361 static const TidyOptionId TidyAsciiCharsLinks[] =
362   { TidyMakeClean, TidyUnknownOption };
363 static const TidyOptionId TidyNumEntitiesLinks[] =
364   { TidyDoctype, TidyPreserveEntities, TidyUnknownOption };
365 static const TidyOptionId TidyDropFontTagsLinks[] =
366   { TidyMakeClean, TidyUnknownOption };
367 static const TidyOptionId TidyMakeCleanTagsLinks[] =
368   { TidyDropFontTags, TidyUnknownOption };
369 static const TidyOptionId TidyGDocCleanLinks[] =
370   { TidyMakeClean, TidyUnknownOption };
371
372 /* Documentation of options */
373 static const TidyOptionDoc option_docs[] =
374 {
375   {TidyXmlDecl,
376    "This option specifies if Tidy should add the XML declaration when "
377    "outputting XML or XHTML. Note that if the input already includes an "
378    "&lt;?xml ... ?&gt; declaration then this option will be ignored. "
379    "If the encoding for the output is different from \"ascii\", one of the "
380    "utf encodings or \"raw\", the declaration is always added as required by "
381    "the XML standard. "
382    , TidyXmlDeclLinks
383   },
384   {TidyXmlSpace,
385    "This option specifies if Tidy should add xml:space=\"preserve\" to "
386    "elements such as &lt;PRE&gt;, &lt;STYLE&gt; and &lt;SCRIPT&gt; when "
387    "generating XML. This is needed if the whitespace in such elements is to "
388    "be parsed appropriately without having access to the DTD. "
389   },
390   {TidyAltText,
391    "This option specifies the default \"alt=\" text Tidy uses for "
392    "&lt;IMG&gt; attributes. This feature is dangerous as it suppresses "
393    "further accessibility warnings. You are responsible for making your "
394    "documents accessible to people who can not see the images! "
395   },
396   {TidyXmlPIs,
397    "This option specifies if Tidy should change the parsing of processing "
398    "instructions to require ?&gt; as the terminator rather than &gt;. This "
399    "option is automatically set if the input is in XML. "
400   },
401   {TidyMakeBare,
402    "This option specifies if Tidy should strip Microsoft specific HTML "
403    "from Word 2000 documents, and output spaces rather than non-breaking "
404    "spaces where they exist in the input. "
405   },
406   {TidyCSSPrefix,
407    "This option specifies the prefix that Tidy uses for styles rules. By "
408    "default, \"c\" will be used. "
409   },
410   {TidyMakeClean,
411    "This option specifies if Tidy "
412    "should strip out surplus presentational tags and attributes replacing "
413    "them by style rules and structural markup as appropriate. It works well "
414    "on the HTML saved by Microsoft Office products. "
415    , TidyMakeCleanTagsLinks
416   },
417   {TidyGDocClean,
418    "This option specifies if Tidy "
419    "should enable specific behavior for cleaning up HTML exported from "
420    "Google Docs. "
421    , TidyMakeCleanTagsLinks
422   },
423   {TidyDoctype,
424    "This option specifies the DOCTYPE declaration generated by Tidy.<br />"
425    "If set to \"omit\" the output won't contain a DOCTYPE declaration.<br />"
426    "If set to \"html5\" the DOCTYPE is set to \"&lt;!DOCTYPE html>\".<br />"
427    "If set to \"auto\" (the default) Tidy will use an educated guess based "
428    "upon the contents of the document.<br />"
429    "If set to \"strict\", Tidy will set the DOCTYPE to the HTML4 or XHTML1 "
430    "strict DTD.<br />"
431    "If set to \"loose\", the DOCTYPE is set to the HTML4 or XHTML1 loose "
432    "(transitional) DTD. <br />"
433    "Alternatively, you can supply a string for the formal public identifier "
434    "(FPI).<br />"
435    "<br />"
436    "For example: <br />"
437    "doctype: \"-//ACME//DTD HTML 3.14159//EN\"<br />"
438    "<br />"
439    "If you specify the FPI for an XHTML document, Tidy will set the "
440    "system identifier to an empty string. For an HTML document, Tidy adds a "
441    "system identifier only if one was already present in order to preserve "
442    "the processing mode of some browsers. Tidy leaves the DOCTYPE for "
443    "generic XML documents unchanged. <code>--doctype omit</code> implies "
444    "<code>--numeric-entities yes</code>. This option does not offer a "
445    "validation of the document conformance. "
446   },
447   {TidyDropEmptyElems,
448    "This option specifies if Tidy should discard empty elements. "
449   },
450   {TidyDropEmptyParas,
451    "This option specifies if Tidy should discard empty paragraphs. "
452   },
453   {TidyDropFontTags,
454    "This option specifies if Tidy should discard &lt;FONT&gt; and "
455    "&lt;CENTER&gt; tags without creating the corresponding style rules. This "
456    "option can be set independently of the clean option. "
457    , TidyDropFontTagsLinks
458   },
459   {TidyDropPropAttrs,
460    "This option specifies if Tidy should strip out proprietary attributes, "
461    "such as MS data binding attributes. "
462   },
463   {TidyEncloseBlockText,
464    "This option specifies if Tidy should insert a &lt;P&gt; element to "
465    "enclose any text it finds in any element that allows mixed content for "
466    "HTML transitional but not HTML strict. "
467   },
468   {TidyEncloseBodyText,
469    "This option specifies if Tidy should enclose any text it finds in the "
470    "body element within a &lt;P&gt; element. This is useful when you want to "
471    "take existing HTML and use it with a style sheet. "
472   },
473   {TidyEscapeCdata,
474    "This option specifies if Tidy should convert &lt;![CDATA[]]&gt; "
475    "sections to normal text. "
476   },
477   {TidyFixComments,
478    "This option specifies if Tidy should replace unexpected hyphens with "
479    "\"=\" characters when it comes across adjacent hyphens. The default is "
480    "yes. This option is provided for users of Cold Fusion which uses the "
481    "comment syntax: &lt;!--- ---&gt; "
482   },
483   {TidyFixUri,
484    "This option specifies if Tidy should check attribute values that carry "
485    "URIs for illegal characters and if such are found, escape them as HTML 4 "
486    "recommends. "
487   },
488   {TidyHideComments,
489    "This option specifies if Tidy should print out comments. "
490   },
491   {TidyCoerceEndTags,
492    "This option specifies if Tidy should coerce a start tag into an end tag "
493    "in cases where it looks like an end tag was probably intended; "
494    "for example, given &lt;span&gt;foo &lt;b&gt;bar&lt;b&gt; baz&lt;/span&gt;, "
495    "Tidy will output &lt;span&gt;foo &lt;b&gt;bar&lt;/b&gt; baz&lt;/span&gt;. "
496   },
497   {TidyOmitOptionalTags,
498    "This option specifies if Tidy should omit optional start tags and end tags "
499    "when generating output. Setting this option causes all tags for the "
500    "html, head, and body elements to be omitted from output, as well as such "
501    "end tags as &lt;/p&gt;, &lt;/li&gt;, &lt;/dt&gt;, &lt;/dd&gt;, "
502    "&lt;/option&gt;, &lt;/tr&gt;, &lt;/td&gt;, and &lt;/th&gt;. "
503    "This option is ignored for XML output. "
504   },
505   {TidyHideEndTags,
506    "This option is an alias for omit-optional-tags. "
507   },
508   {TidyIndentCdata,
509    "This option specifies if Tidy should indent &lt;![CDATA[]]&gt; sections. "
510   },
511   {TidyXmlTags,
512    "This option specifies if Tidy should use the XML parser rather than the "
513    "error correcting HTML parser. "
514   },
515   {TidyJoinClasses,
516    "This option specifies if Tidy should combine class names to generate "
517    "a single new class name, if multiple class assignments are detected on "
518    "an element. "
519    , TidyJoinClassesLinks
520   },
521   {TidyJoinStyles,
522    "This option specifies if Tidy should combine styles to generate a single "
523    "new style, if multiple style values are detected on an element. "
524    , TidyJoinStylesLinks
525   },
526   {TidyLogicalEmphasis,
527    "This option specifies if Tidy should replace any occurrence of &lt;I&gt; "
528    "by &lt;EM&gt; and any occurrence of &lt;B&gt; by &lt;STRONG&gt;. In both "
529    "cases, the attributes are preserved unchanged. This option can be set "
530    "independently of the clean and drop-font-tags options. "
531   },
532   {TidyLowerLiterals,
533    "This option specifies if Tidy should convert the value of an attribute "
534    "that takes a list of predefined values to lower case. This is required "
535    "for XHTML documents. "
536   },
537   {TidyMergeEmphasis,
538    "This option specifies if Tidy should merge nested &lt;b&gt; and &lt;i&gt; "
539    "elements; for example, for the case "
540    "&lt;b class=\"rtop-2\"&gt;foo &lt;b class=\"r2-2\"&gt;bar&lt;/b&gt; baz&lt;/b&gt;, "
541    "Tidy will output  &lt;b class=\"rtop-2\"&gt;foo bar baz&lt;/b&gt;. "
542   },
543   {TidyMergeDivs,
544    "Can be used to modify behavior of -c (--clean yes) option. "
545    "This option specifies if Tidy should merge nested &lt;div&gt; such as "
546    "\"&lt;div&gt;&lt;div&gt;...&lt;/div&gt;&lt;/div&gt;\". If set to "
547    "\"auto\", the attributes of the inner &lt;div&gt; are moved to the "
548    "outer one. As well, nested &lt;div&gt; with ID attributes are not "
549    "merged. If set to \"yes\", the attributes of the inner &lt;div&gt; "
550    "are discarded with the exception of \"class\" and \"style\". "
551    ,TidyMergeDivsLinks
552   },
553   {TidyMergeSpans,
554    "Can be used to modify behavior of -c (--clean yes) option. "
555    "This option specifies if Tidy should merge nested &lt;span&gt; such as "
556    "\"&lt;span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;\". The algorithm "
557    "is identical to the one used by --merge-divs. "
558    ,TidyMergeSpansLinks
559   },
560 #if SUPPORT_ASIAN_ENCODINGS
561   {TidyNCR,
562    "This option specifies if Tidy should allow numeric character references. "
563   },
564 #endif
565   {TidyBlockTags,
566    "This option specifies new block-level tags. This option takes a space or "
567    "comma separated list of tag names. Unless you declare new tags, Tidy will "
568    "refuse to generate a tidied file if the input includes previously unknown "
569    "tags. Note you can't change the content model for elements such as "
570    "&lt;TABLE&gt;, &lt;UL&gt;, &lt;OL&gt; and &lt;DL&gt;. This option is "
571    "ignored in XML mode. "
572    ,TidyBlockTagsLinks
573   },
574   {TidyEmptyTags,
575    "This option specifies new empty inline tags. This option takes a space "
576    "or comma separated list of tag names. Unless you declare new tags, Tidy "
577    "will refuse to generate a tidied file if the input includes previously "
578    "unknown tags. Remember to also declare empty tags as either inline or "
579    "blocklevel. This option is ignored in XML mode. "
580    ,TidyEmptyTagsLinks
581   },
582   {TidyInlineTags,
583    "This option specifies new non-empty inline tags. This option takes a "
584    "space or comma separated list of tag names. Unless you declare new tags, "
585    "Tidy will refuse to generate a tidied file if the input includes "
586    "previously unknown tags. This option is ignored in XML mode. "
587    ,TidyInlineTagsLinks
588   },
589   { TidyPreTags,
590     "This option specifies "
591     "new tags that are to be processed in exactly the same way as HTML's "
592     "&lt;PRE&gt; element. This option takes a space or comma separated list "
593     "of tag names. Unless you declare new tags, Tidy will refuse to generate "
594     "a tidied file if the input includes previously unknown tags. Note you "
595     "can not as yet add new CDATA elements (similar to &lt;SCRIPT&gt;). "
596     "This option is ignored in XML mode. "
597     ,TidyPreTagsLinks
598   },
599   {TidyNumEntities,
600    "This option specifies if Tidy should output entities other than the "
601    "built-in HTML entities (&amp;amp;, &amp;lt;, &amp;gt; and &amp;quot;) in "
602    "the numeric rather than the named entity form. Only entities compatible "
603    "with the DOCTYPE declaration generated are used. Entities that can be "
604    "represented in the output encoding are translated correspondingly. "
605     ,TidyNumEntitiesLinks
606   },
607   {TidyHtmlOut,
608    "This option specifies if Tidy should generate pretty printed output, "
609    "writing it as HTML. "
610   },
611   {TidyXhtmlOut,
612    "This option specifies if Tidy should generate pretty printed output, "
613    "writing it as extensible HTML. "
614    "This option causes Tidy to set the DOCTYPE and default namespace as "
615    "appropriate to XHTML. If a DOCTYPE or namespace is given they will "
616    "checked for consistency with the content of the document. In the case of "
617    "an inconsistency, the corrected values will appear in the output. For "
618    "XHTML, entities can be written as named or numeric entities according to "
619    "the setting of the \"numeric-entities\" option. The original case of tags "
620    "and attributes will be preserved, regardless of other options. "
621   },
622   {TidyXmlOut,
623    "This option specifies if Tidy should pretty print output, writing it as "
624    "well-formed XML. Any entities not defined in XML 1.0 will be written as "
625    "numeric entities to allow them to be parsed by a XML parser. The original "
626    "case of tags and attributes will be preserved, regardless of other "
627    "options. "
628   },
629   {TidyQuoteAmpersand,
630    "This option specifies if Tidy should output unadorned &amp; characters as "
631    "&amp;amp;. "
632   },
633   {TidyQuoteMarks,
634    "This option specifies if Tidy should output &quot; characters as "
635    "&amp;quot; as is preferred by some editing environments. The apostrophe "
636    "character ' is written out as &amp;#39; since many web browsers don't yet "
637    "support &amp;apos;. "
638   },
639   {TidyQuoteNbsp,
640    "This option specifies if Tidy should output non-breaking space characters "
641    "as entities, rather than as the Unicode character value 160 (decimal). "
642   },
643   {TidyDuplicateAttrs,
644    "This option specifies if Tidy should keep the first or last attribute, if "
645    "an attribute is repeated, e.g. has two align attributes. "
646    , TidyDuplicateAttrsLinks
647   },
648   {TidySortAttributes,
649    "This option specifies that tidy should sort attributes within an element "
650    "using the specified sort algorithm. If set to \"alpha\", the algorithm is "
651    "an ascending alphabetic sort. "
652   },
653   {TidyReplaceColor,
654    "This option specifies if Tidy should replace numeric values in color "
655    "attributes by HTML/XHTML color names where defined, e.g. replace "
656    "\"#ffffff\" with \"white\". "
657   },
658   {TidyBodyOnly,
659    "This option specifies if Tidy should print only the contents of the "
660    "body tag as an HTML fragment. If set to \"auto\", this is performed only "
661    "if the body tag has been inferred. Useful for incorporating "
662    "existing whole pages as a portion of another page. "
663    "This option has no effect if XML output is requested. "
664   },
665   {TidyUpperCaseAttrs,
666    "This option specifies if Tidy should output attribute names in upper "
667    "case. The default is no, which results in lower case attribute names, "
668    "except for XML input, where the original case is preserved. "
669   },
670   {TidyUpperCaseTags,
671    "This option specifies if Tidy should output tag names in upper case. "
672    "The default is no, which results in lower case tag names, except for XML "
673    "input, where the original case is preserved. "
674   },
675   {TidyWord2000,
676    "This option specifies if Tidy should go to great pains to strip out all "
677    "the surplus stuff Microsoft Word 2000 inserts when you save Word "
678    "documents as \"Web pages\". Doesn't handle embedded images or VML. "
679    "You should consider using Word's \"Save As: Web Page, Filtered\". "
680   },
681   {TidyAccessibilityCheckLevel,
682    "This option specifies what level of accessibility checking, if any, "
683    "that Tidy should do. Level 0 is equivalent to Tidy Classic's "
684    "accessibility checking. "
685    "For more information on Tidy's accessibility checking, visit the "
686    "<a href=\"http://www.aprompt.ca/Tidy/accessibilitychecks.html\" "
687    ">Adaptive Technology Resource Centre at the University of Toronto</a>. "
688   },
689   {TidyShowErrors,
690    "This option specifies the number Tidy uses to determine if further errors "
691    "should be shown. If set to 0, then no errors are shown. "
692   },
693   {TidyShowInfo,
694    "This option specifies if Tidy should display info-level messages. "
695   },
696   {TidyShowWarnings,
697    "This option specifies if Tidy should suppress warnings. This can be "
698    "useful when a few errors are hidden in a flurry of warnings. "
699   },
700   {TidyBreakBeforeBR,
701    "This option specifies if Tidy should output a line break before each "
702    "&lt;BR&gt; element. "
703   },
704   {TidyIndentContent,
705    "This option specifies if Tidy should indent block-level tags. If set to "
706    "\"auto\", this option causes Tidy to decide whether or not to indent the "
707    "content of tags such as TITLE, H1-H6, LI, TD, TD, or P depending on "
708    "whether or not the content includes a block-level element. You are "
709    "advised to avoid setting indent to yes as this can expose layout bugs in "
710    "some browsers. "
711    ,TidyIndentContentLinks
712   },
713   {TidyIndentAttributes,
714    "This option specifies if Tidy should begin each attribute on a new line. "
715   },
716   {TidyIndentSpaces,
717    "This option specifies the number of spaces Tidy uses to indent content, "
718    "when indentation is enabled. "
719    ,TidyIndentSpacesLinks
720   },
721   {TidyLiteralAttribs,
722    "This option specifies how Tidy deals with whitespace characters within "
723    "attribute values. If the value is \"no\" (the default), Tidy \"munges\" "
724    "or \"normalizes\" attribute values by replacing any newline or tab "
725    "character with a single space character, and further by replacing "
726    "any sequences of multiple whitespace characters with a single space. "
727    "To force tidy to preserve the original, literal values of all attributes, "
728    "and ensure that whitespace characters within attribute values are passed "
729    "through unchanged, set this option to \"yes\". "
730   },
731   {TidyShowMarkup,
732    "This option specifies if Tidy should generate a pretty printed version "
733    "of the markup. Note that Tidy won't generate a pretty printed version if "
734    "it finds significant errors (see force-output). "
735   },
736 #if SUPPORT_ASIAN_ENCODINGS
737   {TidyPunctWrap,
738    "This option specifies if Tidy should line wrap after some Unicode or "
739    "Chinese punctuation characters. "
740   },
741 #endif
742   {TidyBurstSlides,
743    "Currently not used. Tidy Classic only. "
744   },
745   {TidyTabSize,
746    "This option specifies the number of columns that Tidy uses between "
747    "successive tab stops. It is used to map tabs to spaces when reading the "
748    "input. Tidy never outputs tabs. "
749   },
750   {TidyVertSpace,
751    "This option specifies if Tidy should add some empty lines for "
752    "readability. "
753   },
754   {TidyWrapLen,
755    "This option specifies the right margin Tidy uses for line wrapping. Tidy "
756    "tries to wrap lines so that they do not exceed this length. Set wrap to "
757    "zero if you want to disable line wrapping. "
758   },
759   {TidyWrapAsp,
760    "This option specifies if Tidy should line wrap text contained within ASP "
761    "pseudo elements, which look like: &lt;% ... %&gt;. "
762   },
763   {TidyWrapAttVals,
764    "This option specifies if Tidy should line-wrap attribute values, for "
765    "easier editing. Line wrapping means that if the value of an attribute "
766    "causes a line to exceed the width specified by the \"wrap\" option, "
767    "tidy will add one or more line breaks to the value, causing it to "
768    "wrapped into multiple lines. Note that this option can be set "
769    "independently of wrap-script-literals. Also note that by default, Tidy "
770    "\"munges\" or \"normalizes\" attribute values by replacing any newline "
771    "or tab character with a single space character, and further by replacing "
772    "any sequences of multiple whitespace characters with a single space. "
773    "To force Tidy to preserve the original, literal values of all attributes, "
774    "and ensure that whitespace characters within attribute values are passed "
775    "through unchanged, set the literal-attributes option to \"yes\". "
776    ,TidyWrapAttValsLinks
777   },
778   {TidyWrapJste,
779    "This option specifies if Tidy should line wrap text contained within "
780    "JSTE pseudo elements, which look like: &lt;# ... #&gt;. "
781   },
782   {TidyWrapPhp,
783    "This option specifies if Tidy should line wrap text contained within PHP "
784    "pseudo elements, which look like: &lt;?php ... ?&gt;. "
785   },
786   {TidyWrapScriptlets,
787    "This option specifies if Tidy should line wrap string literals that "
788    "appear in script attributes. Tidy wraps long script string literals by "
789    "inserting a backslash character before the line break. "
790    ,TidyWrapScriptletsLinks
791   },
792   {TidyWrapSection,
793    "This option specifies if Tidy should line wrap text contained within "
794    "&lt;![ ... ]&gt; section tags. "
795   },
796   {TidyAsciiChars,
797    "Can be used to modify behavior of -c (--clean yes) option.  If set "
798    "to \"yes\" when using -c, &amp;emdash;, &amp;rdquo;, and other named "
799    "character entities are downgraded to their closest ascii equivalents. "
800    ,TidyAsciiCharsLinks
801   },
802   {TidyCharEncoding,
803    "This option specifies the character encoding Tidy uses for both the input "
804    "and output. For ascii, Tidy will accept Latin-1 (ISO-8859-1) character "
805    "values, but will use entities for all characters whose value &gt; 127. "
806    "For raw, Tidy will output values above 127 without translating them into "
807    "entities. For latin1, characters above 255 will be written as entities. "
808    "For utf8, Tidy assumes that both input and output is encoded as UTF-8. "
809    "You can use iso2022 for files encoded using the ISO-2022 family of "
810    "encodings e.g. ISO-2022-JP. For mac and win1252, Tidy will accept vendor "
811    "specific character values, but will use entities for all characters whose "
812    "value &gt; 127. "
813    "For unsupported encodings, use an external utility to convert to and from "
814    "UTF-8. "
815    ,TidyCharEncodingLinks
816   },
817   {TidyInCharEncoding,
818    "This option specifies the character encoding Tidy uses for the input. See "
819    "char-encoding for more info. "
820    ,TidyInCharEncodingLinks
821   },
822 #if SUPPORT_ASIAN_ENCODINGS
823   {TidyLanguage,
824    "Currently not used, but this option specifies the language Tidy uses "
825    "(for instance \"en\"). "
826   },
827 #endif
828 #if SUPPORT_UTF16_ENCODINGS
829   {TidyOutputBOM,
830    "This option specifies if Tidy should write a Unicode Byte Order Mark "
831    "character (BOM; also known as Zero Width No-Break Space; has value of "
832    "U+FEFF) to the beginning of the output; only for UTF-8 and UTF-16 output "
833    "encodings. If set to \"auto\", this option causes Tidy to write a BOM to "
834    "the output only if a BOM was present at the beginning of the input. A BOM "
835    "is always written for XML/XHTML output using UTF-16 output encodings. "
836   },
837 #endif
838   {TidyOutCharEncoding,
839    "This option specifies the character encoding Tidy uses for the output. "
840    "See char-encoding for more info. May only be different from "
841    "input-encoding for Latin encodings (ascii, latin0, latin1, mac, win1252, "
842    "ibm858). "
843    ,TidyOutCharEncodingLinks
844   },
845   {TidyNewline,
846    "The default is appropriate to the current platform: CRLF on PC-DOS, "
847    "MS-Windows and OS/2, CR on Classic Mac OS, and LF everywhere else "
848    "(Unix and Linux). "
849   },
850   {TidyErrFile,
851    "This option specifies the error file Tidy uses for errors and warnings. "
852    "Normally errors and warnings are output to \"stderr\". "
853    ,TidyErrFileLinks
854   },
855   {TidyFixBackslash,
856    "This option specifies if Tidy should replace backslash characters "
857    "\"<code>\\</code>\" in URLs by forward slashes \"<code>/</code>\". "
858   },
859   {TidyForceOutput,
860    "This option specifies if Tidy should produce output even if errors are "
861    "encountered. Use this option with care - if Tidy reports an error, this "
862    "means Tidy was not able to, or is not sure how to, fix the error, so the "
863    "resulting output may not reflect your intention. "
864   },
865   {TidyEmacs,
866    "This option specifies if Tidy should change the format for reporting "
867    "errors and warnings to a format that is more easily parsed by GNU Emacs. "
868   },
869   {TidyEmacsFile,
870    "Used internally. "
871   },
872   {TidyKeepFileTimes,
873    "This option specifies if Tidy should keep the original modification time "
874    "of files that Tidy modifies in place. The default is no. Setting the "
875    "option to yes allows you to tidy files without causing these files to be "
876    "uploaded to a web server when using a tool such as SiteCopy. Note this "
877    "feature is not supported on some platforms. "
878   },
879   {TidyOutFile,
880    "This option specifies the output file Tidy uses for markup. Normally "
881    "markup is written to \"stdout\". "
882    ,TidyOutFileLinks
883   },
884   {TidyQuiet,
885    "This option specifies if Tidy should output the summary of the numbers "
886    "of errors and warnings, or the welcome or informational messages. "
887   },
888   {TidySlideStyle,
889    "Currently not used.  Tidy Classic only. "
890   },
891   {TidyMark,
892    "This option specifies if Tidy should add a meta element to the document "
893    "head to indicate that the document has been tidied. Tidy won't add a meta "
894    "element if one is already present. "
895   },
896   {TidyWriteBack,
897    "This option specifies if Tidy should write back the tidied markup to the "
898    "same file it read from. You are advised to keep copies of important files "
899    "before tidying them, as on rare occasions the result may not be what you "
900    "expect. "
901   },
902   {TidyDecorateInferredUL,
903    "This option specifies if Tidy should decorate inferred UL elements with "
904    "some CSS markup to avoid indentation to the right. "
905   },
906   {TidyPreserveEntities,
907    "This option specifies if Tidy should preserve the well-formed entities "
908    "as found in the input. "
909   },
910   {TidyAnchorAsName,
911    "This option controls the deletion or addition of the name attribute "
912    "in elements where it can serve as anchor. "
913    "If set to \"yes\", a name attribute, if not already existing, "
914    "is added along an existing id attribute if the DTD allows it. "
915    "If set to \"no\", any existing name attribute is removed "
916    "if an id attribute exists or has been added. "
917   },
918   {N_TIDY_OPTIONS,
919    NULL
920   }
921 };
922
923 const TidyOptionDoc* TY_(OptGetDocDesc)( TidyOptionId optId )
924 {
925     uint i = 0;
926
927     while( option_docs[i].opt != N_TIDY_OPTIONS )
928     {
929         if ( option_docs[i].opt == optId )
930             return &option_docs[i];
931         ++i;
932     }
933     return NULL;
934 }
935
936
937 static char* LevelPrefix( TidyReportLevel level, char* buf, size_t count )
938 {
939   *buf = 0;
940   switch ( level )
941   {
942   case TidyInfo:
943     TY_(tmbstrncpy)( buf, "Info: ", count );
944     break;
945   case TidyWarning:
946     TY_(tmbstrncpy)( buf, "Warning: ", count );
947     break;
948   case TidyConfig:
949     TY_(tmbstrncpy)( buf, "Config: ", count );
950     break;
951   case TidyAccess:
952     TY_(tmbstrncpy)( buf, "Access: ", count );
953     break;
954   case TidyError:
955     TY_(tmbstrncpy)( buf, "Error: ", count );
956     break;
957   case TidyBadDocument:
958     TY_(tmbstrncpy)( buf, "Document: ", count );
959     break;
960   case TidyFatal:
961     TY_(tmbstrncpy)( buf, "panic: ", count );
962     break;
963   }
964   return buf + TY_(tmbstrlen)( buf );
965 }
966
967 /* Updates document message counts and
968 ** compares counts to options to see if message
969 ** display should go forward.
970 */
971 static Bool UpdateCount( TidyDocImpl* doc, TidyReportLevel level )
972 {
973   /* keep quiet after <ShowErrors> errors */
974   Bool go = ( doc->errors < cfg(doc, TidyShowErrors) );
975
976   switch ( level )
977   {
978   case TidyInfo:
979     doc->infoMessages++;
980     break;
981   case TidyWarning:
982     doc->warnings++;
983     go = go && cfgBool( doc, TidyShowWarnings );
984     break;
985   case TidyConfig:
986     doc->optionErrors++;
987     break;
988   case TidyAccess:
989     doc->accessErrors++;
990     break;
991   case TidyError:
992     doc->errors++;
993     break;
994   case TidyBadDocument:
995     doc->docErrors++;
996     break;
997   case TidyFatal:
998     /* Ack! */;
999     break;
1000   }
1001
1002   return go;
1003 }
1004
1005 static char* ReportPosition(TidyDocImpl* doc, int line, int col, char* buf, size_t count)
1006 {
1007     *buf = 0;
1008
1009     /* Change formatting to be parsable by GNU Emacs */
1010     if ( cfgBool(doc, TidyEmacs) && cfgStr(doc, TidyEmacsFile) )
1011         TY_(tmbsnprintf)(buf, count, "%s:%d:%d: ", 
1012                          cfgStr(doc, TidyEmacsFile), line, col);
1013     else /* traditional format */
1014         TY_(tmbsnprintf)(buf, count, "line %d column %d - ", line, col);
1015     return buf + TY_(tmbstrlen)( buf );
1016 }
1017
1018 /* General message writing routine.
1019 ** Each message is a single warning, error, etc.
1020 ** 
1021 ** This routine will keep track of counts and,
1022 ** if the caller has set a filter, it will be 
1023 ** called.  The new preferred way of handling
1024 ** Tidy diagnostics output is either a) define
1025 ** a new output sink or b) install a message
1026 ** filter routine.
1027 */
1028
1029 static void messagePos( TidyDocImpl* doc, TidyReportLevel level,
1030                         int line, int col, ctmbstr msg, va_list args )
1031 #ifdef __GNUC__
1032 __attribute__((format(printf, 5, 0)))
1033 #endif
1034 ;
1035 static void messagePos( TidyDocImpl* doc, TidyReportLevel level,
1036                         int line, int col, ctmbstr msg, va_list args )
1037 {
1038     enum { sizeMessageBuf=2048 };
1039     char *messageBuf = TidyDocAlloc(doc,sizeMessageBuf);
1040     Bool go = UpdateCount( doc, level );
1041
1042     if ( go )
1043     {
1044         va_list args_copy;
1045         va_copy(args_copy, args);
1046         TY_(tmbvsnprintf)(messageBuf, sizeMessageBuf, msg, args);
1047         if ( doc->mssgFilt )
1048         {
1049             TidyDoc tdoc = tidyImplToDoc( doc );
1050             go = doc->mssgFilt( tdoc, level, line, col, messageBuf );
1051         }
1052         if ( doc->mssgFilt2 )
1053         {
1054             TidyDoc tdoc = tidyImplToDoc( doc );
1055             go = go | doc->mssgFilt2( tdoc, level, line, col, msg, args_copy );
1056         }
1057     }
1058
1059     if ( go )
1060     {
1061         enum { sizeBuf=1024 };
1062         char *buf = TidyDocAlloc(doc,sizeBuf);
1063         const char *cp;
1064         if ( line > 0 && col > 0 )
1065         {
1066             ReportPosition(doc, line, col, buf, sizeBuf);
1067 #if !defined(NDEBUG) && defined(_MSC_VER)
1068             SPRTF("%s",buf);
1069 #endif
1070             for ( cp = buf; *cp; ++cp )
1071                 TY_(WriteChar)( *cp, doc->errout );
1072         }
1073
1074         LevelPrefix( level, buf, sizeBuf );
1075 #if !defined(NDEBUG) && defined(_MSC_VER)
1076             SPRTF("%s",buf);
1077             SPRTF("%s\n",messageBuf);
1078 #else
1079         for ( cp = buf; *cp; ++cp )
1080             TY_(WriteChar)( *cp, doc->errout );
1081
1082         for ( cp = messageBuf; *cp; ++cp )
1083             TY_(WriteChar)( *cp, doc->errout );
1084         TY_(WriteChar)( '\n', doc->errout );
1085 #endif
1086         TidyDocFree(doc, buf);
1087     }
1088     TidyDocFree(doc, messageBuf);
1089 }
1090
1091 /* Reports error at current Lexer line/column. */ 
1092 static
1093 void message( TidyDocImpl* doc, TidyReportLevel level, ctmbstr msg, ... )
1094 #ifdef __GNUC__
1095 __attribute__((format(printf, 3, 4)))
1096 #endif
1097 ;
1098
1099 /* Reports error at node line/column. */ 
1100 static
1101 void messageNode( TidyDocImpl* doc, TidyReportLevel level,
1102                   Node* node, ctmbstr msg, ... )
1103 #ifdef __GNUC__
1104 __attribute__((format(printf, 4, 5)))
1105 #endif
1106 ;
1107
1108 /* Reports error at given line/column. */ 
1109 static
1110 void messageLexer( TidyDocImpl* doc, TidyReportLevel level, 
1111                    ctmbstr msg, ... )
1112 #ifdef __GNUC__
1113 __attribute__((format(printf, 3, 4)))
1114 #endif
1115 ;
1116
1117 /* For general reporting.  Emits nothing if --quiet yes */
1118 static
1119 void tidy_out( TidyDocImpl* doc, ctmbstr msg, ... )
1120 #ifdef __GNUC__
1121 __attribute__((format(printf, 2, 3)))
1122 #endif
1123 ;
1124
1125
1126 void message( TidyDocImpl* doc, TidyReportLevel level, ctmbstr msg, ... )
1127 {
1128     va_list args;
1129     if (level == TidyInfo && !cfgBool(doc, TidyShowInfo)) return;
1130     va_start( args, msg );
1131     messagePos( doc, level, 0, 0, msg, args );
1132     va_end( args );
1133 }
1134
1135
1136 void messageLexer( TidyDocImpl* doc, TidyReportLevel level, ctmbstr msg, ... )
1137 {
1138     int line = ( doc->lexer ? doc->lexer->lines : 0 );
1139     int col  = ( doc->lexer ? doc->lexer->columns : 0 );
1140
1141     va_list args;
1142     va_start( args, msg );
1143     messagePos( doc, level, line, col, msg, args );
1144     va_end( args );
1145 }
1146
1147 void messageNode( TidyDocImpl* doc, TidyReportLevel level, Node* node,
1148                   ctmbstr msg, ... )
1149 {
1150     int line = ( node ? node->line :
1151                  ( doc->lexer ? doc->lexer->lines : 0 ) );
1152     int col  = ( node ? node->column :
1153                  ( doc->lexer ? doc->lexer->columns : 0 ) );
1154
1155     va_list args;
1156     va_start( args, msg );
1157     messagePos( doc, level, line, col, msg, args );
1158     va_end( args );
1159 }
1160
1161 void tidy_out( TidyDocImpl* doc, ctmbstr msg, ... )
1162 {
1163     if ( !cfgBool(doc, TidyQuiet) )
1164     {
1165         ctmbstr cp;
1166         enum { sizeBuf=2048 };
1167         char *buf = (char *)TidyDocAlloc(doc,sizeBuf);
1168
1169         va_list args;
1170         va_start( args, msg );
1171         TY_(tmbvsnprintf)(buf, sizeBuf, msg, args);
1172         va_end( args );
1173
1174 #if !defined(NDEBUG) && defined(_MSC_VER)
1175         add_std_out(0);
1176 #endif
1177         for ( cp=buf; *cp; ++cp )
1178           TY_(WriteChar)( *cp, doc->errout );
1179 #if !defined(NDEBUG) && defined(_MSC_VER)
1180         add_std_out(1);
1181 #endif
1182         TidyDocFree(doc, buf);
1183     }
1184 }
1185
1186 #if 0
1187 void ShowVersion( TidyDocImpl* doc )
1188 {
1189     ctmbstr platform = "", helper = "";
1190
1191 #ifdef PLATFORM_NAME
1192     platform = PLATFORM_NAME;
1193     helper = " for ";
1194 #endif
1195
1196     tidy_out( doc, "\nHTML Tidy%s%s (release date: %s; built on %s, at %s)\n"
1197                    "See http://www.html-tidy.org/ for details.\n",
1198               helper, platform, TY_(release_date), __DATE__, __TIME__ );
1199 }
1200 #endif
1201
1202 void TY_(FileError)( TidyDocImpl* doc, ctmbstr file, TidyReportLevel level )
1203 {
1204     message( doc, level, "Can't open \"%s\"\n", file );
1205 }
1206
1207 static char* TagToString(Node* tag, char* buf, size_t count)
1208 {
1209     *buf = 0;
1210     if (tag)
1211     {
1212         if (TY_(nodeIsElement)(tag))
1213             TY_(tmbsnprintf)(buf, count, "<%s>", tag->element);
1214         else if (tag->type == EndTag)
1215             TY_(tmbsnprintf)(buf, count, "</%s>", tag->element);
1216         else if (tag->type == DocTypeTag)
1217             TY_(tmbsnprintf)(buf, count, "<!DOCTYPE>");
1218         else if (tag->type == TextNode)
1219             TY_(tmbsnprintf)(buf, count, "plain text");
1220         else if (tag->type == XmlDecl)
1221             TY_(tmbsnprintf)(buf, count, "XML declaration");
1222         else if (tag->element)
1223             TY_(tmbsnprintf)(buf, count, "%s", tag->element);
1224     }
1225     return buf + TY_(tmbstrlen)(buf);
1226 }
1227
1228 /* lexer is not defined when this is called */
1229 void TY_(ReportUnknownOption)( TidyDocImpl* doc, ctmbstr option )
1230 {
1231     assert( option != NULL );
1232     message( doc, TidyConfig, "unknown option: %s", option );
1233 }
1234
1235 /* lexer is not defined when this is called */
1236 void TY_(ReportBadArgument)( TidyDocImpl* doc, ctmbstr option )
1237 {
1238     assert( option != NULL );
1239     message( doc, TidyConfig,
1240              "missing or malformed argument for option: %s", option );
1241 }
1242
1243 static void NtoS(int n, tmbstr str)
1244 {
1245     tmbchar buf[40];
1246     int i;
1247
1248     for (i = 0;; ++i)
1249     {
1250         buf[i] = (tmbchar)( (n % 10) + '0' );
1251
1252         n = n / 10;
1253
1254         if (n == 0)
1255             break;
1256     }
1257
1258     n = i;
1259
1260     while (i >= 0)
1261     {
1262         str[n-i] = buf[i];
1263         --i;
1264     }
1265
1266     str[n+1] = '\0';
1267 }
1268
1269 void TY_(ReportEncodingWarning)(TidyDocImpl* doc, uint code, uint encoding)
1270 {
1271     switch(code)
1272     {
1273     case ENCODING_MISMATCH:
1274         messageLexer(doc, TidyWarning, GetFormatFromCode(code), 
1275                      TY_(CharEncodingName)(doc->docIn->encoding),
1276                      TY_(CharEncodingName)(encoding));
1277         doc->badChars |= BC_ENCODING_MISMATCH;
1278         break;
1279     }
1280 }
1281
1282 void TY_(ReportEncodingError)(TidyDocImpl* doc, uint code, uint c, Bool discarded)
1283 {
1284     char buf[ 32 ] = {'\0'};
1285
1286     ctmbstr action = discarded ? "discarding" : "replacing";
1287     ctmbstr fmt = GetFormatFromCode(code);
1288
1289     /* An encoding mismatch is currently treated as a non-fatal error */
1290     switch (code)
1291     {
1292     case VENDOR_SPECIFIC_CHARS:
1293         NtoS(c, buf);
1294         doc->badChars |= BC_VENDOR_SPECIFIC_CHARS;
1295         break;
1296
1297     case INVALID_SGML_CHARS:
1298         NtoS(c, buf);
1299         doc->badChars |= BC_INVALID_SGML_CHARS;
1300         break;
1301
1302     case INVALID_UTF8:
1303         TY_(tmbsnprintf)(buf, sizeof(buf), "U+%04X", c);
1304         doc->badChars |= BC_INVALID_UTF8;
1305         break;
1306
1307 #if SUPPORT_UTF16_ENCODINGS
1308     case INVALID_UTF16:
1309         TY_(tmbsnprintf)(buf, sizeof(buf), "U+%04X", c);
1310         doc->badChars |= BC_INVALID_UTF16;
1311         break;
1312 #endif
1313
1314     case INVALID_NCR:
1315         NtoS(c, buf);
1316         doc->badChars |= BC_INVALID_NCR;
1317         break;
1318     }
1319
1320     if (fmt)
1321         messageLexer( doc, TidyWarning, fmt, action, buf );
1322 }
1323
1324 void TY_(ReportEntityError)( TidyDocImpl* doc, uint code, ctmbstr entity,
1325                              int ARG_UNUSED(c) )
1326 {
1327     ctmbstr entityname = ( entity ? entity : "NULL" );
1328     ctmbstr fmt = GetFormatFromCode(code);
1329
1330     if (fmt)
1331         messageLexer( doc, TidyWarning, fmt, entityname );
1332 }
1333
1334 void TY_(ReportAttrError)(TidyDocImpl* doc, Node *node, AttVal *av, uint code)
1335 {
1336     char const *name = "NULL", *value = "NULL";
1337     char tagdesc[64];
1338     ctmbstr fmt = GetFormatFromCode(code);
1339
1340     assert( fmt != NULL );
1341
1342     TagToString(node, tagdesc, sizeof(tagdesc));
1343
1344     if (av)
1345     {
1346         if (av->attribute)
1347             name = av->attribute;
1348         if (av->value)
1349             value = av->value;
1350     }
1351
1352     switch (code)
1353     {
1354     case UNKNOWN_ATTRIBUTE:
1355     case INSERTING_ATTRIBUTE:
1356     case MISSING_ATTR_VALUE:
1357     case XML_ATTRIBUTE_VALUE:
1358     case PROPRIETARY_ATTRIBUTE:
1359     case JOINING_ATTRIBUTE:
1360         messageNode(doc, TidyWarning, node, fmt, tagdesc, name);
1361         break;
1362
1363     case BAD_ATTRIBUTE_VALUE:
1364     case BAD_ATTRIBUTE_VALUE_REPLACED:
1365     case INVALID_ATTRIBUTE:
1366         messageNode(doc, TidyWarning, node, fmt, tagdesc, name, value);
1367         break;
1368
1369     case UNEXPECTED_QUOTEMARK:
1370     case MISSING_QUOTEMARK:
1371     case ID_NAME_MISMATCH:
1372     case BACKSLASH_IN_URI:
1373     case FIXED_BACKSLASH:
1374     case ILLEGAL_URI_REFERENCE:
1375     case ESCAPED_ILLEGAL_URI:
1376     case NEWLINE_IN_URI:
1377     case WHITE_IN_URI:
1378     case UNEXPECTED_GT:
1379     case INVALID_XML_ID:
1380     case UNEXPECTED_EQUALSIGN:
1381         messageNode(doc, TidyWarning, node, fmt, tagdesc);
1382         break;
1383
1384     case XML_ID_SYNTAX:
1385     case PROPRIETARY_ATTR_VALUE:
1386     case ANCHOR_NOT_UNIQUE:
1387     case ATTR_VALUE_NOT_LCASE:
1388         messageNode(doc, TidyWarning, node, fmt, tagdesc, value);
1389         break;
1390
1391
1392     case MISSING_IMAGEMAP:
1393         messageNode(doc, TidyWarning, node, fmt, tagdesc);
1394         doc->badAccess |= BA_MISSING_IMAGE_MAP;
1395         break;
1396
1397     case REPEATED_ATTRIBUTE:
1398         messageNode(doc, TidyWarning, node, fmt, tagdesc, value, name);
1399         break;
1400
1401     case UNEXPECTED_END_OF_FILE_ATTR:
1402         /* on end of file adjust reported position to end of input */
1403         doc->lexer->lines   = doc->docIn->curline;
1404         doc->lexer->columns = doc->docIn->curcol;
1405         messageLexer(doc, TidyWarning, fmt, tagdesc);
1406         break;
1407     }
1408 }
1409
1410 void TY_(ReportMissingAttr)( TidyDocImpl* doc, Node* node, ctmbstr name )
1411 {
1412     char tagdesc[ 64 ];
1413     ctmbstr fmt = GetFormatFromCode(MISSING_ATTRIBUTE);
1414
1415     assert( fmt != NULL );
1416     TagToString(node, tagdesc, sizeof(tagdesc));
1417     messageNode( doc, TidyWarning, node, fmt, tagdesc, name );
1418 }
1419
1420 #if SUPPORT_ACCESSIBILITY_CHECKS
1421
1422 /*********************************************************
1423 * Accessibility
1424 *
1425 * DisplayHTMLTableAlgorithm()
1426 *
1427 * If the table does contain 2 or more logical levels of 
1428 * row or column headers, the HTML 4 table algorithm 
1429 * to show the author how the headers are currently associated 
1430 * with the cells.
1431 *********************************************************/
1432  
1433 void TY_(DisplayHTMLTableAlgorithm)( TidyDocImpl* doc )
1434 {
1435     tidy_out(doc, " \n");
1436     tidy_out(doc, "      - First, search left from the cell's position to find row header cells.\n");
1437     tidy_out(doc, "      - Then search upwards to find column header cells.\n");
1438     tidy_out(doc, "      - The search in a given direction stops when the edge of the table is\n");
1439     tidy_out(doc, "        reached or when a data cell is found after a header cell.\n"); 
1440     tidy_out(doc, "      - Row headers are inserted into the list in the order they appear in\n");
1441     tidy_out(doc, "        the table. \n");
1442     tidy_out(doc, "      - For left-to-right tables, headers are inserted from left to right.\n");
1443     tidy_out(doc, "      - Column headers are inserted after row headers, in \n");
1444     tidy_out(doc, "        the order they appear in the table, from top to bottom. \n");
1445     tidy_out(doc, "      - If a header cell has the headers attribute set, then the headers \n");
1446     tidy_out(doc, "        referenced by this attribute are inserted into the list and the \n");
1447     tidy_out(doc, "        search stops for the current direction.\n");
1448     tidy_out(doc, "        TD cells that set the axis attribute are also treated as header cells.\n");
1449     tidy_out(doc, " \n");
1450 }
1451
1452 void TY_(ReportAccessWarning)( TidyDocImpl* doc, Node* node, uint code )
1453 {
1454     ctmbstr fmt = GetFormatFromCode(code);
1455     doc->badAccess |= BA_WAI;
1456     messageNode( doc, TidyAccess, node, "%s", fmt );
1457 }
1458
1459 void TY_(ReportAccessError)( TidyDocImpl* doc, Node* node, uint code )
1460 {
1461     ctmbstr fmt = GetFormatFromCode(code);
1462     doc->badAccess |= BA_WAI;
1463     messageNode( doc, TidyAccess, node, "%s", fmt );
1464 }
1465
1466 #endif /* SUPPORT_ACCESSIBILITY_CHECKS */
1467
1468 void TY_(ReportWarning)(TidyDocImpl* doc, Node *element, Node *node, uint code)
1469 {
1470     Node* rpt = (element ? element : node);
1471     ctmbstr fmt = GetFormatFromCode(code);
1472     char nodedesc[256] = { 0 };
1473     char elemdesc[256] = { 0 };
1474
1475     assert( fmt != NULL );
1476
1477     TagToString(node, nodedesc, sizeof(nodedesc));
1478
1479     switch (code)
1480     {
1481     case NESTED_QUOTATION:
1482         messageNode(doc, TidyWarning, rpt, "%s", fmt);
1483         break;
1484
1485     case OBSOLETE_ELEMENT:
1486         TagToString(element, elemdesc, sizeof(elemdesc));
1487         messageNode(doc, TidyWarning, rpt, fmt, elemdesc, nodedesc);
1488         break;
1489
1490     case NESTED_EMPHASIS:
1491     case REMOVED_HTML5:
1492     case BAD_BODY_HTML5:
1493     case BAD_ALIGN_HTML5:
1494         messageNode(doc, TidyWarning, rpt, fmt, nodedesc);
1495         break;
1496     case COERCE_TO_ENDTAG_WARN:
1497         messageNode(doc, TidyWarning, rpt, fmt, node->element, node->element);
1498         break;
1499     }
1500 }
1501
1502 void TY_(ReportNotice)(TidyDocImpl* doc, Node *element, Node *node, uint code)
1503 {
1504     Node* rpt = ( element ? element : node );
1505     ctmbstr fmt = GetFormatFromCode(code);
1506     char nodedesc[256] = { 0 };
1507     char elemdesc[256] = { 0 };
1508
1509     assert( fmt != NULL );
1510
1511     TagToString(node, nodedesc, sizeof(nodedesc));
1512
1513     switch (code)
1514     {
1515     case TRIM_EMPTY_ELEMENT:
1516         TagToString(element, elemdesc, sizeof(nodedesc));
1517         messageNode(doc, TidyWarning, element, fmt, elemdesc);
1518         break;
1519
1520     case REPLACING_ELEMENT:
1521         TagToString(element, elemdesc, sizeof(elemdesc));
1522         messageNode(doc, TidyWarning, rpt, fmt, elemdesc, nodedesc);
1523         break;
1524     }
1525 }
1526
1527 void TY_(ReportError)(TidyDocImpl* doc, Node *element, Node *node, uint code)
1528 {
1529     char nodedesc[ 256 ] = {0};
1530     char elemdesc[ 256 ] = {0};
1531     Node* rpt = ( element ? element : node );
1532     ctmbstr fmt = GetFormatFromCode(code);
1533
1534     assert( fmt != NULL );
1535
1536     TagToString(node, nodedesc, sizeof(nodedesc));
1537
1538     switch ( code )
1539     {
1540     case MISSING_STARTTAG:
1541     case UNEXPECTED_ENDTAG:
1542     case TOO_MANY_ELEMENTS:
1543     case INSERTING_TAG:
1544         messageNode(doc, TidyWarning, node, fmt, node->element);
1545         break;
1546
1547     case USING_BR_INPLACE_OF:
1548     case CANT_BE_NESTED:
1549     case PROPRIETARY_ELEMENT:
1550     case UNESCAPED_ELEMENT:
1551     case NOFRAMES_CONTENT:
1552         messageNode(doc, TidyWarning, node, fmt, nodedesc);
1553         break;
1554
1555     case MISSING_TITLE_ELEMENT:
1556     case INCONSISTENT_VERSION:
1557     case MALFORMED_DOCTYPE:
1558     case CONTENT_AFTER_BODY:
1559     case MALFORMED_COMMENT:
1560     case BAD_COMMENT_CHARS:
1561     case BAD_XML_COMMENT:
1562     case BAD_CDATA_CONTENT:
1563     case INCONSISTENT_NAMESPACE:
1564     case DOCTYPE_AFTER_TAGS:
1565     case DTYPE_NOT_UPPER_CASE:
1566         messageNode(doc, TidyWarning, rpt, "%s", fmt);
1567         break;
1568
1569     case COERCE_TO_ENDTAG:
1570     case NON_MATCHING_ENDTAG:
1571         messageNode(doc, TidyWarning, rpt, fmt, node->element, node->element);
1572         break;
1573
1574     case UNEXPECTED_ENDTAG_IN:
1575     case TOO_MANY_ELEMENTS_IN:
1576         messageNode(doc, TidyWarning, node, fmt, node->element, element->element);
1577         if (cfgBool( doc, TidyShowWarnings ))
1578             messageNode(doc, TidyInfo, node, GetFormatFromCode(PREVIOUS_LOCATION),
1579                         element->element);
1580         break;
1581
1582     case ENCODING_IO_CONFLICT:
1583     case MISSING_DOCTYPE:
1584     case SPACE_PRECEDING_XMLDECL:
1585         messageNode(doc, TidyWarning, node, "%s", fmt);
1586         break;
1587
1588     case TRIM_EMPTY_ELEMENT:
1589     case ILLEGAL_NESTING:
1590     case UNEXPECTED_END_OF_FILE:
1591     case ELEMENT_NOT_EMPTY:
1592         TagToString(element, elemdesc, sizeof(elemdesc));
1593         messageNode(doc, TidyWarning, element, fmt, elemdesc);
1594         break;
1595
1596
1597     case MISSING_ENDTAG_FOR:
1598         messageNode(doc, TidyWarning, rpt, fmt, element->element);
1599         break;
1600
1601     case MISSING_ENDTAG_BEFORE:
1602         messageNode(doc, TidyWarning, rpt, fmt, element->element, nodedesc);
1603         break;
1604
1605     case DISCARDING_UNEXPECTED:
1606         /* Force error if in a bad form, or 
1607            Issue #166 - repeated <main> element
1608         */
1609         messageNode(doc, doc->badForm ? TidyError : TidyWarning, node, fmt, nodedesc);
1610         break;
1611
1612     case TAG_NOT_ALLOWED_IN:
1613         messageNode(doc, TidyWarning, node, fmt, nodedesc, element->element);
1614         if (cfgBool( doc, TidyShowWarnings ))
1615             messageNode(doc, TidyInfo, element,
1616                         GetFormatFromCode(PREVIOUS_LOCATION), element->element);
1617         break;
1618
1619     case REPLACING_UNEX_ELEMENT:
1620         TagToString(element, elemdesc, sizeof(elemdesc));
1621         messageNode(doc, TidyWarning, rpt, fmt, elemdesc, nodedesc);
1622         break;
1623     case REMOVED_HTML5:
1624         messageNode(doc, TidyError, rpt, fmt, nodedesc);
1625         break;
1626     }
1627 }
1628
1629 void TY_(ReportFatal)( TidyDocImpl* doc, Node *element, Node *node, uint code)
1630 {
1631     char nodedesc[ 256 ] = {0};
1632     Node* rpt = ( element ? element : node );
1633     ctmbstr fmt = GetFormatFromCode(code);
1634
1635     switch ( code )
1636     {
1637     case SUSPECTED_MISSING_QUOTE:
1638     case DUPLICATE_FRAMESET:
1639         messageNode(doc, TidyError, rpt, "%s", fmt);
1640         break;
1641
1642     case UNKNOWN_ELEMENT:
1643         TagToString(node, nodedesc, sizeof(nodedesc));
1644         messageNode( doc, TidyError, node, fmt, nodedesc );
1645         break;
1646
1647     case UNEXPECTED_ENDTAG_IN:
1648         messageNode(doc, TidyError, node, fmt, node->element, element->element);
1649         break;
1650
1651     case UNEXPECTED_ENDTAG:  /* generated by XML docs */
1652         messageNode(doc, TidyError, node, fmt, node->element);
1653         break;
1654     }
1655 }
1656
1657 void TY_(ErrorSummary)( TidyDocImpl* doc )
1658 {
1659     ctmbstr encnam = "specified";
1660     int charenc = cfg( doc, TidyCharEncoding ); 
1661     if ( charenc == WIN1252 ) 
1662         encnam = "Windows-1252";
1663     else if ( charenc == MACROMAN )
1664         encnam = "MacRoman";
1665     else if ( charenc == IBM858 )
1666         encnam = "ibm858";
1667     else if ( charenc == LATIN0 )
1668         encnam = "latin0";
1669
1670     /* adjust badAccess to that it is 0 if frames are ok */
1671     if ( doc->badAccess & (BA_USING_FRAMES | BA_USING_NOFRAMES) )
1672     {
1673         if (!((doc->badAccess & BA_USING_FRAMES) && !(doc->badAccess & BA_USING_NOFRAMES)))
1674             doc->badAccess &= ~(BA_USING_FRAMES | BA_USING_NOFRAMES);
1675     }
1676
1677     if (doc->badChars)
1678     {
1679 #if 0
1680         if ( doc->badChars & WINDOWS_CHARS )
1681         {
1682             tidy_out(doc, "Characters codes for the Microsoft Windows fonts in the range\n");
1683             tidy_out(doc, "128 - 159 may not be recognized on other platforms. You are\n");
1684             tidy_out(doc, "instead recommended to use named entities, e.g. &trade; rather\n");
1685             tidy_out(doc, "than Windows character code 153 (0x2122 in Unicode). Note that\n");
1686             tidy_out(doc, "as of February 1998 few browsers support the new entities.\n\n");
1687         }
1688 #endif
1689         if (doc->badChars & BC_VENDOR_SPECIFIC_CHARS)
1690         {
1691
1692             tidy_out(doc, "It is unlikely that vendor-specific, system-dependent encodings\n");
1693             tidy_out(doc, "work widely enough on the World Wide Web; you should avoid using the \n");
1694             tidy_out(doc, "%s", encnam );
1695             tidy_out(doc, " character encoding, instead you are recommended to\n" );
1696             tidy_out(doc, "use named entities, e.g. &trade;.\n\n");
1697         }
1698         if ((doc->badChars & BC_INVALID_SGML_CHARS) || (doc->badChars & BC_INVALID_NCR))
1699         {
1700             tidy_out(doc, "Character codes 128 to 159 (U+0080 to U+009F) are not allowed in HTML;\n");
1701             tidy_out(doc, "even if they were, they would likely be unprintable control characters.\n");
1702             tidy_out(doc, "Tidy assumed you wanted to refer to a character with the same byte value in the \n");
1703             tidy_out(doc, "%s", encnam );
1704             tidy_out(doc, " encoding and replaced that reference with the Unicode equivalent.\n\n" );
1705         }
1706         if (doc->badChars & BC_INVALID_UTF8)
1707         {
1708             tidy_out(doc, "Character codes for UTF-8 must be in the range: U+0000 to U+10FFFF.\n");
1709             tidy_out(doc, "The definition of UTF-8 in Annex D of ISO/IEC 10646-1:2000 also\n");
1710             tidy_out(doc, "allows for the use of five- and six-byte sequences to encode\n");
1711             tidy_out(doc, "characters that are outside the range of the Unicode character set;\n");
1712             tidy_out(doc, "those five- and six-byte sequences are illegal for the use of\n");
1713             tidy_out(doc, "UTF-8 as a transformation of Unicode characters. ISO/IEC 10646\n");
1714             tidy_out(doc, "does not allow mapping of unpaired surrogates, nor U+FFFE and U+FFFF\n");
1715             tidy_out(doc, "(but it does allow other noncharacters). For more information please refer to\n");
1716             tidy_out(doc, "http://www.unicode.org/unicode and http://www.cl.cam.ac.uk/~mgk25/unicode.html\n\n");
1717         }
1718
1719 #if SUPPORT_UTF16_ENCODINGS
1720
1721       if (doc->badChars & BC_INVALID_UTF16)
1722       {
1723         tidy_out(doc, "Character codes for UTF-16 must be in the range: U+0000 to U+10FFFF.\n");
1724         tidy_out(doc, "The definition of UTF-16 in Annex C of ISO/IEC 10646-1:2000 does not allow the\n");
1725         tidy_out(doc, "mapping of unpaired surrogates. For more information please refer to\n");
1726         tidy_out(doc, "http://www.unicode.org/unicode and http://www.cl.cam.ac.uk/~mgk25/unicode.html\n\n");
1727       }
1728
1729 #endif
1730
1731       if (doc->badChars & BC_INVALID_URI)
1732       {
1733         tidy_out(doc, "URIs must be properly escaped, they must not contain unescaped\n");
1734         tidy_out(doc, "characters below U+0021 including the space character and not\n");
1735         tidy_out(doc, "above U+007E. Tidy escapes the URI for you as recommended by\n");
1736         tidy_out(doc, "HTML 4.01 section B.2.1 and XML 1.0 section 4.2.2. Some user agents\n");
1737         tidy_out(doc, "use another algorithm to escape such URIs and some server-sided\n");
1738         tidy_out(doc, "scripts depend on that. If you want to depend on that, you must\n");
1739         tidy_out(doc, "escape the URI by your own. For more information please refer to\n");
1740         tidy_out(doc, "http://www.w3.org/International/O-URL-and-ident.html\n\n");
1741       }
1742     }
1743
1744     if (doc->badForm & flg_BadForm) /* Issue #166 - changed to BIT flag to support other errors */
1745     {
1746         tidy_out(doc, "You may need to move one or both of the <form> and </form>\n");
1747         tidy_out(doc, "tags. HTML elements should be properly nested and form elements\n");
1748         tidy_out(doc, "are no exception. For instance you should not place the <form>\n");
1749         tidy_out(doc, "in one table cell and the </form> in another. If the <form> is\n");
1750         tidy_out(doc, "placed before a table, the </form> cannot be placed inside the\n");
1751         tidy_out(doc, "table! Note that one form can't be nested inside another!\n\n");
1752     }
1753
1754     if (doc->badForm & flg_BadMain) /* Issue #166 - repeated <main> element */
1755     {
1756         tidy_out(doc, "Only one <main> element is allowed in a document.\n");
1757         tidy_out(doc, "Subsequent <main> elements have been discarded, which may\n");
1758         tidy_out(doc, "render the document invalid.\n");
1759     }
1760     
1761     if (doc->badAccess)
1762     {
1763         /* Tidy "classic" accessibility tests */
1764         if ( cfg(doc, TidyAccessibilityCheckLevel) == 0 )
1765         {
1766             if (doc->badAccess & BA_MISSING_SUMMARY)
1767             {
1768                 tidy_out(doc, "The table summary attribute should be used to describe\n");
1769                 tidy_out(doc, "the table structure. It is very helpful for people using\n");
1770                 tidy_out(doc, "non-visual browsers. The scope and headers attributes for\n");
1771                 tidy_out(doc, "table cells are useful for specifying which headers apply\n");
1772                 tidy_out(doc, "to each table cell, enabling non-visual browsers to provide\n");
1773                 tidy_out(doc, "a meaningful context for each cell.\n\n");
1774             }
1775
1776             if (doc->badAccess & BA_MISSING_IMAGE_ALT)
1777             {
1778                 tidy_out(doc, "The alt attribute should be used to give a short description\n");
1779                 tidy_out(doc, "of an image; longer descriptions should be given with the\n");
1780                 tidy_out(doc, "longdesc attribute which takes a URL linked to the description.\n");
1781                 tidy_out(doc, "These measures are needed for people using non-graphical browsers.\n\n");
1782             }
1783
1784             if (doc->badAccess & BA_MISSING_IMAGE_MAP)
1785             {
1786                 tidy_out(doc, "Use client-side image maps in preference to server-side image\n");
1787                 tidy_out(doc, "maps as the latter are inaccessible to people using non-\n");
1788                 tidy_out(doc, "graphical browsers. In addition, client-side maps are easier\n");
1789                 tidy_out(doc, "to set up and provide immediate feedback to users.\n\n");
1790             }
1791
1792             if (doc->badAccess & BA_MISSING_LINK_ALT)
1793             {
1794                 tidy_out(doc, "For hypertext links defined using a client-side image map, you\n");
1795                 tidy_out(doc, "need to use the alt attribute to provide a textual description\n");
1796                 tidy_out(doc, "of the link for people using non-graphical browsers.\n\n");
1797             }
1798
1799             if ((doc->badAccess & BA_USING_FRAMES) && !(doc->badAccess & BA_USING_NOFRAMES))
1800             {
1801                 tidy_out(doc, "Pages designed using frames presents problems for\n");
1802                 tidy_out(doc, "people who are either blind or using a browser that\n");
1803                 tidy_out(doc, "doesn't support frames. A frames-based page should always\n");
1804                 tidy_out(doc, "include an alternative layout inside a NOFRAMES element.\n\n");
1805             }
1806
1807         }
1808
1809         tidy_out(doc, "For further advice on how to make your pages accessible\n");
1810         tidy_out(doc, "see %s", ACCESS_URL );
1811         if ( cfg(doc, TidyAccessibilityCheckLevel) > 0 )
1812             tidy_out(doc, " and %s", ATRC_ACCESS_URL );
1813         tidy_out(doc, ".\n" );
1814         tidy_out(doc, ". You may also want to try\n" );
1815         tidy_out(doc, "\"http://www.cast.org/bobby/\" which is a free Web-based\n");
1816         tidy_out(doc, "service for checking URLs for accessibility.\n\n");
1817     }
1818
1819     if (doc->badLayout)
1820     {
1821         if (doc->badLayout & USING_LAYER)
1822         {
1823             tidy_out(doc, "The Cascading Style Sheets (CSS) Positioning mechanism\n");
1824             tidy_out(doc, "is recommended in preference to the proprietary <LAYER>\n");
1825             tidy_out(doc, "element due to limited vendor support for LAYER.\n\n");
1826         }
1827
1828         if (doc->badLayout & USING_SPACER)
1829         {
1830             tidy_out(doc, "You are recommended to use CSS for controlling white\n");
1831             tidy_out(doc, "space (e.g. for indentation, margins and line spacing).\n");
1832             tidy_out(doc, "The proprietary <SPACER> element has limited vendor support.\n\n");
1833         }
1834
1835         if (doc->badLayout & USING_FONT)
1836         {
1837             tidy_out(doc, "You are recommended to use CSS to specify the font and\n");
1838             tidy_out(doc, "properties such as its size and color. This will reduce\n");
1839             tidy_out(doc, "the size of HTML files and make them easier to maintain\n");
1840             tidy_out(doc, "compared with using <FONT> elements.\n\n");
1841         }
1842
1843         if (doc->badLayout & USING_NOBR)
1844         {
1845             tidy_out(doc, "You are recommended to use CSS to control line wrapping.\n");
1846             tidy_out(doc, "Use \"white-space: nowrap\" to inhibit wrapping in place\n");
1847             tidy_out(doc, "of inserting <NOBR>...</NOBR> into the markup.\n\n");
1848         }
1849
1850         if (doc->badLayout & USING_BODY)
1851         {
1852             tidy_out(doc, "You are recommended to use CSS to specify page and link colors\n");
1853         }
1854     }
1855 }
1856
1857 #if 0
1858 void TY_(UnknownOption)( TidyDocImpl* doc, char c )
1859 {
1860     message( doc, TidyConfig,
1861              "unrecognized option -%c use -help to list options\n", c );
1862 }
1863
1864 void TY_(UnknownFile)( TidyDocImpl* doc, ctmbstr program, ctmbstr file )
1865 {
1866     message( doc, TidyConfig, 
1867              "%s: can't open file \"%s\"\n", program, file );
1868 }
1869 #endif
1870
1871 void TY_(NeedsAuthorIntervention)( TidyDocImpl* doc )
1872 {
1873     tidy_out(doc, "This document has errors that must be fixed before\n");
1874     tidy_out(doc, "using HTML Tidy to generate a tidied up version.\n\n");
1875 }
1876
1877 void TY_(GeneralInfo)( TidyDocImpl* doc )
1878 {
1879     if (!cfgBool(doc, TidyShowInfo)) return;
1880     tidy_out(doc, "About HTML Tidy: https://github.com/htacg/tidy-html5\n");
1881     tidy_out(doc, "Bug reports and comments: https://github.com/htacg/tidy-html5/issues\n");
1882     tidy_out(doc, "Or send questions and comments to: https://lists.w3.org/Archives/Public/public-htacg/\n");
1883     tidy_out(doc, "Latest HTML specification: http://dev.w3.org/html5/spec-author-view/\n");
1884     tidy_out(doc, "Validate your HTML documents: http://validator.w3.org/nu/\n");
1885     tidy_out(doc, "Lobby your company to join the W3C: http://www.w3.org/Consortium\n");
1886 }
1887
1888 #if SUPPORT_ACCESSIBILITY_CHECKS
1889
1890 void TY_(AccessibilityHelloMessage)( TidyDocImpl* doc )
1891 {
1892     tidy_out( doc, "\n" );
1893     tidy_out( doc, "Accessibility Checks: Version 0.1\n" );
1894     tidy_out( doc, "\n" );
1895 }
1896
1897 #endif /* SUPPORT_ACCESSIBILITY_CHECKS */
1898
1899 #if 0
1900 void TY_(HelloMessage)( TidyDocImpl* doc, ctmbstr date, ctmbstr filename )
1901 {
1902     tmbchar buf[ 2048 ];
1903     ctmbstr platform = "", helper = "";
1904     ctmbstr msgfmt = "\nHTML Tidy for %s (vers %s; built on %s, at %s)\n"
1905                   "Parsing \"%s\"\n";
1906
1907 #ifdef PLATFORM_NAME
1908     platform = PLATFORM_NAME;
1909     helper = " for ";
1910 #endif
1911     
1912     if ( TY_(tmbstrcmp)(filename, "stdin") == 0 )
1913     {
1914         /* Filename will be ignored at end of varargs */
1915         msgfmt = "\nHTML Tidy for %s (vers %s; built on %s, at %s)\n"
1916                  "Parsing console input (stdin)\n";
1917     }
1918     
1919     TY_(tmbsnprintf)(buf, sizeof(buf), msgfmt, helper, platform, 
1920                      date, __DATE__, __TIME__, filename);
1921     tidy_out( doc, buf );
1922 }
1923 #endif
1924
1925 void TY_(ReportMarkupVersion)( TidyDocImpl* doc )
1926 {
1927     if (doc->givenDoctype)
1928     {
1929         /* todo: deal with non-ASCII characters in FPI */
1930         message(doc, TidyInfo, "Doctype given is \"%s\"", doc->givenDoctype);
1931     }
1932
1933     if ( ! cfgBool(doc, TidyXmlTags) )
1934     {
1935         Bool isXhtml = doc->lexer->isvoyager;
1936         uint apparentVers;
1937         ctmbstr vers;
1938
1939         apparentVers = TY_(ApparentVersion)( doc );
1940
1941         vers = TY_(HTMLVersionNameFromCode)( apparentVers, isXhtml );
1942
1943         if (!vers)
1944             vers = "HTML Proprietary";
1945
1946         message( doc, TidyInfo, "Document content looks like %s", vers );
1947
1948         /* Warn about missing sytem identifier (SI) in emitted doctype */
1949         if ( TY_(WarnMissingSIInEmittedDocType)( doc ) )
1950             message( doc, TidyInfo, "No system identifier in emitted doctype" );
1951     }
1952 }
1953
1954 void TY_(ReportNumWarnings)( TidyDocImpl* doc )
1955 {
1956     if ( doc->warnings > 0 || doc->errors > 0 )
1957     {
1958         tidy_out( doc, "%u %s, %u %s were found!",
1959                   doc->warnings, doc->warnings == 1 ? "warning" : "warnings",
1960                   doc->errors, doc->errors == 1 ? "error" : "errors" );
1961
1962         if ( doc->errors > cfg(doc, TidyShowErrors) ||
1963              !cfgBool(doc, TidyShowWarnings) )
1964             tidy_out( doc, " Not all warnings/errors were shown.\n\n" );
1965         else
1966             tidy_out( doc, "\n\n" );
1967     }
1968     else
1969         tidy_out( doc, "No warnings or errors were found.\n\n" );
1970 }
1971
1972 /*
1973  * local variables:
1974  * mode: c
1975  * indent-tabs-mode: nil
1976  * c-basic-offset: 4
1977  * eval: (c-set-offset 'substatement-open 0)
1978  * end:
1979  */