1 /* -*- mode: c++ -*-
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is the Sablotron XSLT Processor.
13  *
14  * The Initial Developer of the Original Code is Ginger Alliance Ltd.
15  * Portions created by Ginger Alliance are Copyright (C) 2000-2002
16  * Ginger Alliance Ltd. All Rights Reserved.
17  *
18  * Contributor(s):
19  *
20  * Alternatively, the contents of this file may be used under the
21  * terms of the GNU General Public License Version 2 or later (the
22  * "GPL"), in which case the provisions of the GPL are applicable
23  * instead of those above.  If you wish to allow use of your
24  * version of this file only under the terms of the GPL and not to
25  * allow others to use your version of this file under the MPL,
26  * indicate your decision by deleting the provisions above and
27  * replace them with the notice and other provisions required by
28  * the GPL.  If you do not delete the provisions above, a recipient
29  * may use your version of this file under either the MPL or the
30  * GPL.
31  */
32 
33 #if !defined(OutputHIncl)
34 #define OutputHIncl
35 
36 // GP: clean
37 
38 #include "datastr.h"
39 #include "utf8.h"
40 #include "encoding.h"
41 
42 class DataLine;     // see uri.h
43 
44 enum OutputMethod
45 {
46     OUTPUT_XML,
47     OUTPUT_HTML,
48     OUTPUT_TEXT,
49     OUTPUT_XHTML,
50     OUTPUT_UNKNOWN
51 };
52 
53 enum EscMode
54 {
55     ESCAPING_NONE,
56     ESCAPING_URI,
57     ESCAPING_ATTR,
58 //    ESCAPING_CDATA, - use ESCAPING_NONE
59     ESCAPING_LT_AMP,
60     ESCAPING_HTML_URI,
61     ESCAPING_HTML_ATTR
62 };
63 
64 enum SAXOutputType
65 {
66   SAXOUTPUT_NONE,
67   //hard copy, no translations, no hidden ns....
68   SAXOUTPUT_COPY_TREE,
69   //for physical output, hidden ns, aliasing
70   SAXOUTPUT_AS_PHYSICAL,
71   //as physical, but use expat like names
72   SAXOUTPUT_INT_PHYSICAL
73 };
74 
75 #define THE_NAMESPACE_SEPARATOR '`'
76 
77 // the following must match the size of outputStringAtts[] - 1
78 // as defined in output.cpp
79 #define STRING_ITEMS_COUNT 8
80 
81 // constants for special values of precedence for xsl:output attributes
82 // use for OutputDefinition::setItemStr and setItemEQName
83 
84 // specify only if not yet specified, otherwise no error
85 #define OUTPUT_PRECEDENCE_WEAKEST -1
86 // override, no error
87 #define OUTPUT_PRECEDENCE_STRONGEST -2
88 // for internal use only
89 #define OUTPUT_PRECEDENCE_UNSPECIFIED -3
90 
91 //
92 //  StrPrec
93 //  string with (import) precedence
94 //  unspecified: precedence = -1
95 //  to set, new precedence must be less than existing (unless existing == -1)
96 //  special values of new precedence: override without checking (-1), set only if unspecified (-2)
97 //
98 
99 class StrPrec
100 {
101 
102 public:
StrPrec()103     StrPrec()
104 	{
105 	    precedence = OUTPUT_PRECEDENCE_UNSPECIFIED;
106 	};
107     // sets the string if new precedence is stronger
108     // returns TRUE if new pref is non-negative and equal to old (does not set in this case)
109     Bool set(const Str& newString, int newPrecedence);
get()110     const Str& get() const
111 	{
112 	    return string;
113 	}
114 private:
115     Str string;
116     int precedence;
117 };
118 
119 //
120 //  EQNamePrec
121 //  same as StrPrec but holding EQName
122 //
123 
124 class EQNamePrec
125 {
126 
127 public:
EQNamePrec()128     EQNamePrec()
129 	{
130 	    precedence = OUTPUT_PRECEDENCE_UNSPECIFIED;
131 	};
132   // sets the string if new precedence is stronger
133   // returns TRUE if new pref is non-negative and equal to old (does not set in this case)
134     Bool set(const EQName& newName, int newPrecedence);
get()135     const EQName& get() const
136 	{
137 	    return name;
138 	}
139 private:
140     EQName name;
141     int precedence;
142 };
143 
144 //
145 //  OutputDef
146 //  stores the output-controlling information for an XSLT tree
147 //
148 
149 #define OUTPUT_BUFFER_LIMIT     1024
150 #define OUTPUT_BUFFER_SIZE      OUTPUT_BUFFER_LIMIT + 64
151 
152 
153 #define HTML_SPECIAL            TRUE
154 #define NOT_HTML_SPECIAL        FALSE
155 
156 class OutputDefinition
157 {
158 public:
159     OutputDefinition();
160     ~OutputDefinition();
161     // sets a string item
162     // itemId identifies the attribute code, 'value' is the new value
163     // 'caller' is the xsl:output element
164     // precedence is the current import precedence
165     // (may be OUTPUT_PRECEDENCE_STRONGEST to override, ..._WEAKEST to only set if unset) if !caller
166     eFlag setItemStr(
167 	Sit S, XSL_ATT itemId, const Str& value, Vertex *caller, int precedence);
168     // sets an EQName item (@method or @cdata-sect-elems)
169     eFlag setItemEQName(
170 	Sit S, XSL_ATT itemId, const EQName& value, Vertex *caller, int precedence);
171     eFlag setDefaults(Sit S);
172     const Str& getValueStr(XSL_ATT itemId) const;
173     const EQName& getValueEQName(XSL_ATT itemId) const;
174     Bool askEQNameList(XSL_ATT itemId, const EQName &what) const;
175     int getStatus(XSL_ATT itemId) const;
176     OutputMethod getMethod() const;
177     Bool getIndent() const;
178     const Str& getEncoding() const;
179 private:
180     StrPrec stringItems[STRING_ITEMS_COUNT];
181     EQNamePrec
182         method;
183     EQNameList
184         cdataElems;
185     DataLine *targetDataLine;
186     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
187 };
188 
189 //
190 //
191 //  PhysicalOutputterObj
192 //
193 //
194 
195 class PhysicalOutputLayerObj
196 {
197 public:
198     PhysicalOutputLayerObj(CDesc encodingCD_);
199     ~PhysicalOutputLayerObj();
200     eFlag setOptions(Sit S, DataLine *targetDataLine_, OutputDefinition *outDef_);
201     eFlag outputElementStart(Sit S, const Str& name,
202         const NamespaceStack& namespaces, const int namespace_index,
203         const StrStrList& atts, Bool isEmpty);
204     eFlag outputElementEnd(Sit S, const Str& name, Bool isEmpty);
205     eFlag outputText(Sit S, const Str& contents, Bool outputEscaping, Bool inHTMLSpecial);
206     eFlag outputComment(Sit S, const Str& contents);
207     eFlag outputCDataSection(Sit S, const Str& contents);
208     eFlag outputPI(Sit S, const Str& target, const Str& data);
209     eFlag outputDTD(Sit S, const Str& name, const Str& publicId, const Str& systemId);
210     eFlag outputTrailingNewline(Sit S);
211     eFlag outputDone(Sit S);
212     eFlag setMethodByDefault(Sit S, OutputMethod method_);
getDataLine()213     DataLine* getDataLine() { return targetDataLine; };
214     eFlag close(Sit S);
215 private:
216     DataLine *targetDataLine;
217     OutputDefinition *outDef;
218     OutputMethod method;
219     Bool indent;
220     Bool after_markup;  //pc
221     int level;  //pc
222     char buffer[OUTPUT_BUFFER_SIZE],
223         smallBuf[SMALL_BUFFER_SIZE];
224     int curr;
225     Str encoding;
226     CDesc encodingCD;
227     Bool defaultNSWas;
228     eFlag sendOut(Sit S, const char* data, int length, EscMode escapeMode);
229     eFlag sendOutUntil(Sit S, const char* & data, int length,
230         EscMode escapeMode, const char* stoppingText);
231     int writeCharacterRef(char* dest, const char *src, EscMode escapeMode);
232     eFlag flushBuffer(Sit S);
233     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
234 };
235 
236 //
237 //
238 //  OutputterObj
239 //
240 //
241 
242 //output document (for multiple document output)
243 enum OutdocState {
244   OUTDOC_NEW,
245   OUTDOC_ACTIVE,
246   OUTDOC_FINISHED
247 };
248 
249 class OutputterObj;
250 class OutputDocument
251 {
252 public:
OutputDocument(Str h,OutputDefinition * d)253   OutputDocument(Str h, OutputDefinition *d) :
254     href (h), outputter(NULL), state(OUTDOC_NEW), def(d) {};
255   ~OutputDocument();
256   OutputterObj* setOutputter(OutputterObj* new_);
getOutputter()257   OutputterObj* getOutputter() { return outputter; };
getDefinition()258   OutputDefinition* getDefinition() { return def; };
getState()259   OutdocState getState() { return state; };
setState(OutdocState s)260   void setState(OutdocState s) { state = s; };
261   eFlag finish(Sit S);
getHref()262   Str &getHref() { return href; };
getURI()263   Str &getURI() { return uri; };
setURI(Str & val)264   void setURI(Str& val) { uri = val; };
265 private:
266   Str href;
267   OutputterObj *outputter;
268   OutdocState state;
269   OutputDefinition *def;
270   Str uri;
271 };
272 
273 //following structures are used for correct namespace exclusions
274 class SubtreeInfo;
275 
276 enum OutputterState
277 {
278     STATE_OUTSIDE = 0,
279     STATE_IN_MARKUP,
280     STATE_IN_ELEMENT,
281     STATE_IN_ATTRIBUTE,
282     STATE_IN_COMMENT,
283     STATE_IN_PI,
284     STATE_DONE,
285     STATE_UNDEFINED
286 };
287 
288 struct OutputHistoryItem
289 {
290   int flags;
291   int firstOwnNS;
292   OutputDocument *document;
293   OutputDocument *useDocument;
294 };
295 
296 typedef PList<OutputHistoryItem*> OutputHistory;
297 
298 //
299 //  FrontMatter
300 //
301 
302 enum FrontMatterKind
303 {
304     FM_TEXT,
305     FM_COMMENT,
306     FM_PI
307 };
308 
309 struct FrontMatterItem
310 {
311     FrontMatterKind kind;
312     Str string1, string2;
313     Bool disableEsc;
314 };
315 
316 class FrontMatter : public PList<FrontMatterItem*>
317 {
318 public:
319     eFlag appendConstruct(Sit S, FrontMatterKind kind, const Str& string1,
320         const Str& string2, Bool disableEsc);
321     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
322 };
323 
324 
325 class OutputterObj
326 {
327 public:
328     OutputterObj();
329     ~OutputterObj();
330     eFlag setOptions(Sit S, DataLine *targetDataLine_, OutputDefinition *outDef_);
331     eFlag setOptionsSAX(Sit S, SAXHandler *streaming_, void *userData, SAXOutputType saxout_);
332     eFlag eventBeginOutput(Sit S);
333     //_PH_ used for subtree serialization, ends with eventEndOutput
334     eFlag eventBeginSubtree(Sit S);
335     eFlag eventElementStart(Sit S, const EQName& name);
336     eFlag eventElementEnd(Sit S, const EQName& name);
337     eFlag eventAttributeStart(Sit S, const EQName& name);
338     eFlag eventAttributeEnd(Sit S);
339     eFlag eventCommentStart(Sit S);
340     eFlag eventCommentEnd(Sit S);
341   //eFlag eventExcludeNS(Sit S, UriList &exNS);
342     eFlag eventNamespace(Sit S, const Str& prefix, const Str& uri,
343 			 Bool hidden = FALSE);
344     eFlag eventPIStart(Sit S, const Str& name);
345     eFlag eventPIEnd(Sit S);
346     eFlag eventData(Sit S, const Str& data, Bool hardCData = FALSE);
347     eFlag eventCDataSection(Sit S, const Str& data);
348     eFlag eventDisableEscapingForNext(Sit S);
349     eFlag eventEndOutput(Sit S, Bool closePhysical = false);
350     eFlag eventTrailingNewline(Sit S);
351     eFlag setDocumentForLevel(Sit S, OutputDocument *doc);
352     OutputDocument* getDocumentForLevel(Bool forElement);
getSAXOutputType()353     SAXOutputType getSAXOutputType() { return mySAXOutputType; };
getPhysical()354     PhysicalOutputLayerObj* getPhysical() { return physical; };
355 private:
356     eFlag reportCurrData(Sit S, Bool hardCData = FALSE);
357     eFlag reportStartTag(Sit S, Bool isEmpty);
358     eFlag throwInMeta(Sit S);
359     Str* nameForSAX(Sit S, const EQName& q);
360     void pushLevel(const EQName& name);
361 //    void popLevel();
getLevel()362     int getLevel()
363     {
364       return history.number() - 1; //ignore the '/' frame
365     };
getFlags()366     int getFlags()
367     {
368         return (history.number()? history.last() -> flags : 0);
369     }
getFirstOwnNS()370     int getFirstOwnNS()
371     {
372         return (history.number()? history.last() -> firstOwnNS : 0);
373     }
374     Bool nsExcluded(Sit S, Str & uri);
375     eFlag reportXMLDeclIfMust(Sit S);
376     eFlag reportDTDIfMust(Sit S, const EQName& docElementName);
377     eFlag reportFront(Sit S);
378     void report(Sit S, MsgType type, MsgCode code, const Str& arg1, const Str& arg2);
379     //
380     PhysicalOutputLayerObj *physical;
381     SAXHandler *mySAXHandler;
382     void *mySAXUserData;
383     SAXOutputType mySAXOutputType;
384     OutputDefinition *outDef;
385     OutputMethod method;
386     CDesc encodingCD;
387     OutputterState state;
388     Bool outputEscaping;
389     DStr currData;
390     Str
391         currPIName;
392     EQName
393         currElement,
394         currAttName;
395     NamespaceStack
396         currNamespaces;
397     EQNameStrList
398         currAtts;
399     OutputHistory history;
400     Bool noElementYet,
401       noHeadYet,
402       delayedDTD;
403     FrontMatter front;
404 };
405 
406 
407 #endif  // OutputHIncl
408