~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

TidyLib
tidy/src/istack.c

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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.