0023024: Update headers of OCCT files
[occt.git] / src / VrmlData / VrmlData_Node.cxx
1 // Created on: 2006-05-25
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2006-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21 #include <Precision.hxx>
22 #include <VrmlData_Appearance.hxx>
23 #include <VrmlData_ImageTexture.hxx>
24 #include <VrmlData_Material.hxx>
25 #include <VrmlData_ShapeNode.hxx>
26 #include <VrmlData_UnknownNode.hxx>
27 #include <VrmlData_Scene.hxx>
28 #include <VrmlData_InBuffer.hxx>
29 #include <gp_XY.hxx>
30 #include <gp_XYZ.hxx>
31
32 #ifdef WNT
33 #define _CRT_SECURE_NO_DEPRECATE
34 #pragma warning (disable:4996)
35 #endif
36
37 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Node, Standard_Transient)
38 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Node, Standard_Transient)
39 IMPLEMENT_STANDARD_HANDLE  (VrmlData_ShapeNode, VrmlData_Node)
40 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_ShapeNode, VrmlData_Node)
41 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Texture, VrmlData_Node)
42 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Texture, VrmlData_Node)
43 IMPLEMENT_STANDARD_HANDLE  (VrmlData_TextureTransform, VrmlData_Node)
44 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_TextureTransform, VrmlData_Node)
45 IMPLEMENT_STANDARD_HANDLE  (VrmlData_ImageTexture, VrmlData_Texture)
46 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_ImageTexture, VrmlData_Texture)
47 IMPLEMENT_STANDARD_HANDLE  (VrmlData_Appearance, VrmlData_Node)
48 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Appearance, VrmlData_Node)
49 IMPLEMENT_STANDARD_HANDLE  (VrmlData_UnknownNode, VrmlData_Node)
50 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_UnknownNode, VrmlData_Node)
51
52 static VrmlData_Scene MyDefaultScene;
53
54 //=======================================================================
55 //function : IsEqual
56 //purpose  : Global method
57 //=======================================================================
58
59 Standard_Boolean IsEqual (const Handle(VrmlData_Node)& theOne,
60                           const Handle(VrmlData_Node)& theTwo)
61 {
62   Standard_Boolean aResult (Standard_False);
63   if (theOne->Name() != 0L && theTwo->Name() != 0L)
64     aResult = (strcmp (theOne->Name(), theTwo->Name()) == 0);
65   return aResult;
66 }
67
68 //=======================================================================
69 //function : HashCode
70 //purpose  : Global method
71 //=======================================================================
72
73 Standard_Integer HashCode(const Handle(VrmlData_Node)& theNode,
74                           const Standard_Integer       theUpper)
75 {
76   return (theNode->Name() == 0L ? 0
77           : HashCode((Standard_CString)theNode->Name(), theUpper));
78 }
79
80 //=======================================================================
81 //function : VrmlData_Node
82 //purpose  : 
83 //=======================================================================
84
85 VrmlData_Node::VrmlData_Node ()
86   : myScene (&MyDefaultScene),
87     myName  (0L) {}
88
89 //=======================================================================
90 //function : VrmlData_Node
91 //purpose  : Constructor
92 //=======================================================================
93
94 VrmlData_Node::VrmlData_Node (const VrmlData_Scene& theScene,
95                               const char            * theName)
96   : myScene   (&theScene)
97 {
98   if (theName == 0L)
99     theName = "";
100   setName (theName);
101 }
102
103 //=======================================================================
104 //function : Clone
105 //purpose  : Create a copy of this node.
106 //=======================================================================
107
108 Handle(VrmlData_Node) VrmlData_Node::Clone
109                                 (const Handle(VrmlData_Node)& theOther) const
110 {
111   if (theOther.IsNull() == Standard_False) {
112     if (theOther->IsKind (DynamicType()) == Standard_False)
113       return NULL;
114     if (&theOther->Scene() == myScene)
115       theOther->myName = myName;
116     else
117       theOther->setName (myName);
118   }
119   return theOther;
120 }
121
122 //=======================================================================
123 //function : setName
124 //purpose  : 
125 //=======================================================================
126
127 void VrmlData_Node::setName (const char * theName, const char * theSuffix)
128 {
129   size_t len[2] = {
130     strlen(theName) + 1,
131     0
132   };
133   if (theSuffix)
134     len[1] = strlen (theSuffix);
135   char * aName = (char *)Scene().Allocator()->Allocate(len[0]+len[1]);
136   myName = aName;
137   memcpy (aName, theName, len[0]);
138   if (len[1])
139     memcpy (&aName[len[0] - 1], theSuffix, len[1]+1);
140 }
141
142 //=======================================================================
143 //function : IsDefault
144 //purpose  : 
145 //=======================================================================
146
147 Standard_Boolean VrmlData_Node::IsDefault () const
148 {
149   return Standard_False;
150 }
151
152
153 //=======================================================================
154 //function : Write
155 //purpose  : 
156 //=======================================================================
157
158 VrmlData_ErrorStatus VrmlData_Node::Write (const char *) const
159 {
160   return VrmlData_NotImplemented;
161 }
162
163 //=======================================================================
164 //function : WriteClosing
165 //purpose  : 
166 //=======================================================================
167
168 VrmlData_ErrorStatus VrmlData_Node::WriteClosing () const
169 {
170   VrmlData_ErrorStatus aResult = Scene().Status();
171   if (aResult == VrmlData_StatusOK || aResult == VrmlData_NotImplemented)
172     aResult = Scene().WriteLine ("}", 0L, -GlobalIndent());
173   return aResult;
174 }
175
176 //=======================================================================
177 //function : readBrace
178 //purpose  : 
179 //=======================================================================
180
181 VrmlData_ErrorStatus VrmlData_Node::readBrace (VrmlData_InBuffer& theBuffer)
182 {
183   VrmlData_ErrorStatus aStatus;
184   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
185     if (theBuffer.LinePtr[0] == '}')
186       theBuffer.LinePtr++;
187     else
188       aStatus = VrmlData_VrmlFormatError;
189   return aStatus;
190 }
191
192 //=======================================================================
193 //function : ReadBoolean
194 //purpose  : 
195 //=======================================================================
196
197 VrmlData_ErrorStatus VrmlData_Node::ReadBoolean (VrmlData_InBuffer& theBuffer,
198                                                  Standard_Boolean&  theResult)
199 {
200   VrmlData_ErrorStatus aStatus;
201   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
202     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "TRUE"))
203       theResult = Standard_True;
204     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "FALSE"))
205       theResult = Standard_False;
206     else
207       aStatus = VrmlData_BooleanInputError;
208   }
209   return aStatus;
210 }
211
212 //=======================================================================
213 //function : ReadInteger
214 //purpose  : 
215 //=======================================================================
216
217 VrmlData_ErrorStatus VrmlData_Node::ReadInteger (VrmlData_InBuffer& theBuffer,
218                                                  long&              theResult)
219 {
220   VrmlData_ErrorStatus aStatus;
221   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
222     char * endptr;
223     long aResult;
224     aResult = strtol (theBuffer.LinePtr, &endptr, 10);
225     if (endptr == theBuffer.LinePtr)
226       aStatus = VrmlData_NumericInputError;
227     else {
228       theResult = aResult;
229       theBuffer.LinePtr = endptr;
230     }
231   }
232   return aStatus;
233 }
234
235 //=======================================================================
236 //function : ReadString
237 //purpose  : 
238 //=======================================================================
239
240 VrmlData_ErrorStatus VrmlData_Node::ReadString
241                                 (VrmlData_InBuffer& theBuffer,
242                                  TCollection_AsciiString&  theResult)
243 {
244   VrmlData_ErrorStatus aStatus;
245   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
246     if (theBuffer.LinePtr[0] != '\"')
247       aStatus = VrmlData_StringInputError;
248     else {
249       char * ptr = &theBuffer.LinePtr[1];
250       while (*ptr != '\0' && *ptr != '\"')
251         ptr++;
252       if (*ptr == '\0')
253         aStatus = VrmlData_StringInputError;
254       else {
255         *ptr = '\0';
256         theResult = (Standard_CString) &theBuffer.LinePtr[1];
257         theBuffer.LinePtr = ptr+1;
258       }
259     }
260   }
261   return aStatus;
262 }
263
264 //=======================================================================
265 //function : ReadMultiString
266 //purpose  : 
267 //=======================================================================
268
269 VrmlData_ErrorStatus VrmlData_Node::ReadMultiString
270                         (VrmlData_InBuffer&                         theBuffer,
271                          NCollection_List<TCollection_AsciiString>& theResult)
272 {
273   VrmlData_ErrorStatus aStatus;
274   Standard_Boolean isBracketed (Standard_False);
275   // Read the list of URL
276   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
277     if (theBuffer.LinePtr[0] == '[') {
278       theBuffer.LinePtr++;
279       isBracketed = Standard_True;
280     }
281     while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
282       if (isBracketed && theBuffer.LinePtr[0] == ']') { // closing bracket
283         theBuffer.LinePtr++;
284         break;
285       }
286       TCollection_AsciiString aString;
287       if (!OK(aStatus, ReadString(theBuffer, aString)))
288         break;
289       theResult.Append(aString);
290       if (isBracketed == Standard_False ||
291           !OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
292         break;
293       if (theBuffer.LinePtr[0] == ',') {
294         theBuffer.LinePtr++;
295         continue;
296       } else if (theBuffer.LinePtr[0] == ']') // closing bracket
297         theBuffer.LinePtr++;
298       else
299         aStatus = VrmlData_VrmlFormatError;
300       break;
301     }
302   }
303   return aStatus;
304 }
305
306 //=======================================================================
307 //function : ReadNode
308 //purpose  : 
309 //=======================================================================
310
311 VrmlData_ErrorStatus VrmlData_Node::ReadNode
312                                 (VrmlData_InBuffer&             theBuffer,
313                                  Handle(VrmlData_Node)&         theNode,
314                                  const Handle(Standard_Type)&   theType)
315 {
316   Handle(VrmlData_Node) aNode;
317   VrmlData_ErrorStatus  aStatus;
318   // First line of a new node should identify this node type
319   if (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
320     if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "USE")) {
321       TCollection_AsciiString aName;
322       aStatus = VrmlData_Scene::ReadWord (theBuffer, aName);
323       if (aStatus == VrmlData_StatusOK) {
324         aNode = myScene->FindNode (aName.ToCString(), theType);
325         if (aNode.IsNull())
326           aStatus = VrmlData_NodeNameUnknown;
327 //         else
328 //           aNode = aNode->Clone(0L);
329       }
330     }
331
332     // We create a relevant node using the line with the type ID
333     else if (OK(aStatus,
334                 const_cast<VrmlData_Scene *>(myScene)->createNode (theBuffer,
335                                                                    aNode,
336                                                                    theType)))
337       if (aNode.IsNull() == Standard_False)
338         // The node data are read here, including the final closing brace
339         aStatus = aNode->Read(theBuffer);
340
341     if (aStatus == VrmlData_StatusOK)
342       theNode = aNode;
343   }
344   return aStatus;
345 }
346
347 //=======================================================================
348 //function : VrmlData_ShapeNode::Clone
349 //purpose  : 
350 //=======================================================================
351
352 Handle(VrmlData_Node) VrmlData_ShapeNode::Clone
353                                 (const Handle(VrmlData_Node)& theOther) const
354 {
355   Handle(VrmlData_ShapeNode) aResult =
356     Handle(VrmlData_ShapeNode)::DownCast (VrmlData_Node::Clone(theOther));
357   if (aResult.IsNull())
358     aResult= new VrmlData_ShapeNode(theOther.IsNull()?Scene():theOther->Scene(),
359                                     Name());
360   if (&aResult->Scene() == &Scene()) {
361     aResult->SetAppearance (myAppearance);
362     aResult->SetGeometry   (myGeometry);
363   } else {
364     // Create a dummy node to pass the different Scene instance to methods Clone
365     const Handle(VrmlData_UnknownNode) aDummyNode =
366       new VrmlData_UnknownNode (aResult->Scene());
367     if (myAppearance.IsNull() == Standard_False)
368       aResult->SetAppearance(Handle(VrmlData_Appearance)::DownCast
369                              (myAppearance->Clone (aDummyNode)));
370     if (myGeometry.IsNull() == Standard_False)
371       aResult->SetGeometry (Handle(VrmlData_Geometry)::DownCast
372                             (myGeometry->Clone (aDummyNode)));
373   }
374   return aResult;
375 }
376
377 //=======================================================================
378 //function : VrmlData_ShapeNode::Read
379 //purpose  : 
380 //=======================================================================
381
382 VrmlData_ErrorStatus VrmlData_ShapeNode::Read (VrmlData_InBuffer& theBuffer)
383 {
384   VrmlData_ErrorStatus aStatus;
385   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
386     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "appearance"))
387       aStatus = ReadNode (theBuffer, myAppearance,
388                           STANDARD_TYPE(VrmlData_Appearance));
389     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "geometry"))
390       aStatus = ReadNode (theBuffer, myGeometry);
391 // here we do not check for the Geometry type because unknown node types can
392 // occur (IndexedLineSet, etc.)
393 //                          STANDARD_TYPE(VrmlData_Geometry));
394     else
395       break;
396
397     if (!OK(aStatus))
398       break;
399   }
400
401   // Read the terminating (closing) brace
402   if (OK(aStatus))
403     aStatus = readBrace (theBuffer);
404   return aStatus;
405 }
406
407 //=======================================================================
408 //function : VrmlData_ShapeNode::Write
409 //purpose  : 
410 //=======================================================================
411
412 VrmlData_ErrorStatus VrmlData_ShapeNode::Write (const char * thePrefix) const
413 {
414   VrmlData_ErrorStatus aStatus (VrmlData_StatusOK);
415   const VrmlData_Scene& aScene = Scene();
416   static char header[] = "Shape {";
417   if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent())))
418   {
419     if (myAppearance.IsNull() == Standard_False)
420       aStatus = aScene.WriteNode ("appearance", myAppearance);
421     if (myGeometry.IsNull() == Standard_False && OK(aStatus))
422       aStatus = aScene.WriteNode ("geometry", myGeometry);
423
424     aStatus = WriteClosing();
425   }
426   return aStatus;
427 }  
428
429 //=======================================================================
430 //function : VrmlData_ShapeNode::IsDefault
431 //purpose  : 
432 //=======================================================================
433
434 Standard_Boolean VrmlData_ShapeNode::IsDefault () const
435 {
436   Standard_Boolean aResult (Standard_True);
437   if (myGeometry.IsNull() == Standard_False)
438     aResult = myGeometry->IsDefault();
439   return aResult;
440 }
441
442 //=======================================================================
443 //function : VrmlData_UnknownNode::Read
444 //purpose  : 
445 //=======================================================================
446
447 VrmlData_ErrorStatus VrmlData_UnknownNode::Read (VrmlData_InBuffer& theBuffer)
448 {
449   VrmlData_ErrorStatus aStatus;
450   Standard_Integer aLevelCounter (0);
451   // This loop searches for any opening brace.
452   // Such brace increments the level counter. A closing brace decrements
453   // the counter. The loop terminates when the counter becomes negative.
454   while (aLevelCounter >= 0 &&
455          OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
456   {
457     int aChar;
458     while ((aChar = theBuffer.LinePtr[0]) != '\0') {
459       theBuffer.LinePtr++;
460       if        (aChar == '{') {
461         aLevelCounter++;
462         break;
463       } else if (aChar == '}') {
464         aLevelCounter--;
465         break;
466       }
467     }
468   }
469   return aStatus;
470 }
471
472 //=======================================================================
473 //function : VrmlData_UnknownNode::IsDefault
474 //purpose  : 
475 //=======================================================================
476
477 Standard_Boolean VrmlData_UnknownNode::IsDefault () const
478 {
479   return Standard_True;
480 }
481
482 //=======================================================================
483 //function : VrmlData_Appearance::Clone
484 //purpose  : 
485 //=======================================================================
486
487 Handle(VrmlData_Node) VrmlData_Appearance::Clone
488                                 (const Handle(VrmlData_Node)& theOther) const
489 {
490   Handle(VrmlData_Appearance) aResult =
491     Handle(VrmlData_Appearance)::DownCast (VrmlData_Node::Clone(theOther));
492   if (aResult.IsNull())
493     aResult = new VrmlData_Appearance
494       (theOther.IsNull() ? Scene() : theOther->Scene(), Name());
495   if (&aResult->Scene() == &Scene()) {
496     aResult->SetMaterial          (myMaterial);
497     aResult->SetTexture           (myTexture);
498     aResult->SetTextureTransform  (myTTransform);
499   } else {
500     // Create a dummy node to pass the different Scene instance to methods Clone
501     const Handle(VrmlData_UnknownNode) aDummyNode =
502       new VrmlData_UnknownNode (aResult->Scene());
503     if (myMaterial.IsNull()   == Standard_False)
504       aResult->SetMaterial (Handle(VrmlData_Material)::DownCast
505                             (myMaterial->Clone (aDummyNode)));
506     if (myTexture.IsNull()    == Standard_False)
507       aResult->SetTexture(Handle(VrmlData_Texture)::DownCast
508                           (myTexture->Clone (aDummyNode)));
509     if (myTTransform.IsNull() == Standard_False)
510       aResult->SetTextureTransform(Handle(VrmlData_TextureTransform)::DownCast
511                                    (myTTransform->Clone (aDummyNode)));
512   }
513   return aResult;
514 }
515
516 //=======================================================================
517 //function : VrmlData_Appearance::Read
518 //purpose  : 
519 //=======================================================================
520
521 VrmlData_ErrorStatus VrmlData_Appearance::Read (VrmlData_InBuffer& theBuffer)
522 {
523   VrmlData_ErrorStatus aStatus;
524   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
525     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "material"))
526       aStatus = ReadNode (theBuffer, myMaterial,
527                           STANDARD_TYPE(VrmlData_Material));
528     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "textureTransform"))
529       aStatus = ReadNode (theBuffer, myTTransform
530                           /*,STANDARD_TYPE(VrmlData_TextureTransform)*/);
531     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texture"))
532       aStatus = ReadNode (theBuffer, myTexture,
533                           STANDARD_TYPE(VrmlData_Texture));
534     else
535       break;
536
537     if (!OK(aStatus))
538       break;
539   }
540
541   // Read the terminating (closing) brace
542   if (OK(aStatus))
543     aStatus = readBrace (theBuffer);
544   return aStatus;
545 }
546
547 //=======================================================================
548 //function : VrmlData_Appearance::Write
549 //purpose  : 
550 //=======================================================================
551
552 VrmlData_ErrorStatus VrmlData_Appearance::Write (const char * thePrefix) const
553 {
554   static char header[] = "Appearance {";
555   VrmlData_ErrorStatus aStatus;
556   const VrmlData_Scene& aScene = Scene();
557   if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent())))
558   {
559     if (myMaterial.IsNull() == Standard_False)
560       aStatus = aScene.WriteNode ("material", myMaterial);
561     if (myTexture.IsNull() == Standard_False && OK(aStatus))
562       aStatus = aScene.WriteNode ("texture", myTexture);
563     if (myTTransform.IsNull() == Standard_False && OK(aStatus))
564       aStatus = aScene.WriteNode ("textureTransform", myTTransform);
565
566     aStatus = WriteClosing();
567   }
568   return aStatus;
569 }
570
571 //=======================================================================
572 //function : IsDefault
573 //purpose  : 
574 //=======================================================================
575
576 Standard_Boolean VrmlData_Appearance::IsDefault () const
577 {
578   Standard_Boolean aResult (Standard_True);
579   if (myMaterial.IsNull() == Standard_False)
580     aResult = myMaterial->IsDefault();
581   if (aResult == Standard_False)
582     if (myTexture.IsNull() == Standard_False)
583       aResult = myTexture->IsDefault();
584   if (aResult == Standard_False)
585     if (myTTransform.IsNull() == Standard_False)
586       aResult = myTTransform->IsDefault();
587   return aResult;
588 }
589
590 //=======================================================================
591 //function : VrmlData_ImageTexture
592 //purpose  : Constructor
593 //=======================================================================
594
595 VrmlData_ImageTexture::VrmlData_ImageTexture (const VrmlData_Scene&  theScene,
596                                               const char             * theName,
597                                               const char             * theURL,
598                                               const Standard_Boolean theRepS,
599                                               const Standard_Boolean theRepT)
600   : VrmlData_Texture (theScene, theName, theRepS, theRepT),
601     myURL            (theScene.Allocator())
602 {
603   myURL.Append (theURL ? (Standard_CString)theURL : "");
604 }
605
606 //=======================================================================
607 //function : VrmlData_ImageTexture::Clone
608 //purpose  : 
609 //=======================================================================
610
611 Handle(VrmlData_Node) VrmlData_ImageTexture::Clone
612                                 (const Handle(VrmlData_Node)& theOther) const
613 {
614   Handle(VrmlData_ImageTexture) aResult =
615     Handle(VrmlData_ImageTexture)::DownCast (VrmlData_Node::Clone(theOther));
616   if (aResult.IsNull())
617     aResult =
618       new VrmlData_ImageTexture(theOther.IsNull() ? Scene() : theOther->Scene(),
619                                 Name());
620   aResult->myURL = myURL;
621   return aResult;
622 }
623
624 //=======================================================================
625 //function : VrmlData_ImageTexture::Read
626 //purpose  : 
627 //=======================================================================
628
629 VrmlData_ErrorStatus VrmlData_ImageTexture::Read (VrmlData_InBuffer& theBuffer)
630 {
631   VrmlData_ErrorStatus aStatus;
632   Standard_Boolean aRepeatS (Standard_True), aRepeatT (Standard_True);
633   myURL.Clear();
634   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
635     if      (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url"))
636       aStatus = ReadMultiString (theBuffer, myURL);
637     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "repeatS"))
638       aStatus = ReadBoolean (theBuffer, aRepeatS);
639     else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "repeatT"))
640       aStatus = ReadBoolean (theBuffer, aRepeatT);
641     else
642       break;
643
644     if (!OK(aStatus))
645       break;
646   }
647   if (OK(aStatus) && OK(aStatus, readBrace (theBuffer))) {
648     SetRepeatS (aRepeatS);
649     SetRepeatT (aRepeatT);
650   }
651   return aStatus;
652 }
653