Version:
~ [ 1.0 ] ~
1 /* istack.c -- inline stack for compatibility with Mosaic
2
3 (c) 1998-2004 (W3C) MIT, ERCIM, Keio University
4 See tidy.h for the copyright notice.
5
6 CVS Info :
7
8 $Author: arnaud02 $
9 $Date: 2004/12/06 12:53:25 $
10 $Revision: 1.16 $
11
12 */
13
14 #include "tidy-int.h"
15 #include "lexer.h"
16 #include "attrs.h"
17 #include "streamio.h"
18 #include "tmbstr.h"
19
20 /* duplicate attributes */
21 AttVal *DupAttrs( TidyDocImpl* doc, AttVal *attrs)
22 {
23 AttVal *newattrs;
24
25 if (attrs == NULL)
26 return attrs;
27
28 newattrs = NewAttribute();
29 *newattrs = *attrs;
30 newattrs->next = DupAttrs( doc, attrs->next );
31 newattrs->attribute = tmbstrdup(attrs->attribute);
32 newattrs->value = tmbstrdup(attrs->value);
33 newattrs->dict = FindAttribute(doc, newattrs);
34 newattrs->asp = attrs->asp ? CloneNode(doc, attrs->asp) : NULL;
35 newattrs->php = attrs->php ? CloneNode(doc, attrs->php) : NULL;
36 return newattrs;
37 }
38
39 /*
40 push a copy of an inline node onto stack
41 but don't push if implicit or OBJECT or APPLET
42 (implicit tags are ones generated from the istack)
43
44 One issue arises with pushing inlines when
45 the tag is already pushed. For instance:
46
47 <p><em>text
48 <p><em>more text
49
50 Shouldn't be mapped to
51
52 <p><em>text</em></p>
53 <p><em><em>more text</em></em>
54 */
55 void PushInline( TidyDocImpl* doc, Node *node)
56 {
57 Lexer* lexer = doc->lexer;
58 IStack *istack;
59
60 if (node->implicit)
61 return;
62
63 if (node->tag == NULL)
64 return;
65
66 if (!(node->tag->model & CM_INLINE))
67 return;
68
69 if (node->tag->model & CM_OBJECT)
70 return;
71
72 if ( !nodeIsFONT(node) && IsPushed(doc, node) )
73 return;
74
75 /* make sure there is enough space for the stack */
76 if (lexer->istacksize + 1 > lexer->istacklength)
77 {
78 if (lexer->istacklength == 0)
79 lexer->istacklength = 6; /* this is perhaps excessive */
80
81 lexer->istacklength = lexer->istacklength * 2;
82 lexer->istack = (IStack *)MemRealloc(lexer->istack,
83 sizeof(IStack)*(lexer->istacklength));
84 }
85
86 istack = &(lexer->istack[lexer->istacksize]);
87 istack->tag = node->tag;
88
89 istack->element = tmbstrdup(node->element);
90 istack->attributes = DupAttrs( doc, node->attributes );
91 ++(lexer->istacksize);
92 }
93
94 /* pop inline stack */
95 void PopInline( TidyDocImpl* doc, Node *node )
96 {
97 Lexer* lexer = doc->lexer;
98 AttVal *av;
99 IStack *istack;
100
101 if (node)
102 {
103 if (node->tag == NULL)
104 return;
105
106 if (!(node->tag->model & CM_INLINE))
107 return;
108
109 if (node->tag->model & CM_OBJECT)
110 return;
111
112 /* if node is </a> then pop until we find an <a> */
113 if ( nodeIsA(node) )
114 {
115 while (lexer->istacksize > 0)
116 {
117 --(lexer->istacksize);
118 istack = &(lexer->istack[lexer->istacksize]);
119
120 while (istack->attributes)
121 {
122 av = istack->attributes;
123 istack->attributes = av->next;
124 FreeAttribute( doc, av );
125 }
126
127 if ( istack->tag->id == TidyTag_A )
128 {
129 MemFree(istack->element);
130 break;
131 }
132
133 MemFree(istack->element);
134 }
135
136 return;
137 }
138 }
139
140 if (lexer->istacksize > 0)
141 {
142 --(lexer->istacksize);
143 istack = &(lexer->istack[lexer->istacksize]);
144
145 while (istack->attributes)
146 {
147 av = istack->attributes;
148 istack->attributes = av->next;
149 FreeAttribute( doc, av );
150 }
151
152 MemFree(istack->element);
153
154 /* #427822 - fix by Randy Waki 7 Aug 00 */
155 if (lexer->insert >= lexer->istack + lexer->istacksize)
156 lexer->insert = NULL;
157 }
158 }
159
160 Bool IsPushed( TidyDocImpl* doc, Node *node)
161 {
162 Lexer* lexer = doc->lexer;
163 int i;
164
165 for (i = lexer->istacksize - 1; i >= 0; --i)
166 {
167 if (lexer->istack[i].tag == node->tag)
168 return yes;
169 }
170
171 return no;
172 }
173
174 /*
175 This has the effect of inserting "missing" inline
176 elements around the contents of blocklevel elements
177 such as P, TD, TH, DIV, PRE etc. This procedure is
178 called at the start of ParseBlock. when the inline
179 stack is not empty, as will be the case in:
180
181 <i><h1>italic heading</h1></i>
182
183 which is then treated as equivalent to
184
185 <h1><i>italic heading</i></h1>
186
187 This is implemented by setting the lexer into a mode
188 where it gets tokens from the inline stack rather than
189 from the input stream.
190 */
191 int InlineDup( TidyDocImpl* doc, Node* node )
192 {
193 Lexer* lexer = doc->lexer;
194 int n;
195
196 if ((n = lexer->istacksize - lexer->istackbase) > 0)
197 {
198 lexer->insert = &(lexer->istack[lexer->istackbase]);
199 lexer->inode = node;
200 }
201
202 return n;
203 }
204
205 /*
206 defer duplicates when entering a table or other
207 element where the inlines shouldn't be duplicated
208 */
209 void DeferDup( TidyDocImpl* doc )
210 {
211 doc->lexer->insert = NULL;
212 doc->lexer->inode = NULL;
213 }
214
215 Node *InsertedToken( TidyDocImpl* doc )
216 {
217 Lexer* lexer = doc->lexer;
218 Node *node;
219 IStack *istack;
220 uint n;
221
222 /* this will only be NULL if inode != NULL */
223 if (lexer->insert == NULL)
224 {
225 node = lexer->inode;
226 lexer->inode = NULL;
227 return node;
228 }
229
230 /*
231
232 is this is the "latest" node then update
233 the position, otherwise use current values
234 */
235
236 if (lexer->inode == NULL)
237 {
238 lexer->lines = doc->docIn->curline;
239 lexer->columns = doc->docIn->curcol;
240 }
241
242 node = NewNode(lexer);
243 node->type = StartTag;
244 node->implicit = yes;
245 node->start = lexer->txtstart;
246 /* #431734 [JTidy bug #226261 (was 126261)] - fix by Gary Peskin 20 Dec 00 */
247 node->end = lexer->txtend; /* was : lexer->txtstart; */
248 istack = lexer->insert;
249
250 #if 0 && defined(_DEBUG)
251 if ( lexer->istacksize == 0 )
252 fprintf( stderr, "0-size istack!\n" );
253 #endif
254
255 node->element = tmbstrdup(istack->element);
256 node->tag = istack->tag;
257 node->attributes = DupAttrs( doc, istack->attributes );
258
259 /* advance lexer to next item on the stack */
260 n = (uint)(lexer->insert - &(lexer->istack[0]));
261
262 /* and recover state if we have reached the end */
263 if (++n < lexer->istacksize)
264 lexer->insert = &(lexer->istack[n]);
265 else
266 lexer->insert = NULL;
267
268 return node;
269 }
270
271
272
273
274
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.