1 /*
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 /* sdom.cpp */
34 
35 #define SablotAsExport
36 #include "sdom.h"
37 
38 #ifdef ENABLE_DOM
39 
40 #include "base.h"
41 #include "verts.h"
42 #include "tree.h"
43 #include "context.h"
44 #include "guard.h"
45 #include "platform.h"
46 
47 #define getTmpList(v) (toV(v) -> getOwner().tmpList)
48 
49 char* SDOM_ExceptionMsg[] =
50 {
51     // SDOM_OK
52     (char *) "OK",
53 
54     // SDOM_INDEX_SIZE_ERR 1
55     (char *) "list index out of bounds",
56 
57     // SDOM_DOMSTRING_SIZE_ERR 2
58     (char *) "invalid size of string",
59 
60     // SDOM_HIERARCHY_REQUEST_ERR 3
61     (char *) "hierarchy request error",
62 
63     // SDOM_WRONG_DOCUMENT_ERR 4
64     (char *) "node used in a document that did not create it",
65 
66     // SDOM_INVALID_CHARACTER_ERR 5
67     (char *) "invalid character in string",
68 
69     // SDOM_NO_DATA_ALLOWED_ERR 6
70     (char *) "data not allowed",
71 
72     // SDOM_NO_MODIFICATION_ALLOWED_ERR 7
73     (char *) "modification not allowed",
74 
75     // SDOM_NOT_FOUND_ERR 8
76     (char *) "reference to a non-existent node",
77 
78     // SDOM_NOT_FOUND_ERR 9
79     (char *) "functionality not supported",
80 
81     // SDOM_INUSE_ATTRIBUTE_ERR 10
82     (char *) "attribute is inuse",
83 
84     // SDOM_NOT_FOUND_ERR 10
85     (char *) "attribute is inuse",
86 
87     // SDOM_INVALID_STATE_ERR 11
88     (char *) "invalid state",
89 
90     // SDOM_SYNTAX_ERR 12
91     (char *) "syntax error",
92 
93     // SDOM_INVALID_MODIFICATION_ERR 13
94     (char *) "invalid modification",
95 
96     // SDOM_NAMESPACE_ERR 14
97     (char *) "namespace error",
98 
99     // SDOM_INVALID_ACCESS_ERR 15
100     (char *) "invalid access",
101 
102     // INVALID_NODE_TYPE
103     (char *) "invalid node type",
104 
105     // SDOM_QUERY_PARSE_ERR
106     (char *) "query parsing error",
107 
108     // SDOM_QUERY_EXECUTION_ERR
109     (char *) "query execution error",
110 
111     // SDOM_NOT_OK
112     (char *) "general exception"
113 };
114 
115 #define SDOM_Err(SITUA, CODE) { SIT( SITUA ).setSDOMExceptionCode( CODE );\
116     SIT( SITUA ).message(\
117     MT_ERROR, E2_SDOM, CODE, SDOM_ExceptionMsg[CODE]); return CODE; }
118 
119 #define SE(statement) {SDOM_Exception code__ = statement; \
120     if (code__) return code__;}
121 
122 #define SIT(PTR) (*(Situation*)PTR)
123 
124 #define isXMLNS_(qn, resolver) \
125     (qn.getPrefix() == resolver -> getOwner().stdPhrase(PHRASE_XMLNS) || \
126         (qn.getPrefix() == UNDEF_PHRASE && \
127 	     qn.getLocal() == resolver -> getOwner().stdPhrase(PHRASE_XMLNS)))
128 
129 //
130 //    globals
131 //
132 
133 SDOM_NodeCallback* theDisposeCallback = NULL;
134 #define ownerDoc(NODE) ( &(toV(NODE)->getOwner().getRoot()) )
135 
SDOM_newString(const Str & strg)136 char* SDOM_newString(const Str& strg)
137 {
138     int len = strg.length();
139     char *p = new char[len + 1];
140     strcpy(p, (char*)(const char*)strg);
141     p[len] = 0;
142     return p;
143 }
144 
145 //_JP_ v
146 // helper functions for namespace handling
___SDOM_swallowParentNSrec(SablotSituation s,SDOM_Node n,Tree * t,NSList * parentNs)147 SDOM_Exception ___SDOM_swallowParentNSrec(SablotSituation s, SDOM_Node n, Tree* t, NSList* parentNs)
148 {
149   // inherits from parentNs to begin of n->namespaces with respect to scoping
150   // do it recursively for all child elements
151     if ( isElement(toV(n)) ) {
152       NSList* currentNs   = &(toE(n) -> namespaces);
153       NmSpace* nm;
154       const int imax = parentNs->number() - 1;
155       for (int i = imax; i >= 0; i--) {
156           nm = toNS((*parentNs)[i]);
157 	  if (currentNs -> findNdx(nm -> prefix) == -1) {
158 	    nm = new(&(NZ(t) -> getArena())) NmSpace(*t, nm -> prefix, nm -> uri,
159 						     NSKIND_PARENT);
160 	    currentNs -> append(toV(nm));
161 	    nm -> parent = toV(n);
162 	  };
163       };
164       //zero in args => all appended namespaces will have kind == NSKIND_PARENT
165       //parentNs->giveCurrent(SIT(s), *currentNs, t, 0);
166       SDOM_Node checkedNode;
167       SE( SDOM_getFirstChild(s, n, &checkedNode) );
168       while (checkedNode) {
169 	SE( ___SDOM_swallowParentNSrec(s, checkedNode, t, currentNs) );
170 	SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
171       };
172     };
173     return SDOM_OK;
174 }
175 
__SDOM_swallowParentNS(SablotSituation s,SDOM_Node n)176 SDOM_Exception __SDOM_swallowParentNS(SablotSituation s, SDOM_Node n)
177 {
178   // inherits from parent's NSList to begin of n->namespaces with respect to scoping
179   // do it recursively for all child elements
180     if ( n && isElement(toV(n)) && toE(n) -> parent ) {
181       NSList* parentNs = &(toE(toE(n) -> parent) -> namespaces);
182       Tree* t = toTree(ownerDoc(toE(n)));
183       SE( ___SDOM_swallowParentNSrec(s, n, t, parentNs) );
184     };
185     return SDOM_OK;
186 }
187 
__SDOM_dropParentNS(SablotSituation s,SDOM_Node n)188 SDOM_Exception __SDOM_dropParentNS(SablotSituation s, SDOM_Node n)
189 {
190   // removes inherited namespaces from n->namespaces
191   // and from all child elements recursively
192     if ( n && isElement(toV(n)) ) {
193       NSList *checkedNs = &(toE(n) -> namespaces);
194       NmSpace *nm;
195       const int imax = checkedNs->number() - 1;
196       for (int i = imax; i >= 0; i--) {
197 	nm = toNS((*checkedNs)[i]);
198 	if ( nm -> usageCount == 0 && nm -> kind == NSKIND_PARENT ) {
199 	  checkedNs->rm(i);
200 	  nm -> parent = NULL;
201 	  //getTmpList(toE(n)).append(nm);
202 	  delete nm;
203 	};
204       };
205       SDOM_Node checkedNode;
206       SE( SDOM_getFirstChild(s, n, &checkedNode) );
207       while (checkedNode) {
208 	SE( __SDOM_dropParentNS(s, checkedNode) );
209 	SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
210       };
211     };
212     return SDOM_OK;
213 }
214 
__SDOM_refreshNS(SablotSituation s,SDOM_Node n,NmSpace * nmspace)215 SDOM_Exception __SDOM_refreshNS(SablotSituation s, SDOM_Node n, NmSpace* nmspace)
216 {
217   // appends or changes nmspace in all child elements recursively
218   // with respect to scoping
219     SDOM_Node checkedNode;
220     Tree *t;
221     NmSpace *nm;
222     SE( SDOM_getFirstChild(s, n, &checkedNode) );
223     while (checkedNode) {
224       if ( isElement(checkedNode) ) {
225 	  nm = toE(checkedNode) -> namespaces.find(nmspace -> prefix);
226 	  if ( nm ) {
227 	      if ( nm -> usageCount == 0 && nm -> kind == NSKIND_PARENT ) {
228 		  nm -> uri = nmspace -> uri;
229 		  SE( __SDOM_refreshNS(s, checkedNode, nmspace) );
230 	      };
231 	  } else {
232 	      //t = toTree(ownerDoc(toE(n)));
233 	      t = &(toE(n) -> getOwner());
234 	      nm = new(&(t -> getArena())) NmSpace(*t, nmspace -> prefix,
235 					               nmspace -> uri,
236 						       NSKIND_PARENT);
237 	      toE(checkedNode) -> namespaces.append(nm);
238 	      nm -> setParent(toE(checkedNode));
239 	      SE( __SDOM_refreshNS(s, checkedNode, nmspace) );
240 	  };
241       };
242       SE( SDOM_getNextSibling(s, checkedNode, &checkedNode) );
243     };
244     return SDOM_OK;
245 }
246 
__SDOM_canChangeUriNS(SablotSituation s,SDOM_Node n,NmSpace * nmspace,const SDOM_char * uri)247 SDOM_Exception __SDOM_canChangeUriNS(SablotSituation s, SDOM_Node n, NmSpace* nmspace, const SDOM_char *uri)
248 {
249   // order of tests has meaning
250   if ( !n || nmspace->usageCount == 0 )
251     // namespace without parent is changeable
252     // not used namespace is changeable
253       return SDOM_OK;
254 
255   Str olduri = toV(nmspace)->getOwner().expand(nmspace->uri);
256   if ( !strcmp((char*)olduri,(char*)uri) )
257       return SDOM_OK;// no change will be done
258 
259   return SDOM_NAMESPACE_ERR;
260 }
261 
262 
__SDOM_touchNS(SablotSituation s,SDOM_Node n,Phrase prefix,Phrase uri,NsKind kind,unsigned int maxUsageCount)263 SDOM_Exception __SDOM_touchNS(SablotSituation s, SDOM_Node n, Phrase prefix, Phrase uri, NsKind kind, unsigned int maxUsageCount)
264 {
265   //appends or changes n.namespaces to push prefix:uri into scope
266   //potentially refreshes childrens' namespaces
267   //suppose if kind == NSKIND_DECLARED then nm will NOT be immediatelly used
268   //suppose if kind == NSKIND_PARENT then nm will be immediatelly used
269   NmSpace *nm = toE(n)->namespaces.find(prefix);
270   if (nm) {
271     //nm->prefix == prefix
272     if (nm->uri == uri) {
273       if (kind == NSKIND_PARENT) nm -> usageCount++;
274       else nm -> kind = kind;
275     } else {
276       if ( kind == NSKIND_PARENT ) {
277 	if (nm -> kind == NSKIND_PARENT && nm -> usageCount <= maxUsageCount) {
278 	  nm -> uri = uri;
279 	  return __SDOM_refreshNS(s, n, nm);
280 	} else {
281 	  return SDOM_NAMESPACE_ERR;//_JP_ not in spec - namespace collision
282 	};
283       } else {
284 	if (nm -> usageCount <= maxUsageCount) {
285 	  nm -> kind = kind;
286 	  nm -> uri = uri;
287 	  return __SDOM_refreshNS(s, n, nm);
288 	} else {
289 	  return SDOM_NAMESPACE_ERR;//_JP_ not in spec - namespace collision
290 	};
291       };
292     };
293   } else {
294     //nm with prefix not exists
295     //!!chybka
296 	//Tree *auxt = NZ(toTree(ownerDoc(toE(n))));
297 	Tree *auxt = &(toE(n) -> getOwner());
298     nm = new(&(auxt -> getArena()))
299             NmSpace(toE(n) -> getOwner(),prefix, uri, kind);
300     if (kind == NSKIND_PARENT) nm -> usageCount = 1;
301     toE(n) -> namespaces.append(nm);
302     toV(nm) -> setParent(toE(n));
303   };
304   return SDOM_OK;
305 }
306 
307 
__SDOM_touchNSByChar(SablotSituation s,SDOM_Node n,SDOM_char * prefix,SDOM_char * uri,NsKind kind,int maxUsageCount)308 SDOM_Exception __SDOM_touchNSByChar(SablotSituation s, SDOM_Node n, SDOM_char* prefix, SDOM_char* uri, NsKind kind, int maxUsageCount)
309 {
310   //appends or changes n.namespaces to push prefix:uri into scope
311   //potentially refreshes childrens' namespaces
312   Phrase ph_prefix = prefix && strcmp((char*)prefix,"xmlns") ? toE(ownerDoc(toE(n)))->dict().insert((const char*)prefix) : UNDEF_PHRASE;
313   Phrase ph_uri = uri ? toE(ownerDoc(toE(n)))->dict().insert((const char*)uri) : UNDEF_PHRASE;
314   return __SDOM_touchNS(s, n, ph_prefix, ph_uri, kind, maxUsageCount);
315 }
316 
317 
318 //_JP_ ^
319 
320 
SDOM_createElement(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * tagName)321 SDOM_Exception SDOM_createElement(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *tagName)
322 {
323     QName q;
324     //try to find the document element
325     Element *e = NULL;
326     for (int i = 0; i < toRoot(d) -> contents.number(); i++)
327       {
328 	if (isElement(toRoot(d) -> contents[i]))
329 	  {
330 	    e = toE(toRoot(d) -> contents[i]);
331 	    break;
332 	  }
333       }
334     if (!e) e = toRoot(d);
335 
336     e -> setLogical(SIT(s), q, tagName, TRUE);
337     *pn = new(&(toTree(d) -> getArena())) Element(*toTree(d), q);
338     //_TH_ v
339     getTmpList(d).append(*pn);
340     //_TH_ ^
341     return SDOM_OK;
342 }
343 
344 //_JP_ v
SDOM_createElementNS(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * uri,const SDOM_char * qName)345 SDOM_Exception SDOM_createElementNS(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *uri, const SDOM_char *qName)
346 {
347     if ( !isValidQName((char*)qName) )
348         return SDOM_INVALID_CHARACTER_ERR;
349 
350     Str prefix = Str();
351     const char *colon = strchr((char*)qName,':');
352     QName q;
353 
354     if ( colon ) { //qName has prefix
355 
356         if ( !uri )
357 	    return SDOM_NAMESPACE_ERR;
358 
359 	prefix.nset((char*)qName, intPtrDiff(colon, qName));
360 
361 	if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
362 	    //redefinition of xml-namespace
363 	    return SDOM_NAMESPACE_ERR;
364 
365 	q.setPrefix(toE(d)->dict().insert((const char*)prefix));
366 	q.setLocal(toE(d)->dict().insert((const char*)((ptrdiff_t)colon + 1)));
367 	q.setUri(toE(d)->dict().insert((const char*)uri));
368 
369     } else {
370 
371         q.setPrefix(UNDEF_PHRASE);
372 	q.setLocal(toE(d)->dict().insert((const char*)qName));
373 
374 	if ( uri && strcmp((char*)uri,"") ) {
375 	    q.setUri(toE(d)->dict().insert((const char*)uri));
376 	} else {
377 	    q.setUri(UNDEF_PHRASE);
378 	};
379     };
380 
381     *pn = new(&(toTree(d) -> getArena())) Element(*toTree(d), q);
382     // no parent, no childs, no attributes => only 1 namespace:
383     NmSpace* newNS = new(&(toTree(d) -> getArena())) NmSpace(*toTree(d),
384 							     q.getPrefix(),
385 							     q.getUri(),
386 							     NSKIND_DECLARED);
387     newNS -> usageCount = 1;
388     toE(*pn) -> namespaces.append(newNS);
389     toV(newNS) -> setParent(toE(*pn));
390     //_TH_ v
391     getTmpList(d).append(*pn);
392     //_TH_ ^
393     return SDOM_OK;
394 }
395 //_JP_ ^
396 
_SDOM_createAttributeWithParent(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * name,SDOM_Node parent)397 SDOM_Exception _SDOM_createAttributeWithParent(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *name, SDOM_Node parent)
398 {
399     QName q;
400     //_JP_ v
401     // uses parent's NSList, if exists
402     if ( parent )
403         toE(parent) -> setLogical(SIT(s), q, name, FALSE);
404     else
405         toRoot(d) -> setLogical(SIT(s), q, name, FALSE);
406     //_JP_ ^
407     if ( !isXMLNS_(q, toRoot(d)) ) {
408         *pn = new(&(toTree(d) -> getArena()))
409 	    Attribute(*toTree(d), q, (char*)"", XSLA_NONE);
410 	if (parent)
411 	    toE(parent)->namespaces.incPrefixUsage(q.getPrefix());
412     } else
413         *pn = new(&(toTree(d) -> getArena()))
414 	    NmSpace(*toTree(d),
415 		    q.getPrefix() == UNDEF_PHRASE ? UNDEF_PHRASE : q.getLocal(),
416 		    UNDEF_PHRASE,
417 		    NSKIND_DECLARED);
418     //_TH_ v
419     getTmpList(d).append(*pn);
420     //_TH_ ^
421     return SDOM_OK;
422 }
423 
SDOM_createAttribute(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * name)424 SDOM_Exception SDOM_createAttribute(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *name)
425 {
426     return _SDOM_createAttributeWithParent(s, d, pn, name, NULL);
427 }
428 
429 //_JP_ v
SDOM_createAttributeNS(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * uri,const SDOM_char * qName)430 SDOM_Exception SDOM_createAttributeNS(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *uri, const SDOM_char *qName)
431 {
432     if ( !isValidQName((char*)qName) )
433         return SDOM_INVALID_CHARACTER_ERR;
434 
435     Str prefix = Str();
436     const char *colon = strchr((char*)qName,':');
437     QName q;
438 
439     if ( colon ) { //qName has prefix
440 
441         if ( !uri )
442 	    return SDOM_NAMESPACE_ERR;
443 
444 	prefix.nset((char*)qName, intPtrDiff(colon, qName));
445 
446 	if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
447 	    //redefinition of xml namespace
448 	    return SDOM_NAMESPACE_ERR;
449 
450 	if ( !strcmp((const char*)prefix,"xmlns") && strcmp(theXMLNSNamespace,uri) )
451 	    //redefinition of xmlns namespace
452 	    return SDOM_NAMESPACE_ERR;
453 
454 	q.setPrefix(toE(d)->dict().insert((const char*)prefix));
455 	q.setLocal(toE(d)->dict().insert((const char*)((ptrdiff_t)colon + 1)));
456 	q.setUri(toE(d)->dict().insert((const char*)uri));
457 
458     } else {
459 
460         q.setPrefix(UNDEF_PHRASE);
461 	q.setLocal(toE(d)->dict().insert((const char*)qName));
462 	if ( uri && strcmp((char*)uri,"") ) {
463 	    q.setUri(toE(d)->dict().insert((const char*)uri));
464 	} else {
465 	    q.setUri(UNDEF_PHRASE);
466 	};
467     };
468 
469     if ( !isXMLNS_(q, toRoot(d)) )
470         *pn = new(&(toTree(d) -> getArena()))
471 	    Attribute(*toTree(d), q, (char*)"", XSLA_NONE);
472     else
473         *pn = new(&(toTree(d) -> getArena()))
474 	    NmSpace(*toTree(d),
475 		    q.getLocal(),
476 		    UNDEF_PHRASE,
477 		    NSKIND_DECLARED);
478 
479     //_TH_ v
480     getTmpList(d).append(*pn);
481     //_TH_ ^
482     return SDOM_OK;
483 }
484 //_JP_ ^
485 
SDOM_createTextNode(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * data)486 SDOM_Exception SDOM_createTextNode(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *data)
487 {
488     *pn = new(&(toTree(d) -> getArena())) Text(*toTree(d), (char*) data);
489     //_TH_ v
490     getTmpList(d).append(*pn);
491     //_TH_ ^
492     return SDOM_OK;
493 }
494 
SDOM_createCDATASection(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * data)495 SDOM_Exception SDOM_createCDATASection(SablotSituation s, SDOM_Document d, SDOM_Node *pn, const SDOM_char *data)
496 {
497     SE( SDOM_createTextNode(s, d, pn, data) );
498     toText(toV(*pn)) -> beCDATA();
499     return SDOM_OK;
500 }
501 
SDOM_createComment(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * data)502 SDOM_Exception SDOM_createComment(
503     SablotSituation s,
504     SDOM_Document d,
505     SDOM_Node *pn,
506     const SDOM_char *data)
507 {
508     *pn = new(&(toTree(d) -> getArena())) Comment(*toTree(d), (char*) data);
509     //_TH_ v
510     getTmpList(d).append(*pn);
511     //_TH_ ^
512     return SDOM_OK;
513 }
514 
SDOM_createProcessingInstruction(SablotSituation s,SDOM_Document d,SDOM_Node * pn,const SDOM_char * target,const SDOM_char * data)515 SDOM_Exception SDOM_createProcessingInstruction(
516     SablotSituation s,
517     SDOM_Document d,
518     SDOM_Node *pn,
519     const SDOM_char *target,
520     const SDOM_char *data)
521 {
522     *pn = new(&(toTree(d) -> getArena())) ProcInstr(
523         *toTree(d),
524         toTree(d) -> unexpand((char*) target),
525 	(char*) data);
526     //_TH_ v
527     getTmpList(d).append(*pn);
528     //_TH_ ^
529     return SDOM_OK;
530 }
531 
SDOM_disposeNode(SablotSituation s,SDOM_Node n)532 SDOM_Exception SDOM_disposeNode(SablotSituation s, SDOM_Node n)
533 {
534     Vertex *v = toV(n);
535     switch(v -> vt & VT_BASE)
536     {
537         case VT_ELEMENT:
538 	        ccdelete(v, toE(v)); break;
539 	    case VT_ATTRIBUTE:
540 	        ccdelete(v, toA(v)); break;
541 	    case VT_NAMESPACE:
542 	        ccdelete(v, toNS(v)); break;
543 	    case VT_PI:
544 	        ccdelete(v, toPI(v)); break;
545 	    case VT_TEXT: // and CDATA
546 	        ccdelete(v, toText(v)); break;
547 	    case VT_XSL:
548 	        ccdelete(v, toX(v)); break;
549 	    case VT_COMMENT:
550 	        ccdelete(v, toComment(v)); break;
551 		default:
552 		    sabassert(!"disposeSDOM_Node");
553     }
554     return SDOM_OK;
555 }
556 
SDOM_getNodeType(SablotSituation s,SDOM_Node n,SDOM_NodeType * pType)557 SDOM_Exception SDOM_getNodeType(SablotSituation s, SDOM_Node n, SDOM_NodeType *pType)
558 {
559     Vertex *v = toV(n);
560     switch(basetype(v))
561     {
562         case VT_ROOT:
563 	        *pType = SDOM_DOCUMENT_NODE; break;
564         case VT_ELEMENT:
565 	        *pType = SDOM_ELEMENT_NODE; break;
566 	    case VT_ATTRIBUTE:
567 	        *pType = SDOM_ATTRIBUTE_NODE; break;
568 	    case VT_TEXT:
569 	    {
570 	        if (toText(v) -> isCDATA())
571 		        *pType = SDOM_CDATA_SECTION_NODE;
572 			else
573 	            *pType = SDOM_TEXT_NODE;
574 		}; break;
575 	    case VT_COMMENT:
576 	        *pType = SDOM_COMMENT_NODE; break;
577 		case VT_PI:
578 		    *pType = SDOM_PROCESSING_INSTRUCTION_NODE; break;
579 		case VT_NAMESPACE:
580 		  *pType = SDOM_ATTRIBUTE_NODE; break;
581 		default:
582 		    *pType = SDOM_OTHER_NODE;
583 	}
584 	return SDOM_OK;
585 }
586 
SDOM_getNodeName(SablotSituation s,SDOM_Node n,SDOM_char ** pName)587 SDOM_Exception SDOM_getNodeName(SablotSituation s, SDOM_Node n, SDOM_char **pName)
588 {
589     Str fullName;
590     Vertex *v = toV(n);
591     switch(v -> vt & VT_BASE)
592     {
593     case VT_ELEMENT:
594     {
595 	v -> getOwner().expandQStr(toE(v) -> getName(), fullName);
596 	*pName = SDOM_newString(fullName);
597     };
598     break;
599     case VT_ATTRIBUTE:
600     {
601 	v -> getOwner().expandQStr(toA(v) -> getName(), fullName);
602 	*pName = SDOM_newString(fullName);
603     };
604     break;
605     case VT_NAMESPACE:
606     {
607 	v -> getOwner().expandQStr(toNS(v) -> getName(), fullName);
608 	DStr fullName2 = "xmlns";
609 	if ( strcmp(fullName,"") ) {
610 	  fullName2 += ":";
611 	  fullName2 += fullName;
612 	}
613 	*pName = SDOM_newString(fullName2);
614     };
615     break;
616     case VT_TEXT: // and CDATA
617     {
618 	if (toText(v) -> isCDATA())
619 	    *pName = SDOM_newString("#cdata-section");
620 	else
621 	    *pName = SDOM_newString("#text");
622     }; break;
623     case VT_COMMENT:
624 	*pName = SDOM_newString("#comment"); break;
625     case VT_ROOT:
626 	*pName = SDOM_newString("#document"); break;
627     case VT_PI:
628 	*pName = SDOM_newString(toPI(v) -> getOwner().expand(toPI(v) -> getName().getLocal())); break;
629 
630     default:
631 	*pName = NULL;
632     }
633     return SDOM_OK;
634 }
635 
SDOM_getNodeNSUri(SablotSituation s,SDOM_Node n,SDOM_char ** pName)636 SDOM_Exception SDOM_getNodeNSUri(SablotSituation s, SDOM_Node n, SDOM_char **pName)
637 {
638     Str value;
639     Vertex *v = toV(n);
640     switch(v -> vt & VT_BASE)
641     {
642     case VT_ELEMENT:
643     {
644 	value = v -> getOwner().expand(toE(v) -> getName().getUri());
645 	*pName = SDOM_newString(value);
646     };
647     break;
648     case VT_ATTRIBUTE:
649     {
650 	value = v -> getOwner().expand(toA(v) -> getName().getUri());
651 	*pName = SDOM_newString(value);
652     };
653     break;
654     case VT_NAMESPACE:
655     {
656       *pName = SDOM_newString(theXMLNSNamespace);
657     };
658     break;
659     default:
660 	*pName = NULL;
661     }
662     return SDOM_OK;
663 }
664 
SDOM_getNodePrefix(SablotSituation s,SDOM_Node n,SDOM_char ** pName)665 SDOM_Exception SDOM_getNodePrefix(SablotSituation s, SDOM_Node n, SDOM_char **pName)
666 {
667     Str value;
668     Vertex *v = toV(n);
669     switch(v -> vt & VT_BASE)
670     {
671     case VT_ELEMENT:
672     {
673 	value = v -> getOwner().expand(toE(v) -> getName().getPrefix());
674 	*pName = SDOM_newString(value);
675     };
676     break;
677     case VT_ATTRIBUTE:
678     {
679 	value = v -> getOwner().expand(toA(v) -> getName().getPrefix());
680 	*pName = SDOM_newString(value);
681     };
682     break;
683     case VT_NAMESPACE:
684     {
685 	v -> getOwner().expandQStr(toNS(v) -> getName(), value);
686 	if ( !strcmp(value,"") ) {
687 	  *pName = SDOM_newString("");
688 	} else {
689 	  *pName = SDOM_newString("xmlns");
690 	};
691     };
692     break;
693     default:
694 	*pName = NULL;
695     }
696     return SDOM_OK;
697 }
698 
SDOM_getNodeLocalName(SablotSituation s,SDOM_Node n,SDOM_char ** pName)699 SDOM_Exception SDOM_getNodeLocalName(SablotSituation s, SDOM_Node n, SDOM_char **pName)
700 {
701     Str value;
702     Vertex *v = toV(n);
703     switch(v -> vt & VT_BASE)
704     {
705     case VT_ELEMENT:
706     {
707 	value = v -> getOwner().expand(toE(v) -> getName().getLocal());
708 	*pName = SDOM_newString(value);
709     };
710     break;
711     case VT_ATTRIBUTE:
712     {
713 	value = v -> getOwner().expand(toA(v) -> getName().getLocal());
714 	*pName = SDOM_newString(value);
715     };
716     break;
717     case VT_NAMESPACE:
718     {
719 	v -> getOwner().expandQStr(toNS(v) -> getName(), value);
720 	if ( !strcmp(value,"") ) {
721 	  *pName = SDOM_newString("xmlns");
722 	} else {
723 	  value = v -> getOwner().expand(toNS(v) -> getName().getLocal());
724 	  *pName = SDOM_newString(value);
725 	};
726 
727 
728     };
729     break;
730     default:
731 	*pName = NULL;
732     }
733     return SDOM_OK;
734 }
735 
SDOM_setNodeName(SablotSituation s,SDOM_Node n,const SDOM_char * name)736 SDOM_Exception SDOM_setNodeName(SablotSituation s, SDOM_Node n, const SDOM_char *name)
737 {
738     Vertex *v = toV(n);
739     QName q;
740     if (isRoot(v))
741         SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
742     switch (v -> vt & VT_BASE)
743     {
744     case VT_ELEMENT:
745 	toE(v) -> setLogical(SIT(s), q, name, TRUE);
746 	break;
747     default:
748     {
749 	if (v -> parent)
750 	    toE(v -> parent) -> setLogical(SIT(s), q, name, FALSE);
751 	else
752 	    v -> getOwner().getRoot().setLogical(SIT(s), q, name, FALSE);
753     }
754     }
755 
756     switch(v -> vt & VT_BASE)
757     {
758     case VT_ELEMENT:
759         if ( q.getPrefix() != UNDEF_PHRASE && !toE(v) -> namespaces.find(q.getPrefix()) )
760 	  SDOM_Err(s, SDOM_NAMESPACE_ERR);
761         toE(v) -> namespaces.decPrefixUsage(toE(v) -> name.getPrefix());
762 	toE(v) -> name = q;
763 	toE(v) -> namespaces.incPrefixUsage(q.getPrefix());
764 	break;
765     case VT_ATTRIBUTE:
766           if ( toA(v) -> parent ) {
767 	    Phrase curPrefix = toA(v) -> name.getPrefix();
768 	    Phrase newPrefix = q.getPrefix();
769 	    if ( (newPrefix != UNDEF_PHRASE
770 		  && !toE(toA(v) -> parent) -> namespaces.find(newPrefix))
771 		 ||
772 		 (newPrefix == toA(v)-> getOwner().stdPhrase(PHRASE_XMLNS)
773 		  || !strcmp(name,"xmlns")) ){
774 	      //attempt to change attribute to namespace
775 	      SDOM_Err(s, SDOM_NAMESPACE_ERR);
776 	    };
777 	    if ( curPrefix != UNDEF_PHRASE)
778 	      toE(toA(v) -> parent) -> namespaces.decPrefixUsage(curPrefix);
779 	    toA(v) -> name = q;
780 	    if ( newPrefix != UNDEF_PHRASE)
781 	      toE(toA(v) -> parent) -> namespaces.incPrefixUsage(newPrefix);
782 	  } else
783 	    toA(v) -> name = q;
784 	  break;
785     case VT_NAMESPACE:
786     {
787       if ( strcmp(name,"xmlns") ) {
788 	if ( !(q.getPrefix() == toNS(v)-> getOwner().stdPhrase(PHRASE_XMLNS)) ) {
789 	  //attempt to change namespace to attribute
790 	  SDOM_Err(s, SDOM_NAMESPACE_ERR);
791 	};
792       } else {
793 	//default namespace
794 	q.setLocal(UNDEF_PHRASE);
795       };
796       q.setPrefix(UNDEF_PHRASE);
797       if ( !(toNS(v) -> name == q) ) {
798 	if ( toNS(v) -> usageCount != 0 ) {
799 	  SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
800 	} else {
801 	  toNS(v) -> prefix = q.getLocal();
802 	  toNS(v) -> name = q;
803 	};
804       };
805     }; break;
806     case VT_PI:
807 	toPI(v) -> name = q;
808 	break;
809     default:
810 	SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
811     }
812     return SDOM_OK;
813 }
814 
SDOM_getNodeValue(SablotSituation s,SDOM_Node n,SDOM_char ** pValue)815 SDOM_Exception SDOM_getNodeValue(SablotSituation s, SDOM_Node n, SDOM_char **pValue)
816 {
817     Vertex *v = toV(n);
818     switch(v -> vt & VT_BASE)
819     {
820 	    case VT_ATTRIBUTE:
821 	        *pValue = SDOM_newString(toA(v) -> cont);
822 		    break;
823 	    case VT_NAMESPACE:
824 	        *pValue = SDOM_newString(v -> getOwner().expand(toNS(v) -> uri));
825 		    break;
826 	    case VT_TEXT: // and CDATA section
827 	        *pValue = SDOM_newString(toText(v) -> cont);
828 		    break;
829 	    case VT_COMMENT:
830 	        *pValue = SDOM_newString(toComment(v) -> cont);
831 		    break;
832 		case VT_PI:
833 	        *pValue = SDOM_newString(toPI(v) -> cont);
834 		    break;
835 		default:
836 		    // element and document (root) have void value
837 		    *pValue = NULL;
838 	}
839 	return SDOM_OK;
840 }
841 
SDOM_setNodeValue(SablotSituation s,SDOM_Node n,const SDOM_char * value)842 SDOM_Exception SDOM_setNodeValue(SablotSituation s, SDOM_Node n, const SDOM_char *value)
843 {
844     Vertex *v = toV(n);
845     switch(v -> vt & VT_BASE)
846     {
847 	    case VT_ATTRIBUTE:
848 	        toA(v) -> cont = value;
849 		    break;
850 	    case VT_NAMESPACE:
851 	        SE( __SDOM_canChangeUriNS(s, toNS(v) -> parent, toNS(v), value) );
852 	        toNS(v) -> uri = v -> getOwner().unexpand(value);
853 		    break;
854 	    case VT_TEXT: // and CDATA section
855 	        toText(v) -> cont = value;
856 		    break;
857 	    case VT_COMMENT:
858 	        toComment(v) -> cont = value;
859 		    break;
860 		case VT_PI:
861 	        toPI(v) -> cont = value;
862 		    break;
863 		default:
864 		    // element and document (root) have void value
865 		    SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
866 	}
867 	return SDOM_OK;
868 }
869 
SDOM_getParentNode(SablotSituation s,SDOM_Node n,SDOM_Node * pParent)870 SDOM_Exception SDOM_getParentNode(SablotSituation s, SDOM_Node n, SDOM_Node *pParent)
871 {
872     Vertex *v = toV(n);
873     if (isRoot(v) || isAttr(v) || isNS(v))
874         *pParent = NULL;
875 	else
876 	    *pParent = v -> parent;
877 	return SDOM_OK;
878 }
879 
SDOM_getFirstChild(SablotSituation s,SDOM_Node n,SDOM_Node * pFirstChild)880 SDOM_Exception SDOM_getFirstChild(SablotSituation s, SDOM_Node n, SDOM_Node *pFirstChild)
881 {
882     Vertex *v = toV(n);
883     if (!isElement(v) && !isRoot(v))
884         *pFirstChild = NULL;
885 	else
886 	{
887 	    int childCount = toE(v) -> contents.number();
888 	    if (childCount)
889 	        *pFirstChild = (SDOM_Node)(toE(v) -> contents[0]);
890 		else
891 		    *pFirstChild = NULL;
892 	}
893 	return SDOM_OK;
894 }
895 
SDOM_getLastChild(SablotSituation s,SDOM_Node n,SDOM_Node * pLastChild)896 SDOM_Exception SDOM_getLastChild(SablotSituation s, SDOM_Node n, SDOM_Node *pLastChild)
897 {
898     Vertex *v = toV(n);
899     if (!isElement(v) && !isRoot(v))
900         *pLastChild = NULL;
901 	else
902 	{
903 	    int childCount = toE(v) -> contents.number();
904 	    if (childCount)
905 	        *pLastChild = (SDOM_Node)(toE(v) -> contents.last());
906 		else
907 		    *pLastChild = NULL;
908 	}
909 	return SDOM_OK;
910 }
911 
SDOM_getPreviousSibling(SablotSituation s,SDOM_Node n,SDOM_Node * pPreviousSibling)912 SDOM_Exception SDOM_getPreviousSibling(SablotSituation s, SDOM_Node n, SDOM_Node *pPreviousSibling)
913 {
914     switch(toV(n) -> vt & VT_BASE)
915     {
916         case VT_ATTRIBUTE:
917 	    case VT_NAMESPACE:
918         case VT_ROOT:
919 	        *pPreviousSibling = NULL;
920 		    break;
921         default:
922             *pPreviousSibling = toV(n) -> getPreviousSibling();
923 	}
924     return SDOM_OK;
925 }
926 
SDOM_getNextSibling(SablotSituation s,SDOM_Node n,SDOM_Node * pNextSibling)927 SDOM_Exception SDOM_getNextSibling(SablotSituation s, SDOM_Node n, SDOM_Node *pNextSibling)
928 {
929     switch(toV(n) -> vt & VT_BASE)
930     {
931         case VT_ATTRIBUTE:
932     	case VT_NAMESPACE:
933         case VT_ROOT:
934 	        *pNextSibling = NULL;
935 		    break;
936         default:
937             *pNextSibling = toV(n) -> getNextSibling();
938 	}
939     return SDOM_OK;
940 }
941 
SDOM_getChildNodeIndex(SablotSituation s,SDOM_Node n,int index,SDOM_Node * pChildNode)942 SDOM_Exception SDOM_getChildNodeIndex(SablotSituation s, SDOM_Node n, int index, SDOM_Node *pChildNode)
943 {
944     Vertex *v = toV(n);
945     if ( (!isElement(v) && !isRoot(v))
946 	 || index < 0
947 	 || index >= toE(v) -> contents.number() )
948         *pChildNode = NULL;
949     else
950 	*pChildNode = (SDOM_Node)(toE(n) -> contents[index]);
951     return SDOM_OK;
952 }
953 
SDOM_getChildNodeCount(SablotSituation s,SDOM_Node n,int * count)954 SDOM_Exception SDOM_getChildNodeCount(SablotSituation s, SDOM_Node n, int *count)
955 {
956     Vertex *v = toV(n);
957     if ( !isElement(v) && !isRoot(v) )
958         *count = 0;
959     else
960 	*count = toE(v) -> contents.number();
961     return SDOM_OK;
962 }
963 
SDOM_getOwnerDocument(SablotSituation s,SDOM_Node n,SDOM_Document * pOwnerDocument)964 SDOM_Exception SDOM_getOwnerDocument(SablotSituation s, SDOM_Node n, SDOM_Document *pOwnerDocument)
965 {
966     if (isRoot(toV(n)))
967         *pOwnerDocument = NULL;
968 	else
969         *pOwnerDocument = ownerDoc(n);
970     return SDOM_OK;
971 }
972 
hasElementChild(RootNode * r)973 Bool hasElementChild(RootNode *r)
974 {
975     for (int i = 0; i < r -> contents.number(); i++)
976         if (isElement(r -> contents[i]))
977 	  return TRUE;
978     return FALSE;
979 }
980 
981 // is first ancestor of second?
isAncestor(Vertex * first,Vertex * second)982 Bool isAncestor(Vertex *first, Vertex *second)
983 {
984     for (Vertex *p = second; p; p = p -> parent)
985         if (p == first) return TRUE;
986 	return FALSE;
987 }
988 
SDOM_insertBefore(SablotSituation s,SDOM_Node n,SDOM_Node newChild,SDOM_Node refChild)989 SDOM_Exception SDOM_insertBefore(SablotSituation s, SDOM_Node n, SDOM_Node newChild, SDOM_Node refChild)
990 {
991     Vertex *v = toV(n);
992 
993     // check if v is an element (or root)
994     if (!isElement(v))
995         SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
996 
997 	// check the type of newChild
998 	if (!newChild)
999 	    SDOM_Err(s, SDOM_NOT_FOUND_ERR)
1000 	else
1001 	    switch(basetype(newChild))
1002     	{
1003     	    case VT_ATTRIBUTE:
1004     	    case VT_NAMESPACE:
1005     	    case VT_ROOT:
1006     	        SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1007     	}
1008 	// check if newChild is from the same doc
1009 	if ((isRoot(v) && ownerDoc(newChild) != v) ||
1010 	    (!isRoot(v) && ownerDoc(v) != ownerDoc(newChild)))
1011 	    SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1012 
1013 	// check type of the reference child
1014 	if (refChild)
1015 	    switch(toV(refChild) -> vt & VT_BASE)
1016     	{
1017     	    case VT_ATTRIBUTE:
1018     	    case VT_NAMESPACE:
1019     	    case VT_ROOT:
1020     	        SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1021     	}
1022 
1023 	// check if newChild is not an ancestor of n
1024 	if (isAncestor(toV(newChild), toV(n)))
1025 	    SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1026 
1027 	// check if not attempting to have more doc elements
1028 	if (isRoot(v) && isElement(newChild) && hasElementChild(toRoot(v)))
1029 	    SDOM_Err(s, SDOM_HIERARCHY_REQUEST_ERR);
1030 
1031 	// see if newChild needs to be removed from tree
1032 	Vertex *parent;
1033 	if (NULL != (parent = toV(newChild) -> parent))
1034 	    SE( SDOM_removeChild(s, parent, newChild) );
1035 	//_JP_ v
1036 // 	// v ???
1037 // 	int ndx = toE(v) -> contents.getIndex(toV(newChild));
1038 // 	if (ndx != -1)
1039 // 	    toE(v) -> contents.rm(ndx);
1040 // 	// ^ ???
1041 // 	//_TH_ v
1042 // 	getTmpList(n).rmP(newChild);
1043 // 	//_TH_ ^
1044  	int ndx = toE(v) -> contents.getIndex(toV(newChild));
1045  	if (ndx != -1)
1046  	    toE(v) -> contents.rm(ndx);
1047 	else
1048 	    getTmpList(n).rmP(newChild);
1049 	//_JP_ ^
1050 	if (refChild)
1051 	{
1052     	ndx = toE(v) -> contents.getIndex(toV(refChild));
1053 	    if (ndx == -1)
1054 	        SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1055 	    toE(v) -> contents.insertBefore(toV(newChild), ndx);
1056 	}
1057 	else
1058 	    toE(v) -> contents.append(toV(newChild));
1059 	    // toE(v) -> contents.appendAndSetOrdinal(toV(newChild));
1060 	toV(newChild) -> setParent(v);
1061 	//_JP_ v
1062 	//old_parent's not used namespaces was cleaned by SDOM_removeChild
1063 	SE( __SDOM_swallowParentNS(s, newChild) );
1064 	//_JP_ ^
1065 	return SDOM_OK;
1066 }
1067 
SDOM_removeChild(SablotSituation s,SDOM_Node n,SDOM_Node oldChild)1068 SDOM_Exception SDOM_removeChild(SablotSituation s, SDOM_Node n, SDOM_Node oldChild)
1069 {
1070     Vertex *v = toV(n);
1071     if (!isElement(v))
1072         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1073 	switch(toV(oldChild) -> vt & VT_BASE)
1074     	{
1075     	    case VT_ATTRIBUTE:
1076     	    case VT_NAMESPACE:
1077     	    case VT_ROOT:
1078     	        SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1079     	}
1080 	if (toV(oldChild) -> parent != toV(n))
1081 	    SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1082 	//_JP_ v
1083 	//SE( __SDOM_dropParentNS(s, oldChild) );
1084 	//_JP_ ^
1085 	toE(v) -> removeChild(toV(oldChild));
1086 	//_TH_ v
1087 	getTmpList(n).append(oldChild);
1088 	//_TH_ ^
1089     return SDOM_OK;
1090 }
1091 
SDOM_replaceChild(SablotSituation s,SDOM_Node n,SDOM_Node newChild,SDOM_Node oldChild)1092 SDOM_Exception SDOM_replaceChild(SablotSituation s, SDOM_Node n, SDOM_Node newChild, SDOM_Node oldChild)
1093 {
1094     SDOM_Node tmp;
1095     SE( SDOM_getParentNode(s, newChild, &tmp) );
1096     if (tmp) SE( SDOM_removeChild(s, tmp, newChild) );
1097 
1098     SE( SDOM_getNextSibling(s, oldChild, &tmp) );
1099     SE( SDOM_removeChild(s, n, oldChild) );
1100     SE( SDOM_insertBefore(s, n, newChild, tmp) );
1101 
1102     //_JP_ old version not satisfying DOM spec:
1103     //SE( SDOM_insertBefore(s, n, newChild, oldChild) );
1104     //SE( SDOM_removeChild(s, n, oldChild) );
1105 
1106     return SDOM_OK;
1107 }
1108 
SDOM_appendChild(SablotSituation s,SDOM_Node n,SDOM_Node newChild)1109 SDOM_Exception SDOM_appendChild(SablotSituation s, SDOM_Node n, SDOM_Node newChild)
1110 {
1111     return SDOM_insertBefore(s, n, newChild, NULL);
1112 }
1113 
1114 SDOM_Exception cloneVertex(SablotSituation, Tree *, Vertex *, int, Vertex **);
1115 
cloneVertexList(SablotSituation s,Tree * t,VertexList * vlForeign,int deep,Element * tParent)1116 SDOM_Exception cloneVertexList(SablotSituation s, Tree *t, VertexList *vlForeign, int deep, Element *tParent)
1117 {
1118     Vertex *newVertex;
1119     for (int i = 0; i < vlForeign -> number(); i++)
1120     {
1121         SE( cloneVertex(s, t, (*vlForeign)[i], deep, &newVertex) );
1122 	    // the following also handles atts and namespaces correctly
1123 	    tParent -> newChild(SIT(s), newVertex);
1124     }
1125     return SDOM_OK;
1126 }
1127 
cloneVertex(SablotSituation s,Tree * t,Vertex * foreign,int deep,Vertex ** clone)1128 SDOM_Exception cloneVertex(SablotSituation s, Tree *t, Vertex *foreign, int deep, Vertex **clone)
1129 {
1130     Tree *tForeign = &(foreign -> getOwner());
1131     QName q;
1132     EQName expanded;
1133 
1134 	if (basetype(foreign) == VT_ROOT)
1135 	    SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1136 
1137 	// get the correctly unexpanded name
1138 	if (basetype(foreign) == VT_ELEMENT ||
1139 	    basetype(foreign) == VT_ATTRIBUTE ||
1140 	    basetype(foreign) == VT_PI ||
1141 	    basetype(foreign) == VT_NAMESPACE)
1142 	{
1143         switch(basetype(foreign))
1144         {
1145             case VT_ELEMENT:
1146     		    tForeign -> expandQ(toE(foreign) -> getName(), expanded);
1147     		    break;
1148     	    case VT_ATTRIBUTE:
1149     		    tForeign -> expandQ(toA(foreign) -> getName(), expanded);
1150     		    break;
1151     	    case VT_NAMESPACE:
1152     		    tForeign -> expandQ(toNS(foreign) -> getName(), expanded);
1153     		    break;
1154     		case VT_PI:
1155     		    tForeign -> expandQ(toPI(foreign) -> getName(), expanded);
1156     		    break;
1157     	};
1158 	    q.setLocal(t -> unexpand(expanded.getLocal()));
1159 	    q.setPrefix(t -> unexpand(expanded.getPrefix()));
1160 	    q.setUri(t -> unexpand(expanded.getUri()));
1161     }
1162 
1163     // create the actual copy
1164     switch(basetype(foreign))
1165     {
1166         case VT_ELEMENT:
1167             *clone = new(&(t -> getArena()))
1168 	            Element(*t, q);
1169 	        break;
1170 	    case VT_ATTRIBUTE:
1171             *clone = new(&(t -> getArena()))
1172 	            Attribute(*t, q, toA(foreign) -> cont, XSLA_NONE);
1173 		    break;
1174 		case VT_NAMESPACE:
1175             *clone = new(&(t -> getArena())) NmSpace(*t,
1176 	            t -> unexpand(tForeign -> expand(toNS(foreign) -> prefix)),
1177 		        t -> unexpand(tForeign -> expand(toNS(foreign) -> uri)),
1178 			toNS(foreign) -> kind);
1179 	    // _JP_ v
1180 	    toNS(*clone) -> usageCount = toNS(foreign) -> usageCount;
1181 	    // _JP_ ^
1182 		    break;
1183 		case VT_PI:
1184             *clone = new(&(t -> getArena())) ProcInstr(*t, q.getLocal(), toPI(foreign) -> cont);
1185 		    break;
1186 	    case VT_COMMENT:
1187             *clone = new(&(t -> getArena())) Comment(*t, toComment(foreign) -> cont);
1188 	            break;
1189 	    case VT_TEXT:
1190 	        {
1191 	            *clone = new(&(t -> getArena())) Text(*t, toText(foreign) -> cont);
1192     	        if (toText(foreign) -> isCDATA())
1193                     toText(*clone) -> beCDATA();
1194 			}; break;
1195     }
1196 
1197     if (isElement(foreign))
1198     {
1199         // must clone atts and namespaces in any case
1200 	    sabassert(isElement(*clone));
1201         cloneVertexList(s, t, &(toE(foreign) -> atts), deep, toE(*clone));
1202         cloneVertexList(s, t, &(toE(foreign) -> namespaces), deep, toE(*clone));
1203 
1204 	    // if deep then recurse
1205 	    if (deep)
1206             cloneVertexList(s, t, &(toE(foreign) -> contents), deep, toE(*clone));
1207 	}
1208     return SDOM_OK;
1209 }
1210 
SDOM_cloneForeignNode(SablotSituation s,SDOM_Document d,SDOM_Node n,int deep,SDOM_Node * clone)1211 SDOM_Exception SDOM_cloneForeignNode(SablotSituation s, SDOM_Document d, SDOM_Node n, int deep, SDOM_Node *clone)
1212 {
1213   SDOM_Exception se = cloneVertex(s, toTree(d), toV(n), deep, (Vertex**) clone);
1214     //_JP_ v
1215   se = (se != SDOM_OK) ? se : __SDOM_dropParentNS(s, *clone);
1216     //_JP_ ^
1217     //_TH_ v
1218   getTmpList(d).append(*clone);
1219     //_TH_ ^
1220   return se;
1221 }
1222 
SDOM_cloneNode(SablotSituation s,SDOM_Node n,int deep,SDOM_Node * clone)1223 SDOM_Exception SDOM_cloneNode(SablotSituation s, SDOM_Node n, int deep, SDOM_Node *clone)
1224 {
1225     return SDOM_cloneForeignNode(s, ownerDoc(n), n, deep, clone);
1226 }
1227 
SDOM_getAttribute(SablotSituation s,SDOM_Node n,const SDOM_char * name,SDOM_char ** pValue)1228 SDOM_Exception SDOM_getAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *name, SDOM_char **pValue)
1229 {
1230     QName q;
1231     if (!isElement(toV(n)))
1232         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1233     Element *e = toE(toV(n));
1234 
1235     e -> setLogical(SIT(s), q, name, FALSE);
1236     Vertex *v = NULL;
1237     Bool isXMLNS = isXMLNS_(q, e);
1238     if (!isXMLNS)
1239         v = e -> atts.find(q);
1240 	else
1241 	    v = e -> namespaces.find(
1242 	        q.getLocal() != UNDEF_PHRASE ? q.getLocal() : UNDEF_PHRASE);
1243     if (!v)
1244         *pValue = SDOM_newString("");
1245 	else
1246 	{
1247 	    if (!isXMLNS)
1248 	      *pValue = SDOM_newString(toA(v) -> cont);
1249 	    else
1250 	      *pValue = SDOM_newString(e -> getOwner().expand(toNS(v) -> uri));
1251 	}
1252     return SDOM_OK;
1253 }
1254 
SDOM_getAttributeNS(SablotSituation s,SDOM_Node n,SDOM_char * uri,SDOM_char * local,SDOM_char ** pValue)1255 SDOM_Exception SDOM_getAttributeNS(SablotSituation s, SDOM_Node n, SDOM_char *uri, SDOM_char *local, SDOM_char **pValue)
1256 {
1257     QName q;
1258     if (!isElement(toV(n)))
1259         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1260     Element *e = toE(toV(n));
1261 
1262     Vertex *v = NULL;
1263     Bool isXMLNS = ( !strcmp((char*)uri,theXMLNSNamespace) );
1264     if ( !isXMLNS ) {
1265         const int attcount = e -> atts.number();
1266 	for (int i = 0; i < attcount; i++) {
1267 	  q = toA(e->atts[i]) -> name;
1268 	  if (!strcmp((char*)local, (char*)(e -> getOwner().expand(q.getLocal())))
1269 	      && !strcmp((char*)uri, (char*)(e -> getOwner().expand(q.getUri())))) {
1270 	    v = e -> atts[i];
1271 	    break;
1272 	  };
1273 	};
1274     } else {
1275         const int nscount = e -> namespaces.number();
1276 	for (int i = 0; i < nscount; i++) {
1277 	  q = toNS(e->namespaces[i]) -> name;
1278 	  if (!strcmp((char*)local, (char*)(e -> getOwner().expand(toNS(e->namespaces[i])->prefix)))) {
1279 	    v = e -> namespaces[i];
1280 	    break;
1281 	  };
1282 	};
1283     }
1284     if (!v)
1285         *pValue = SDOM_newString("");
1286 	else
1287 	{
1288 	    if (!isXMLNS)
1289 	      *pValue = SDOM_newString(toA(v) -> cont);
1290 	    else
1291 	      *pValue = SDOM_newString(e -> getOwner().expand(toNS(v) -> uri));
1292 	}
1293     return SDOM_OK;
1294 }
1295 
SDOM_getAttributeNode(SablotSituation s,SDOM_Node n,const SDOM_char * name,SDOM_Node * attr)1296 SDOM_Exception SDOM_getAttributeNode(SablotSituation s, SDOM_Node n, const SDOM_char *name, SDOM_Node *attr)
1297 {
1298     QName q;
1299     if ( !isElement(toV(n)) )
1300         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1301     Element *e = toE(toV(n));
1302 
1303     e -> setLogical(SIT(s), q, name, FALSE);
1304     Vertex *v = NULL;
1305     Bool isXMLNS = isXMLNS_(q, e);
1306     if (!isXMLNS)
1307         v = e -> atts.find(q);
1308 	else
1309 	  {
1310 	    v = e -> namespaces.find(
1311 			q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS)?
1312 				     q.getLocal() : UNDEF_PHRASE);
1313 	  }
1314     if (!v)
1315         *attr = 0;
1316     else
1317       {
1318 	*attr = (SDOM_Node)v;
1319       }
1320     return SDOM_OK;
1321 }
1322 
SDOM_getAttributeNodeNS(SablotSituation s,SDOM_Node n,SDOM_char * uri,SDOM_char * local,SDOM_Node * attr)1323 SDOM_Exception SDOM_getAttributeNodeNS(SablotSituation s, SDOM_Node n, SDOM_char *uri, SDOM_char *local, SDOM_Node *attr)
1324 {
1325     QName q;
1326     if (!isElement(toV(n)))
1327         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1328     Element *e = toE(toV(n));
1329 
1330     Vertex *v = NULL;
1331     if ( strcmp((char*)uri,theXMLNSNamespace) ) {
1332       //true attribute
1333         const int attcount = e -> atts.number();
1334 	for (int i = 0; i < attcount; i++) {
1335 	  q = toA(e->atts[i]) -> name;
1336 	  if (!strcmp((char*)local, (char*)(e -> getOwner().expand(q.getLocal())))
1337 	      && !strcmp((char*)uri, (char*)(e -> getOwner().expand(q.getUri())))) {
1338 	    v = e -> atts[i];
1339 	    break;
1340 	  };
1341 	};
1342     } else {
1343       //namespace
1344         const int nscount = e -> namespaces.number();
1345 	char* pre;
1346 	if ( !strcmp(local,"xmlns") )
1347 	  pre = "";
1348 	else
1349 	  pre = (char*)local;
1350 
1351 	for (int i = 0; i < nscount; i++) {
1352 	  q = toNS(e->namespaces[i]) -> name;
1353 	  if (!strcmp(pre, (char*)(e -> getOwner().expand(toNS(e->namespaces[i])->prefix)))) {
1354 	    v = e -> namespaces[i];
1355 	    break;
1356 	  };
1357 	};
1358     };
1359     *attr = v;
1360     return SDOM_OK;
1361 }
1362 
SDOM_getAttributeNodeIndex(SablotSituation s,SDOM_Node n,const int index,SDOM_Node * attr)1363 SDOM_Exception SDOM_getAttributeNodeIndex(SablotSituation s, SDOM_Node n, const int index, SDOM_Node *attr)
1364 {
1365     if (!isElement(toV(n)))
1366         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1367     Element *e = toE(toV(n));
1368     int nscount = e -> namespaces.number();
1369 
1370     if (index < 0 || index >= nscount + e -> atts.number() )
1371         *attr = NULL;
1372     else
1373         if (index < nscount)
1374 	    *attr = (SDOM_Node)(e -> namespaces[index]);
1375 	else
1376             *attr = (SDOM_Node)(e -> atts[index-nscount]);
1377     return SDOM_OK;
1378 }
1379 
SDOM_getAttributeNodeCount(SablotSituation s,SDOM_Node n,int * count)1380 SDOM_Exception SDOM_getAttributeNodeCount(SablotSituation s, SDOM_Node n, int *count)
1381 {
1382     if (!isElement(toV(n)))
1383         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1384     Element *e = toE(toV(n));
1385     *count = e -> namespaces.number()  +  e -> atts.number();
1386     return SDOM_OK;
1387 }
1388 
1389 
SDOM_setAttribute(SablotSituation s,SDOM_Node n,const SDOM_char * attName,const SDOM_char * attValue)1390 SDOM_Exception SDOM_setAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *attName, const SDOM_char *attValue)
1391 {
1392     QName q;
1393     if (!isElement(toV(n)))
1394         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1395     Element *e = toE(toV(n));
1396 
1397     e -> setLogical(SIT(s), q, attName, FALSE);
1398     Vertex *v;
1399     if ( !isXMLNS_(q, e) ) {
1400         v = e -> atts.find(q);
1401 	if (!v) {
1402 	    SE( _SDOM_createAttributeWithParent(s, ownerDoc(e), (SDOM_Node*) &v, attName, e));
1403 	    //_TH_ v
1404 	    getTmpList(n).rmP(v);
1405 	    //_TH_ ^
1406 	    e -> atts.append(toA(v));
1407 	    toV(v) -> setParent(e);
1408 	};
1409 	SE( SDOM_setNodeValue(s, v, attValue) );
1410     } else { //attribute is namespace declaration
1411         v = e -> namespaces.find(q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS) ? q.getLocal() : UNDEF_PHRASE);
1412 	if (!v) {
1413 	    SE( _SDOM_createAttributeWithParent(s, ownerDoc(e), (SDOM_Node*) &v, attName, e));
1414 	    //_TH_ v
1415 	    getTmpList(n).rmP(v);
1416 	    //_TH_ ^
1417 	    e -> namespaces.append(toNS(v));
1418 	    toV(v) -> setParent(e);
1419 	};
1420 	SE( SDOM_setNodeValue(s, v, attValue) );
1421 	//_JP_ v
1422 	toNS(v) -> kind = NSKIND_DECLARED;
1423 	SE( __SDOM_refreshNS(s, n, toNS(v)) );
1424 	//_JP_ ^
1425     };
1426 
1427     return SDOM_OK;
1428 }
1429 
1430 //_JP_ v
SDOM_setAttributeNS(SablotSituation s,SDOM_Node n,const SDOM_char * uri,const SDOM_char * qName,const SDOM_char * value)1431 SDOM_Exception SDOM_setAttributeNS(SablotSituation s, SDOM_Node n, const SDOM_char *uri, const SDOM_char *qName, const SDOM_char *value)
1432 {
1433     if (!isElement(toV(n)))
1434         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1435 
1436     if ( !isValidQName((char*)qName) )
1437         SDOM_Err(s, SDOM_INVALID_CHARACTER_ERR);
1438 
1439     QName q;
1440     Element *e = toE(toV(n));
1441     Str prefix = Str();
1442     char *colon = strchr((char*)qName,':');
1443 
1444     if ( colon ) { //qName has prefix
1445 
1446         if ( !uri )
1447 	    SDOM_Err(s, SDOM_NAMESPACE_ERR);
1448 
1449 	prefix.nset((char*)qName, intPtrDiff(colon, qName));
1450 
1451 	if ( !strcmp((const char*)prefix,"xml") && strcmp(theXMLNamespace,uri) )
1452 	    //redefinition of xml-namespace
1453 	    SDOM_Err(s, SDOM_NAMESPACE_ERR);
1454 
1455 	if ( !strcmp((const char*)prefix,"xmlns") && strcmp(theXMLNSNamespace,uri) )
1456 	    //redefinition of xmlns-namespace
1457 	    SDOM_Err(s, SDOM_NAMESPACE_ERR);
1458 
1459 	q.setPrefix(ownerDoc(toE(n))->dict().insert((const char*)prefix));
1460 	q.setLocal(ownerDoc(toE(n))->dict().insert((const char*)((ptrdiff_t)colon + 1)));
1461 	q.setUri(ownerDoc(toE(n))->dict().insert((const char*)uri));
1462 
1463     } else {
1464 
1465         q.setPrefix(UNDEF_PHRASE);
1466 	q.setLocal(ownerDoc(toE(n))->dict().insert((const char*)qName));
1467 
1468 	if ( uri && strcmp((char*)uri,"") ) {
1469 	    q.setUri(ownerDoc(toE(n))->dict().insert((const char*)uri));
1470 	} else {
1471 	    q.setUri(UNDEF_PHRASE);
1472 	};
1473     };
1474 
1475     SDOM_Node replaced;
1476     SE( SDOM_getAttributeNodeNS(s, n,
1477 				(SDOM_char*)(e -> getOwner().expand(q.getUri())),
1478 				(SDOM_char*)(e -> getOwner().expand(q.getLocal())),
1479 				&replaced) );
1480 
1481     if ( strcmp((char*)uri, theXMLNSNamespace) ) {
1482       //true attribute
1483       if ( replaced ) {
1484 	//attr with the same uri:local found
1485 	if ( q.getPrefix() == toA(replaced)->name.getPrefix() ) {
1486 	  //the same prefix
1487 	} else {
1488 	  //prefix != replaced.prefix
1489 	  if ( q.getPrefix() != UNDEF_PHRASE ) {
1490 	    SE( __SDOM_touchNS(s, n,
1491 			       q.getPrefix(),
1492 			       q.getUri(),
1493 			       NSKIND_PARENT, 0) );
1494 	    e -> namespaces.decPrefixUsage(toA(replaced)->name.getPrefix());
1495 	  };
1496 	  toA(replaced)->name.setPrefix(q.getPrefix());
1497 	};
1498       } else {
1499 	//attr with the same uri:local NOT found
1500 	if ( q.getPrefix() != UNDEF_PHRASE )
1501 	  SE( __SDOM_touchNS(s, n,
1502 			     q.getPrefix(),
1503 			     q.getUri(),
1504 			     NSKIND_PARENT, 0) );
1505 	Tree *tOwner = toTree(ownerDoc(e));
1506 	replaced = new(&(tOwner -> getArena()))
1507 	           Attribute(*tOwner, q, (char*)"", XSLA_NONE);
1508 	e -> atts.append(toA(replaced));
1509 	toV(replaced) -> setParent(e);
1510       };
1511       SE( SDOM_setNodeValue(s, replaced, value) );
1512 
1513     } else {
1514       // att is namespace
1515       SE( __SDOM_touchNSByChar(s, n,
1516 			       (SDOM_char*)(e -> getOwner().expand(q.getLocal())),
1517 			       (SDOM_char*)value,
1518 			       NSKIND_DECLARED, 0) );
1519   };
1520     return SDOM_OK;
1521 }
1522 
1523 
SDOM_setAttributeNode(SablotSituation s,SDOM_Node n,SDOM_Node attnode,SDOM_Node * replaced)1524 SDOM_Exception SDOM_setAttributeNode(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *replaced)
1525 {
1526   if ( !( isElement(toV(n)) && (isAttr(toV(attnode))
1527 				|| isNS(toV(attnode))) ) )
1528     SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1529   if ( ownerDoc(n) != ownerDoc(attnode) )
1530     SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1531   if ( toV(attnode) -> parent )
1532     SDOM_Err(s, SDOM_INUSE_ATTRIBUTE_ERR);
1533   Element *e = toE(toV(n));
1534   //NmSpace *nm;
1535   if ( isAttr(toV(attnode)) ) {
1536     Str attname;
1537     e -> getOwner().expandQStr(toA(attnode) -> getName(), attname);
1538     SE( SDOM_getAttributeNode(s, n, (SDOM_char*)attname, replaced) );
1539     if ( *replaced ) {
1540       //attr with the same prefix:local found
1541       if ( toA(attnode)->name.getUri() == toA(*replaced)->name.getUri() ) {
1542 	//the same uri
1543 // 	int ndx = e -> atts.findNdx(toA(*replaced)->name);
1544 // 	toV(*replaced) -> parent = NULL;
1545 // 	//_TH_ v
1546 // 	getTmpList(n).append(*replaced);
1547 // 	//_TH_ ^
1548 // 	e -> atts[ndx] = toV(attnode);
1549 	//_JP_ v
1550 	int ndx = toV(*replaced) -> ordinal;
1551 	toV(*replaced) -> parent = NULL;
1552 	//_TH_ v
1553 	getTmpList(n).append(*replaced);
1554 	getTmpList(n).rmP(attnode);
1555 	//_TH_ ^
1556 	e -> atts[ndx] = toV(attnode);
1557 	toV(attnode) -> ordinal = ndx;
1558 	//_JP_ ^
1559       } else {
1560 	//attnode.uri != replaced.uri
1561 	if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1562 	  SE( __SDOM_touchNS(s, n,
1563 			     toA(attnode)->name.getPrefix(),
1564 			     toA(attnode)->name.getUri(),
1565 			     NSKIND_PARENT, 1) );
1566 // 	int ndx = e -> atts.findNdx(toA(*replaced)->name);
1567 // 	toV(*replaced) -> parent = NULL;
1568 // 	//_TH_ v
1569 // 	getTmpList(n).append(*replaced);
1570 // 	//_TH_ ^
1571 // 	e -> atts[ndx] = toV(attnode);
1572 	//_JP_ v
1573 	int ndx = toV(*replaced) -> ordinal;
1574 	toV(*replaced) -> parent = NULL;
1575 	//_TH_ v
1576 	getTmpList(n).append(*replaced);
1577 	getTmpList(n).rmP(attnode);
1578 	//_TH_ ^
1579 	e -> atts[ndx] = toV(attnode);
1580 	toV(attnode) -> ordinal = ndx;
1581 	//_JP_ ^
1582       };
1583     } else {
1584       //attr with the same prefix:local NOT found
1585       if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1586 	SE( __SDOM_touchNS(s, n,
1587 			   toA(attnode)->name.getPrefix(),
1588 			   toA(attnode)->name.getUri(),
1589 			   NSKIND_PARENT, 0) );
1590       //_TH_ v
1591       getTmpList(n).rmP(attnode);
1592       //_TH_ ^
1593       e -> atts.append(toA(attnode));
1594     };
1595     toV(attnode) -> setParent(e);
1596 
1597   } else {
1598     // attnode is namespace
1599     int ndx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1600     if (ndx != -1) {
1601       //namespace with the attnode.prefix exists
1602       NmSpace *nm = toNS(e -> namespaces[ndx]);
1603       if ( nm -> uri == toNS(attnode) -> uri ) {
1604 	//namespace with attnode.prefix has attnode.uri
1605 	//_TH_ v
1606 	getTmpList(n).rmP(attnode);
1607 	//_TH_ ^
1608 	toV(nm) -> parent = NULL;
1609 	//_TH_ v
1610 	getTmpList(n).append(nm);
1611 	//_TH_ ^
1612 	e -> namespaces[ndx] = toV(attnode);
1613 	toV(attnode) -> setParent(e);
1614 	toV(attnode) -> ordinal = ndx;
1615 	toNS(attnode)->kind = nm->kind;
1616 	toNS(attnode)->usageCount = nm->usageCount;
1617 	*replaced = (SDOM_Node)nm;
1618       } else {
1619 	//namespace with attnode.prefix has NOT attnode.uri
1620 	if ( nm -> usageCount != 0 || nm -> kind == NSKIND_DECLARED ) {
1621 	  // namespace used
1622 	  SDOM_Err(s, SDOM_NAMESPACE_ERR);
1623 	} else {
1624 	  // namespace NOT used
1625 	  //_TH_ v
1626 	  getTmpList(n).rmP(attnode);
1627 	  //_TH_ ^
1628 	  toV(nm) -> parent = NULL;
1629 	  //_TH_ v
1630 	  getTmpList(n).append(nm);
1631 	  //_TH_ ^
1632 	  e -> namespaces[ndx] = toV(attnode);
1633 	  toV(attnode) -> setParent(e);
1634 	  toV(attnode) -> ordinal = ndx;
1635 	  toNS(attnode)->kind = NSKIND_DECLARED;
1636 	  toNS(attnode)->usageCount = 0;
1637 	  *replaced = (SDOM_Node)nm;
1638 	};
1639       };
1640     } else {
1641       //namespace with attnode.prefix NOT exists
1642       *replaced = NULL;
1643       toNS(attnode)->kind = NSKIND_DECLARED;
1644       toNS(attnode)->usageCount = 0;
1645       //_TH_ v
1646       getTmpList(n).rmP(attnode);
1647       //_TH_ ^
1648       e -> namespaces.append(toNS(attnode));
1649       toV(attnode) -> setParent(e);
1650       SE( __SDOM_refreshNS(s, n, toNS(attnode)) );
1651     };
1652   };
1653   return SDOM_OK;
1654 }
1655 
SDOM_setAttributeNodeNS(SablotSituation s,SDOM_Node n,SDOM_Node attnode,SDOM_Node * replaced)1656 SDOM_Exception SDOM_setAttributeNodeNS(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *replaced)
1657 {
1658   if ( !( isElement(toV(n)) && (isAttr(toV(attnode))
1659 				|| isNS(toV(attnode))) ) )
1660     SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1661   if ( ownerDoc(n) != ownerDoc(attnode) )
1662     SDOM_Err(s, SDOM_WRONG_DOCUMENT_ERR);
1663   if ( toV(attnode) -> parent )
1664     SDOM_Err(s, SDOM_INUSE_ATTRIBUTE_ERR);
1665   Element *e = toE(toV(n));
1666   //NmSpace *nm;
1667   if ( isAttr(toV(attnode)) ) {
1668     Str attname;
1669     e -> getOwner().expandQStr(toA(attnode) -> getName(), attname);
1670     SE( SDOM_getAttributeNodeNS(s, n,
1671 				(SDOM_char*)(e -> getOwner().expand(toA(attnode)->name.getUri())),
1672 				(SDOM_char*)(e -> getOwner().expand(toA(attnode)->name.getLocal())),
1673 				replaced) );
1674     if ( *replaced ) {
1675       //attr with the same uri:local found
1676       if ( toA(attnode)->name.getPrefix() == toA(*replaced)->name.getPrefix() ) {
1677 	//the same prefix
1678 // 	int ndx = e -> atts.findNdx(toA(*replaced)->name);
1679 // 	toV(*replaced) -> parent = NULL;
1680 // 	//_TH_ v
1681 // 	getTmpList(n).append(*replaced);
1682 // 	//_TH_ ^
1683 // 	e -> atts[ndx] = toV(attnode);
1684 	//_JP_ v
1685 	int ndx = toV(*replaced) -> ordinal;
1686 	toV(*replaced) -> parent = NULL;
1687 	//_TH_ v
1688 	getTmpList(n).append(*replaced);
1689 	getTmpList(n).rmP(attnode);
1690 	//_TH_ ^
1691 	e -> atts[ndx] = toV(attnode);
1692 	toV(attnode) -> ordinal = ndx;
1693 	//_JP_ ^
1694 
1695 	//+++++++++++++++++
1696       } else {
1697 	//attnode.prefix != replaced.prefix
1698 	if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1699 	  SE( __SDOM_touchNS(s, n,
1700 			     toA(attnode)->name.getPrefix(),
1701 			     toA(attnode)->name.getUri(),
1702 			     NSKIND_PARENT, 1) );
1703 	if ( toA(*replaced)->name.getPrefix() != UNDEF_PHRASE )
1704 	  e -> namespaces.decPrefixUsage(toA(*replaced)->name.getPrefix());
1705 // 	int ndx = e -> atts.findNdx(toA(*replaced)->name);
1706 // 	toV(*replaced) -> parent = NULL;
1707 // 	//_TH_ v
1708 // 	getTmpList(n).append(*replaced);
1709 // 	//_TH_ ^
1710 // 	e -> atts[ndx] = toV(attnode);
1711 	//_JP_ v
1712 	int ndx = toV(*replaced) -> ordinal;
1713 	toV(*replaced) -> parent = NULL;
1714 	//_TH_ v
1715 	getTmpList(n).rmP(attnode);
1716 	getTmpList(n).append(*replaced);
1717 	//_TH_ ^
1718 	e -> atts[ndx] = toV(attnode);
1719 	toV(attnode) -> ordinal = ndx;
1720 	//_JP_ ^
1721       };
1722     } else {
1723       //attr with the same uri:local NOT found
1724       if ( toA(attnode)->name.getPrefix() != UNDEF_PHRASE )
1725 	SE( __SDOM_touchNS(s, n,
1726 			   toA(attnode)->name.getPrefix(),
1727 			   toA(attnode)->name.getUri(),
1728 			   NSKIND_PARENT, 0) );
1729       //_TH_ v
1730       getTmpList(n).rmP(attnode);
1731       //_TH_ ^
1732       e -> atts.append(toA(attnode));
1733     };
1734     toV(attnode) -> setParent(e);
1735 
1736   } else {
1737     // attnode is namespace
1738     int ndx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1739     if (ndx != -1) {
1740       //namespace with the attnode.prefix exists
1741       NmSpace *nm = toNS(e -> namespaces[ndx]);
1742       if ( nm -> uri == toNS(attnode) -> uri ) {
1743 	//namespace with attnode.prefix has attnode.uri
1744 	//_TH_ v
1745 	getTmpList(n).rmP(attnode);
1746 	//_TH_ ^
1747 	toV(nm) -> parent = NULL;
1748 	//_TH_ v
1749 	getTmpList(n).append(nm);
1750 	//_TH_ ^
1751 	e -> namespaces[ndx] = toV(attnode);
1752 	toV(attnode) -> setParent(e);
1753 	toV(attnode) -> ordinal = ndx;
1754 	toNS(attnode)->kind = nm->kind;
1755 	toNS(attnode)->usageCount = nm->usageCount;
1756 	*replaced = (SDOM_Node)nm;
1757       } else {
1758 	//namespace with attnode.prefix has NOT attnode.uri
1759 	if ( nm -> usageCount != 0 || nm -> kind == NSKIND_DECLARED ) {
1760 	  // namespace used
1761 	  return SDOM_NAMESPACE_ERR;
1762 	} else {
1763 	  // namespace NOT used
1764 	  //_TH_ v
1765 	  getTmpList(n).rmP(attnode);
1766 	  //_TH_ ^
1767 	  toV(nm) -> parent = NULL;
1768 	  //_TH_ v
1769 	  getTmpList(n).append(nm);
1770 	  //_TH_ ^
1771 	  e -> namespaces[ndx] = toV(attnode);
1772 	  toV(attnode) -> setParent(e);
1773 	  toV(attnode) -> ordinal = ndx;
1774 	  toNS(attnode)->kind = NSKIND_DECLARED;
1775 	  toNS(attnode)->usageCount = 0;
1776 	  *replaced = (SDOM_Node)nm;
1777 	};
1778       };
1779     } else {
1780       //namespace with attnode.prefix NOT exists
1781       *replaced = NULL;
1782       toNS(attnode)->kind = NSKIND_DECLARED;
1783       toNS(attnode)->usageCount = 0;
1784       //_TH_ v
1785       getTmpList(n).rmP(attnode);
1786       //_TH_ ^
1787       e -> namespaces.append(toNS(attnode));
1788       toV(attnode) -> setParent(e);
1789       SE( __SDOM_refreshNS(s, n, toNS(attnode)) );
1790     };
1791   };
1792   return SDOM_OK;
1793 }
1794 
1795 
SDOM_removeAttributeNode(SablotSituation s,SDOM_Node n,SDOM_Node attnode,SDOM_Node * removed)1796 SDOM_Exception SDOM_removeAttributeNode(SablotSituation s, SDOM_Node n, SDOM_Node attnode, SDOM_Node *removed)
1797 {
1798     if (!isElement(toV(n)))
1799         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1800     Element *e = toE(toV(n));
1801 
1802     if (isAttr(attnode))
1803     {
1804         int attNdx = e -> atts.findNdx(toA(attnode)->name);
1805         if (attNdx != -1)
1806         {
1807 	    //_TH_ v
1808 	    Vertex *tmp = e -> atts[attNdx];
1809 	    //_TH_ ^
1810             tmp -> parent = NULL;
1811             e -> atts.rm(attNdx);
1812 	    //_TH_ v
1813 	    getTmpList(n).append(tmp);
1814 	    //_TH_ ^
1815 	    if (toA(tmp) -> name.getPrefix() != UNDEF_PHRASE)
1816 	        e -> namespaces.decPrefixUsage(toA(tmp) -> name.getPrefix());
1817 	    *removed = tmp;
1818     	} else {
1819 	  SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1820 	};
1821     }
1822     else
1823     {
1824         int attNdx = e -> namespaces.findNdx(toNS(attnode)->prefix);
1825         if (attNdx != -1)
1826 	{
1827 	    if (toNS(e -> namespaces[attNdx]) -> usageCount != 0)
1828 	        SDOM_Err(s, SDOM_NO_MODIFICATION_ALLOWED_ERR);
1829 	    //_TH_ v
1830 	    Vertex *tmp = e -> namespaces[attNdx];
1831 	    //_TH_ ^
1832             tmp -> parent = NULL;
1833             e -> namespaces.rm(attNdx);
1834 	    //_TH_ v
1835 	    getTmpList(n).append(tmp);
1836 	    //_TH_ ^
1837 	    *removed = tmp;
1838     	} else {
1839 	  SDOM_Err(s, SDOM_NOT_FOUND_ERR);
1840 	};
1841     }
1842     return SDOM_OK;
1843 }
1844 //_JP_ ^
1845 
1846 
SDOM_removeAttribute(SablotSituation s,SDOM_Node n,const SDOM_char * name)1847 SDOM_Exception SDOM_removeAttribute(SablotSituation s, SDOM_Node n, const SDOM_char *name)
1848 {
1849     QName q;
1850     if (!isElement(toV(n)))
1851         SDOM_Err(s, SDOM_INVALID_NODE_TYPE);
1852     Element *e = toE(toV(n));
1853 
1854     e -> setLogical(SIT(s), q, name, FALSE);
1855     if (!isXMLNS_(q, e))
1856     {
1857         int attNdx = e -> atts.findNdx(q);
1858         if (attNdx != -1)
1859         {
1860 	    //_TH_ v
1861 	    Vertex *tmp = e -> atts[attNdx];
1862 	    //_TH_ ^
1863             e -> atts[attNdx] -> parent = NULL;
1864             e -> atts.rm(attNdx);
1865 	    //_TH_ v
1866 	    getTmpList(n).append(tmp);
1867 	    //_TH_ ^
1868 	    //_JP_ v
1869 	    if (toA(tmp) -> name.getPrefix() != UNDEF_PHRASE)
1870 	        e -> namespaces.decPrefixUsage(toA(tmp) -> name.getPrefix());
1871 	    //_JP_ ^
1872     	}
1873     }
1874     else
1875     {
1876         int attNdx = e -> namespaces.findNdx(
1877 			q.getLocal() != e -> getOwner().stdPhrase(PHRASE_XMLNS) ?
1878 			q.getLocal() : UNDEF_PHRASE);
1879         if (attNdx != -1)
1880 	{
1881 	    //_JP_ v
1882 	    if (toNS(e -> namespaces[attNdx]) -> usageCount != 0)
1883 	        return SDOM_NO_MODIFICATION_ALLOWED_ERR;
1884 	    //_JP_ ^
1885             e -> namespaces[attNdx] -> parent = NULL;
1886             e -> namespaces.rm(attNdx);
1887     	}
1888     }
1889     return SDOM_OK;
1890 }
1891 
1892 
SDOM_getAttributeElement(SablotSituation s,SDOM_Node attr,SDOM_Node * owner)1893 SDOM_Exception SDOM_getAttributeElement(SablotSituation s, SDOM_Node attr, SDOM_Node *owner)
1894 {
1895   Vertex *v = toV(attr);
1896   if ( isAttr(v) | isNS(v) )
1897     {
1898       *owner = v -> parent;
1899       return SDOM_OK;
1900     }
1901   else
1902     return SDOM_HIERARCHY_REQUEST_ERR;
1903 }
1904 
SDOM_getAttributeList(SablotSituation s,SDOM_Node n,SDOM_NodeList * pAttrList)1905 SDOM_Exception SDOM_getAttributeList(SablotSituation s, SDOM_Node n, SDOM_NodeList *pAttrList)
1906 {
1907     *pAttrList = new CList;
1908     if (isElement(toV(n)))
1909     {
1910         int i;
1911         NSList& namespaces = toE(toV(n)) -> namespaces;
1912 	    for (i = 0; i < namespaces.number(); i++)
1913 	        ((CList*)(*pAttrList)) -> append(namespaces[i]);
1914         AttList& atts = toE(toV(n)) -> atts;
1915 	    for (i = 0; i < atts.number(); i++)
1916 	        ((CList*)(*pAttrList)) -> append(atts[i]);
1917     }
1918     return SDOM_OK;
1919 }
1920 
1921 //
1922 //
1923 //
1924 
SDOM_docToString(SablotSituation s,SDOM_Document d,SDOM_char ** pSerialized)1925 SDOM_Exception SDOM_docToString(SablotSituation s, SDOM_Document d, SDOM_char **pSerialized)
1926 {
1927     // using explicit temp because of BeOS
1928     char *serializedTemp = NULL;
1929     toTree(d) -> serialize(SIT(s), serializedTemp);
1930     *pSerialized = serializedTemp;
1931     return SDOM_OK;
1932 }
1933 
1934 //_PH_
SDOM_nodeToString(SablotSituation s,SDOM_Document d,SDOM_Node n,SDOM_char ** pSerialized)1935 SDOM_Exception SDOM_nodeToString(SablotSituation s, SDOM_Document d,
1936 				 SDOM_Node n,
1937 				 SDOM_char **pSerialized)
1938 {
1939     char *serializedTemp = NULL;
1940     toTree(d) -> serializeNode(SIT(s), toE(n), serializedTemp);
1941     *pSerialized = serializedTemp;
1942     return SDOM_OK;
1943 }
1944 
1945 //
1946 //
1947 //
1948 
SDOM_getNodeListLength(SablotSituation s,SDOM_NodeList l,int * pLength)1949 SDOM_Exception SDOM_getNodeListLength(SablotSituation s, SDOM_NodeList l, int *pLength)
1950 {
1951     *pLength = ((CList*)l) -> number();
1952     return SDOM_OK;
1953 }
1954 
SDOM_getNodeListItem(SablotSituation s,SDOM_NodeList l,int index,SDOM_Node * pItem)1955 SDOM_Exception SDOM_getNodeListItem(SablotSituation s, SDOM_NodeList l, int index, SDOM_Node *pItem)
1956 {
1957     if ((index < 0) || (index >= ((CList*)l) -> number()))
1958         SDOM_Err(s, SDOM_INDEX_SIZE_ERR);
1959     *pItem = ((CList*)l) -> operator[](index);
1960     return SDOM_OK;
1961 }
1962 
SDOM_disposeNodeList(SablotSituation s,SDOM_NodeList l)1963 SDOM_Exception SDOM_disposeNodeList(SablotSituation s, SDOM_NodeList l)
1964 {
1965     if (!((CList*)l) -> decRefCount())
1966         delete (CList*)l;
1967 	return SDOM_OK;
1968 }
1969 
1970 
1971 //
1972 //
1973 //
1974 
SDOM_xql(SablotSituation s,const SDOM_char * query,SDOM_Node currentNode,SDOM_NodeList * pResult)1975 SDOM_Exception SDOM_xql(SablotSituation s, const SDOM_char *query, SDOM_Node currentNode, SDOM_NodeList *pResult)
1976 {
1977     RootNode &root = toV(currentNode) -> getOwner().getRoot();
1978 
1979     // find the document element
1980     int i;
1981     for (i = 0; i < root.contents.number(); i++)
1982         if (isElement(root.contents[i])) break;
1983 
1984     Element *docElement = (i < root.contents.number()) ?
1985         toE(root.contents[i]) : &root;
1986     Expression queryEx(*docElement);
1987     *pResult = NULL;
1988 
1989     // parse the query string as a non-pattern
1990     if (queryEx.parse(SIT(s), (char*)query, FALSE, TRUE))
1991         SDOM_Err(s, SDOM_QUERY_PARSE_ERR);
1992 
1993 	// create an initial context
1994     GP( Context ) dummy = new Context(NULL); //_cn_ no current node
1995     GP( Context ) c;
1996     c.assign(dummy);
1997     (*c).set(toV(currentNode));
1998 
1999 	// create the result context
2000 	if (queryEx.createContext(SIT(s), c))
2001         SDOM_Err(s, SDOM_QUERY_EXECUTION_ERR);
2002 
2003 	// preserve the CList
2004 	(*c).getArrayForDOM() -> incRefCount();
2005     c.unkeep();
2006 	*pResult = (SDOM_NodeList) (*c).getArrayForDOM();
2007     return SDOM_OK;
2008 }
2009 
SDOM_xql_ns(SablotSituation s,const SDOM_char * query,SDOM_Node currentNode,char ** nsmap,SDOM_NodeList * pResult)2010 SDOM_Exception SDOM_xql_ns(SablotSituation s, const SDOM_char *query, SDOM_Node currentNode, char** nsmap, SDOM_NodeList *pResult)
2011 {
2012   //RootNode &root = toV(currentNode) -> getOwner().getRoot();
2013 
2014   // find the document element
2015   //int i;
2016   //for (i = 0; i < root.contents.number(); i++)
2017   //    if (isElement(root.contents[i])) break;
2018   GP( Tree ) tree = new Tree(Str("noscheme:dummy-tree"), false);
2019   QName q;
2020   q.setLocal((*tree).unexpand(Str("dummy-root")));
2021   Element *e = new(&((*tree).getArena())) Element(*tree, q);
2022   e -> setSubtreeInfo((*tree).getRootSubtree());
2023   char ** aux = nsmap;
2024   while (*aux) {
2025     char *pref = *aux;
2026     char *uri = *(aux + 1);
2027     NmSpace *nm = new(&((*tree).getArena()))
2028       NmSpace(*tree, (*tree).unexpand(pref), (*tree).unexpand(uri),
2029 	      false, NSKIND_DECLARED);
2030     e -> newChild(SIT(s), nm);
2031     aux += 2;
2032   }
2033 
2034   Expression queryEx(*e);
2035   *pResult = NULL;
2036 
2037   // parse the query string as a non-pattern
2038   if (queryEx.parse(SIT(s), (char*)query, FALSE, TRUE))
2039     SDOM_Err(s, SDOM_QUERY_PARSE_ERR);
2040 
2041   // create an initial context
2042   GP( Context ) dummy = new Context(NULL); //_cn_ no current node
2043   GP( Context ) c;
2044   c.assign(dummy);
2045   (*c).set(toV(currentNode));
2046 
2047   // create the result context
2048   if (queryEx.createContext(SIT(s), c))
2049     SDOM_Err(s, SDOM_QUERY_EXECUTION_ERR);
2050 
2051   // preserve the CList
2052   (*c).getArrayForDOM() -> incRefCount();
2053   c.unkeep();
2054   *pResult = (SDOM_NodeList) (*c).getArrayForDOM();
2055   return SDOM_OK;
2056 }
2057 
2058 //
2059 //    exception retrieval
2060 //
2061 
SDOM_getExceptionCode(SablotSituation s)2062 int SDOM_getExceptionCode(SablotSituation s)
2063 {
2064     return SIT(s).getSDOMExceptionCode();
2065 }
2066 
SDOM_getExceptionMessage(SablotSituation s)2067 char* SDOM_getExceptionMessage(SablotSituation s)
2068 {
2069     return SDOM_newString(
2070         SDOM_ExceptionMsg[SDOM_getExceptionCode(s)]);
2071 }
2072 
SDOM_getExceptionDetails(SablotSituation s,int * code,char ** message,char ** documentURI,int * fileLine)2073 void SDOM_getExceptionDetails(
2074     SablotSituation s,
2075     int *code,
2076     char **message,
2077     char **documentURI,
2078     int *fileLine)
2079 {
2080     Str message_, documentURI_;
2081     MsgCode code_;
2082     int fileLine_;
2083     SIT(s).getSDOMExceptionExtra(code_, message_, documentURI_, fileLine_);
2084     *code = code_;
2085     *fileLine = fileLine_;
2086     *documentURI = SDOM_newString(documentURI_);
2087     *message = SDOM_newString(message_);
2088 }
2089 
2090 
2091 
2092 //
2093 //    internal
2094 //
2095 
SDOM_setNodeInstanceData(SDOM_Node n,void * data)2096 void SDOM_setNodeInstanceData(SDOM_Node n, void *data)
2097 {
2098     toV(n) -> setInstanceData(data);
2099 }
2100 
SDOM_getNodeInstanceData(SDOM_Node n)2101 void* SDOM_getNodeInstanceData(SDOM_Node n)
2102 {
2103     return toV(n) -> getInstanceData();
2104 }
2105 
SDOM_setDisposeCallback(SDOM_NodeCallback * f)2106 void SDOM_setDisposeCallback(SDOM_NodeCallback *f)
2107 {
2108     theDisposeCallback = f;
2109 }
2110 
SDOM_getDisposeCallback()2111 SDOM_NodeCallback* SDOM_getDisposeCallback()
2112 {
2113     return theDisposeCallback;
2114 }
2115 
2116 
2117 
2118 //_TH_ v
SDOM_tmpListDump(SDOM_Document doc,int p)2119 void SDOM_tmpListDump(SDOM_Document doc, int p)
2120 {
2121   getTmpList(doc).dump(p);
2122 }
2123 //_TH_ ^
2124 
SDOM_compareNodes(SablotSituation s,SDOM_Node n1,SDOM_Node n2,int * res)2125 SDOM_Exception SDOM_compareNodes(SablotSituation s, SDOM_Node n1, SDOM_Node n2, int *res)
2126 {
2127   if (&(toV(n1) -> getOwner()) == &(toV(n2) -> getOwner()) ) //the same owner
2128     {
2129       int s1 = toV(n1) -> stamp;
2130       int s2 = toV(n2) -> stamp;
2131       if (s1 < s2)
2132 	*res = -1;
2133       else if (s1 == s2)
2134 	*res = 0;
2135       else
2136 	*res = 1;
2137     }
2138   else
2139     {
2140       *res = strcmp( (char*)(toV(n1) -> getOwner().getURI()),
2141 		     (char*)(toV(n2) -> getOwner().getURI()) );
2142     }
2143   return SDOM_OK;
2144 }
2145 
2146 #endif /* ENABLE_DOM */
2147