2
ilstack.c - inline stack for compatibility with Mosaic
4
(c) 1998-2001 (W3C) MIT, INRIA, Keio University
5
See tidy.c for the copyright notice.
9
$Author: terry_teague $
10
$Date: 2001/08/19 19:19:20 $
18
extern Bool debug_flag;
19
extern Node *debug_element;
20
extern Lexer *debug_lexer;
22
/* duplicate attributes */
23
AttVal *DupAttrs(AttVal *attrs)
30
newattrs = NewAttribute();
32
newattrs->next = DupAttrs(attrs->next);
33
newattrs->attribute = wstrdup(attrs->attribute);
34
newattrs->value = wstrdup(attrs->value);
35
newattrs->dict = FindAttribute(newattrs);
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)
44
One issue arises with pushing inlines when
45
the tag is already pushed. For instance:
50
Shouldn't be mapped to
53
<p><em><em>more text</em></em>
55
void PushInline(Lexer *lexer, Node *node)
62
if (node->tag == null)
65
if (!(node->tag->model & CM_INLINE))
68
if (node->tag->model & CM_OBJECT)
71
if (node->tag != tag_font && IsPushed(lexer, node))
74
/* make sure there is enough space for the stack */
75
if (lexer->istacksize + 1 > lexer->istacklength)
77
if (lexer->istacklength == 0)
78
lexer->istacklength = 6; /* this is perhaps excessive */
80
lexer->istacklength = lexer->istacklength * 2;
81
lexer->istack = (IStack *)MemRealloc(lexer->istack,
82
sizeof(IStack)*(lexer->istacklength));
85
istack = &(lexer->istack[lexer->istacksize]);
86
istack->tag = node->tag;
88
istack->element = wstrdup(node->element);
89
istack->attributes = DupAttrs(node->attributes);
90
++(lexer->istacksize);
93
/* pop inline stack */
94
void PopInline(Lexer *lexer, Node *node)
101
if (node->tag == null)
104
if (!(node->tag->model & CM_INLINE))
107
if (node->tag->model & CM_OBJECT)
110
/* if node is </a> then pop until we find an <a> */
111
if (node->tag == tag_a)
113
while (lexer->istacksize > 0)
115
--(lexer->istacksize);
116
istack = &(lexer->istack[lexer->istacksize]);
118
while (istack->attributes)
120
av = istack->attributes;
123
MemFree(av->attribute);
127
istack->attributes = av->next;
131
if (istack->tag == tag_a)
133
MemFree(istack->element);
137
MemFree(istack->element);
144
if (lexer->istacksize > 0)
146
--(lexer->istacksize);
147
istack = &(lexer->istack[lexer->istacksize]);
149
while (istack->attributes)
151
av = istack->attributes;
154
MemFree(av->attribute);
158
istack->attributes = av->next;
162
MemFree(istack->element);
164
/* #427822 - fix by Randy Waki 7 Aug 00 */
165
if (lexer->insert >= lexer->istack + lexer->istacksize)
166
lexer->insert = null;
170
Bool IsPushed(Lexer *lexer, Node *node)
174
for (i = lexer->istacksize - 1; i >= 0; --i)
176
if (lexer->istack[i].tag == node->tag)
184
This has the effect of inserting "missing" inline
185
elements around the contents of blocklevel elements
186
such as P, TD, TH, DIV, PRE etc. This procedure is
187
called at the start of ParseBlock. when the inline
188
stack is not empty, as will be the case in:
190
<i><h1>italic heading</h1></i>
192
which is then treated as equivalent to
194
<h1><i>italic heading</i></h1>
196
This is implemented by setting the lexer into a mode
197
where it gets tokens from the inline stack rather than
198
from the input stream.
200
int InlineDup(Lexer *lexer, Node *node)
204
if ((n = lexer->istacksize - lexer->istackbase) > 0)
206
lexer->insert = &(lexer->istack[lexer->istackbase]);
214
defer duplicates when entering a table or other
215
element where the inlines shouldn't be duplicated
217
void DeferDup(Lexer *lexer)
219
lexer->insert = null;
223
Node *InsertedToken(Lexer *lexer)
229
/* this will only be null if inode != null */
230
if (lexer->insert == null)
239
is this is the "latest" node then update
240
the position, otherwise use current values
243
if (lexer->inode == null)
245
lexer->lines = lexer->in->curline;
246
lexer->columns = lexer->in->curcol;
250
node->type = StartTag;
251
node->implicit = yes;
252
node->start = lexer->txtstart;
253
/* #431734 [JTidy bug #226261 (was 126261)] - fix by Gary Peskin 20 Dec 00 */
254
node->end = lexer->txtend; /* was : lexer->txtstart; */
255
istack = lexer->insert;
256
if (lexer->istacksize == 0) /* Andy Quick 13 Jun 99 */
257
tidy_out(lexer->errout, "0-size istack!\n");
258
node->element = wstrdup(istack->element);
259
node->tag = istack->tag;
260
node->attributes = DupAttrs(istack->attributes);
262
/* advance lexer to next item on the stack */
263
n = lexer->insert - &(lexer->istack[0]);
265
/* and recover state if we have reached the end */
266
if (++n < lexer->istacksize)
267
lexer->insert = &(lexer->istack[n]);
269
lexer->insert = null;