0031668: Visualization - WebGL sample doesn't work on Emscripten 1.39
[occt.git] / src / StepData / StepData_StepWriter.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 // List of changes:
15 //skl 29.01.2003 - deleted one space symbol at the begining
16 //                 of strings from Header Section
17
18 #include <Interface_Check.hxx>
19 #include <Interface_CheckIterator.hxx>
20 #include <Interface_EntityIterator.hxx>
21 #include <Interface_FloatWriter.hxx>
22 #include <Interface_InterfaceMismatch.hxx>
23 #include <Interface_Macros.hxx>
24 #include <Interface_ReportEntity.hxx>
25 #include <Standard_NoSuchObject.hxx>
26 #include <Standard_Transient.hxx>
27 #include <StepData_ESDescr.hxx>
28 #include <StepData_Field.hxx>
29 #include <StepData_FieldList.hxx>
30 #include <StepData_PDescr.hxx>
31 #include <StepData_Protocol.hxx>
32 #include <StepData_ReadWriteModule.hxx>
33 #include <StepData_SelectArrReal.hxx>
34 #include <StepData_SelectMember.hxx>
35 #include <StepData_StepModel.hxx>
36 #include <StepData_StepWriter.hxx>
37 #include <StepData_UndefinedEntity.hxx>
38 #include <StepData_WriterLib.hxx>
39 #include <TCollection_AsciiString.hxx>
40 #include <TCollection_HAsciiString.hxx>
41
42 #include <stdio.h>
43 #define StepLong 72
44 // StepLong : longueur maxi d une ligne de fichier Step
45
46
47 //  Constantes litterales (interessantes, pour les performances ET LA MEMOIRE)
48
49 static TCollection_AsciiString  textscope    (" &SCOPE");
50 static TCollection_AsciiString  textendscope ("        ENDSCOPE");
51 static TCollection_AsciiString  textcomm     ("  /*  ");
52 static TCollection_AsciiString  textendcomm  ("  */");
53 static TCollection_AsciiString  textlist     ("(");
54 static TCollection_AsciiString  textendlist  (")");
55 static TCollection_AsciiString  textendent   (");");
56 static TCollection_AsciiString  textparam    (",");
57 static TCollection_AsciiString  textundef    ("$");
58 static TCollection_AsciiString  textderived  ("*");
59 static TCollection_AsciiString  texttrue     (".T.");
60 static TCollection_AsciiString  textfalse    (".F.");
61 static TCollection_AsciiString  textunknown  (".U.");
62
63
64
65 //=======================================================================
66 //function : StepData_StepWriter
67 //purpose  : 
68 //=======================================================================
69
70 StepData_StepWriter::StepData_StepWriter(const Handle(StepData_StepModel)& amodel)
71     : thecurr (StepLong) , thefloatw (12)
72 {
73   themodel = amodel;  thelabmode = thetypmode = 0;
74   thefile  = new TColStd_HSequenceOfHAsciiString();
75   thesect  = Standard_False;  thefirst = Standard_True;
76   themult  = Standard_False;  thecomm  = Standard_False;
77   thelevel = theindval = 0;   theindent = Standard_False;
78 //  Format flottant : reporte dans le FloatWriter
79 }
80
81 //  ....                Controle d Envoi des Flottants                ....
82
83 //=======================================================================
84 //function : FloatWriter
85 //purpose  : 
86 //=======================================================================
87
88 Interface_FloatWriter& StepData_StepWriter::FloatWriter ()
89 {  return thefloatw;  }    // s y reporter
90
91
92 //=======================================================================
93 //function : LabelMode
94 //purpose  : 
95 //=======================================================================
96
97 Standard_Integer&  StepData_StepWriter::LabelMode ()
98 {  return thelabmode;  }
99
100
101 //=======================================================================
102 //function : TypeMode
103 //purpose  : 
104 //=======================================================================
105
106 Standard_Integer&  StepData_StepWriter::TypeMode  ()
107 {  return thetypmode;  }
108
109 //  ....                Description des Scopes (AVANT Envoi)               ....
110
111
112 //=======================================================================
113 //function : SetScope
114 //purpose  : 
115 //=======================================================================
116
117 void StepData_StepWriter::SetScope (const Standard_Integer numscope,
118                                     const Standard_Integer numin)
119 {
120   Standard_Integer nb = themodel->NbEntities();
121   if (numscope <= 0 || numscope > nb || numin <= 0 || numin > nb)
122     throw Interface_InterfaceMismatch("StepWriter : SetScope, out of range");
123   if (thescopenext.IsNull()) {
124     thescopebeg  = new TColStd_HArray1OfInteger (1,nb); thescopebeg->Init(0);
125     thescopeend  = new TColStd_HArray1OfInteger (1,nb); thescopeend->Init(0);
126     thescopenext = new TColStd_HArray1OfInteger (1,nb); thescopenext->Init(0);
127   }
128   else if (thescopenext->Value(numin) != 0) {
129 #ifdef OCCT_DEBUG
130     std::cout << "StepWriter : SetScope (scope : " << numscope << " entity : "
131       << numin << "), Entity already in a Scope"<<std::endl;
132 #endif
133     throw Interface_InterfaceMismatch("StepWriter : SetScope, already set");
134   }
135   thescopenext->SetValue(numin,-1);  // nouvelle fin de scope
136   if (thescopebeg->Value(numscope) == 0) thescopebeg->SetValue(numscope,numin);
137   Standard_Integer lastin = thescopeend->Value(numscope);
138   if (lastin > 0) thescopenext->SetValue(lastin,numin);
139   thescopeend->SetValue(numscope,numin);
140 }
141
142
143 //=======================================================================
144 //function : IsInScope
145 //purpose  : 
146 //=======================================================================
147
148 Standard_Boolean StepData_StepWriter::IsInScope(const Standard_Integer num) const
149 {
150   if (thescopenext.IsNull()) return Standard_False;
151   return (thescopenext->Value(num) != 0);
152 }
153
154 //  ###########################################################################
155 //  ##    ##    ##    ##        ENVOI DES  SECTIONS        ##    ##    ##    ##
156
157 //  ....                      Envoi du Modele Complet                      ....
158
159
160 //=======================================================================
161 //function : SendModel
162 //purpose  : 
163 //=======================================================================
164
165 void StepData_StepWriter::SendModel(const Handle(StepData_Protocol)& protocol,
166                                     const Standard_Boolean headeronly)
167 {
168   StepData_WriterLib lib(protocol);
169
170   if (!headeronly)
171     thefile->Append (new TCollection_HAsciiString("ISO-10303-21;"));
172   SendHeader();
173
174 //  ....                Header : suite d entites sans Ident                ....
175
176   Interface_EntityIterator header = themodel->Header();
177   thenum = 0;
178   for (header.Start(); header.More(); header.Next()) {
179     Handle(Standard_Transient) anent = header.Value();
180
181 //   Write Entity via Lib  (similaire a SendEntity)
182     Handle(StepData_ReadWriteModule) module;  Standard_Integer CN;
183     if (lib.Select(anent,module,CN)) {
184       if (module->IsComplex(CN))   StartComplex();
185       else {
186         TCollection_AsciiString styp;
187         if (thetypmode > 0) styp = module->ShortType(CN);
188         if (styp.Length() == 0) styp = module->StepType(CN);
189         StartEntity (styp);
190       }
191       module->WriteStep(CN,*this,anent);
192       if (module->IsComplex(CN))   EndComplex();
193     } else {
194 //    Pas trouve ci-dessus ... tenter UndefinedEntity
195       DeclareAndCast(StepData_UndefinedEntity,und,anent);
196       if (und.IsNull()) continue;
197       if (und->IsComplex())   StartComplex();
198       und->WriteParams(*this); 
199       if (und->IsComplex())   EndComplex();
200    }
201     EndEntity ();
202   }
203   EndSec();
204   if (headeronly) return;
205
206 //  Data : Comme Header mais avec des Idents ... sinon le code est le meme
207   SendData();
208
209 // ....                    Erreurs Globales (silya)                    ....
210
211   Handle(Interface_Check) achglob = themodel->GlobalCheck();
212   Standard_Integer nbfails = achglob->NbFails();
213   if (nbfails > 0) {
214     Comment(Standard_True);
215     SendComment("GLOBAL FAIL MESSAGES,  recorded at Read time :");
216     for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
217       SendComment (achglob->Fail(ifail));
218     }
219     Comment(Standard_False);
220     NewLine(Standard_False);
221   }
222
223 //  ....                Sortie des Entites une par une                ....
224
225   Standard_Integer nb = themodel->NbEntities();
226   for (Standard_Integer i = 1 ; i <= nb; i ++) {
227 //    Liste principale : on n envoie pas les Entites dans un Scope
228 //    Elles le seront par l intermediaire du Scope qui les contient
229     if (!thescopebeg.IsNull()) {  if (thescopenext->Value(i) != 0) continue;  }
230     SendEntity (i,lib);
231   }
232
233   EndSec();
234   EndFile();
235 }
236
237
238 //  ....                DECOUPAGE DU FICHIER EN SECTIONS                ....
239
240
241 //=======================================================================
242 //function : SendHeader
243 //purpose  : 
244 //=======================================================================
245
246 void StepData_StepWriter::SendHeader ()
247 {
248   NewLine(Standard_False);
249   thefile->Append (new TCollection_HAsciiString("HEADER;"));
250   thesect = Standard_True;
251 }
252
253
254 //=======================================================================
255 //function : SendData
256 //purpose  : 
257 //=======================================================================
258
259 void StepData_StepWriter::SendData ()
260 {
261   if (thesect) throw Interface_InterfaceMismatch("StepWriter : Data section");
262   NewLine(Standard_False);
263   thefile->Append (new TCollection_HAsciiString("DATA;"));
264   thesect = Standard_True;
265 }
266
267
268 //=======================================================================
269 //function : EndSec
270 //purpose  : 
271 //=======================================================================
272
273 void StepData_StepWriter::EndSec ()
274 {
275   thefile->Append (new TCollection_HAsciiString("ENDSEC;"));
276   thesect = Standard_False;
277 }
278
279
280 //=======================================================================
281 //function : EndFile
282 //purpose  : 
283 //=======================================================================
284
285 void StepData_StepWriter::EndFile ()
286 {
287   if (thesect) throw Interface_InterfaceMismatch("StepWriter : EndFile");
288   NewLine(Standard_False);
289   thefile->Append (new TCollection_HAsciiString("END-ISO-10303-21;"));
290   thesect = Standard_False;
291 }
292
293 //  ....                        ENVOI D UNE ENTITE                        ....
294
295
296 //=======================================================================
297 //function : SendEntity
298
299 //purpose  : 
300 //=======================================================================
301
302 void StepData_StepWriter::SendEntity(const Standard_Integer num,
303                                      const StepData_WriterLib& lib)
304 {
305   char lident[20];
306   Handle(Standard_Transient) anent = themodel->Entity(num);
307   Standard_Integer idnum = num , idtrue = 0;
308
309     //   themodel->Number(anent) et-ou IdentLabel(anent)
310   if (thelabmode > 0) idtrue = themodel->IdentLabel(anent);
311   if (thelabmode == 1) idnum = idtrue;
312   if (idnum == 0) idnum = num;
313   if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d = ",idnum); //skl 29.01.2003
314   else sprintf(lident,"%d:#%d = ",idnum,idtrue); //skl 29.01.2003
315
316 //  SendIdent repris , lident vient d etre calcule
317   thecurr.Clear();
318   thecurr.Add (lident);
319   themult = Standard_False;
320
321 //  ....        Traitement du Scope Eventuel
322   if (!thescopebeg.IsNull()) {
323     Standard_Integer numin = thescopebeg->Value(num);
324     if (numin != 0) {
325       SendScope();
326       for (Standard_Integer nument = numin; numin > 0; nument = numin) {
327         SendEntity(nument,lib);
328         numin = thescopenext->Value(nument);
329       }
330       SendEndscope();
331     }
332   }
333
334 //  ....        Envoi de l Entite proprement dite
335
336 //   Write Entity via Lib
337   thenum = num;
338   Handle(StepData_ReadWriteModule) module;  Standard_Integer CN;
339   if (themodel->IsRedefinedContent(num)) {
340 //    Entite Erreur : Ecrire le Contenu + les Erreurs en Commentaires
341     Handle(Interface_ReportEntity) rep = themodel->ReportEntity(num);
342     DeclareAndCast(StepData_UndefinedEntity,und,rep->Content());
343     if (und.IsNull()) {
344       thechecks.CCheck(num)->AddFail("Erroneous Entity, Content lost");
345       StartEntity(TCollection_AsciiString("!?LOST_DATA"));
346     } else {
347       thechecks.CCheck(num)->AddWarning("Erroneous Entity, equivalent content");
348       if (und->IsComplex())   AddString(" (",2);
349       und->WriteParams(*this);
350       if (und->IsComplex()) { AddString(") ",2); }  //thelevel --; }
351     }
352     EndEntity ();        // AVANT les Commentaires
353     NewLine(Standard_False);
354     Comment(Standard_True);
355     if (und.IsNull()) SendComment("   ERRONEOUS ENTITY, DATA LOST");
356     SendComment("On Entity above, Fail Messages recorded at Read time :");
357     Handle(Interface_Check) ach = rep->Check();
358     Standard_Integer nbfails = ach->NbFails();
359     for (Standard_Integer ifail = 1; ifail <= nbfails; ifail ++) {
360       SendComment (ach->Fail(ifail));
361     }
362     Comment(Standard_False);
363     NewLine(Standard_False);
364
365 //    Cas normal
366   }
367   else if (lib.Select(anent,module,CN)) {
368     if (module->IsComplex(CN))   StartComplex();
369     else {
370       TCollection_AsciiString styp;
371       if (thetypmode > 0) styp = module->ShortType(CN);
372       if (styp.Length() == 0) styp = module->StepType(CN);
373       StartEntity (styp);
374     }
375     module->WriteStep(CN,*this,anent);
376     if (module->IsComplex(CN))   EndComplex();
377     EndEntity ();
378   }
379   else {
380     //    Pas trouve ci-dessus ... tenter UndefinedEntity
381     DeclareAndCast(StepData_UndefinedEntity,und,anent);
382     if (und.IsNull()) return;
383     if (und->IsComplex())   StartComplex();
384     und->WriteParams(*this);
385     if (und->IsComplex())   EndComplex();
386     EndEntity ();
387   }
388 }
389
390 //  ###########################################################################
391 //  ##    ##    ##        CONSTITUTION DU TEXTE A ENVOYER        ##    ##    ##
392
393 //  Passer a la ligne. Ligne vide pas comptee sauf si evenempty == Standard_True
394
395
396 //=======================================================================
397 //function : NewLine
398 //purpose  : 
399 //=======================================================================
400
401 void StepData_StepWriter::NewLine (const Standard_Boolean evenempty)
402 {
403   if (evenempty || thecurr.Length() > 0) {
404     thefile->Append(thecurr.Moved());
405   }
406   Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
407   thecurr.SetInitial(indst);  thecurr.Clear();
408 }
409
410
411 //  Regrouper ligne en cours avec precedente; reste en cours sauf si newline
412 //  == Standard_True, auquel cas on commence une nouvelle ligne
413 //  Ne fait rien si : total correspondant > StepLong ou debut ou fin d`entite
414
415
416 //=======================================================================
417 //function : JoinLast
418 //purpose  : 
419 //=======================================================================
420
421 void StepData_StepWriter::JoinLast (const Standard_Boolean)
422 {
423   thecurr.SetKeep();
424 }
425
426
427 //=======================================================================
428 //function : Indent
429 //purpose  : 
430 //=======================================================================
431
432 void StepData_StepWriter::Indent (const Standard_Boolean onent)
433 {  theindent = onent;  }
434
435
436 //=======================================================================
437 //function : SendIdent
438 //purpose  : 
439 //=======================================================================
440
441 void StepData_StepWriter::SendIdent(const Standard_Integer ident)
442 {
443   char lident[12];
444   sprintf(lident,"#%d =",ident);
445   thecurr.Clear();
446   thecurr.Add (lident);
447   themult = Standard_False;
448 }
449
450
451 //=======================================================================
452 //function : SendScope
453 //purpose  : 
454 //=======================================================================
455
456 void StepData_StepWriter::SendScope ()
457 {  AddString(textscope);  }
458
459
460 //=======================================================================
461 //function : SendEndscope
462 //purpose  : 
463 //=======================================================================
464
465 void StepData_StepWriter::SendEndscope ()
466 {
467   NewLine(Standard_False);
468   thefile->Append(new TCollection_HAsciiString(textendscope));
469 }
470
471
472 //=======================================================================
473 //function : Comment
474 //purpose  : 
475 //=======================================================================
476
477 void StepData_StepWriter::Comment (const Standard_Boolean mode)
478 {
479   if (mode && !thecomm) AddString(textcomm,20);
480   if (!mode && thecomm) AddString(textendcomm);
481   thecomm = mode;
482 }
483
484
485 //=======================================================================
486 //function : SendComment
487 //purpose  : 
488 //=======================================================================
489
490 void StepData_StepWriter::SendComment(const Handle(TCollection_HAsciiString)& text)
491 {
492   if (!thecomm) throw Interface_InterfaceMismatch("StepWriter : Comment");
493   AddString(text->ToCString(),text->Length());
494 }
495
496
497 //=======================================================================
498 //function : SendComment
499 //purpose  : 
500 //=======================================================================
501
502 void StepData_StepWriter::SendComment (const Standard_CString text)
503 {
504   if (!thecomm) throw Interface_InterfaceMismatch("StepWriter : Comment");
505   AddString(text,(Standard_Integer) strlen(text));
506 }
507
508
509 //=======================================================================
510 //function : StartEntity
511 //purpose  : 
512 //=======================================================================
513
514 void StepData_StepWriter::StartEntity(const TCollection_AsciiString& atype)
515 {
516   if (atype.Length() == 0) return;
517   if (themult) {
518     if (thelevel != 1) throw Interface_InterfaceMismatch("StepWriter : StartEntity");   // decompte de parentheses mauvais ...
519     AddString(textendlist);
520     AddString(" ",1); //skl 29.01.2003
521   }
522   themult = Standard_True;
523   //AddString(" ",1);  //skl 29.01.2003
524   AddString(atype);
525   thelevel  = 0;
526   theindval = thecurr.Length();
527   thecurr.SetInitial(0);
528   thefirst  = Standard_True;
529   OpenSub();
530 }
531
532
533 //=======================================================================
534 //function : StartComplex
535 //purpose  : 
536 //=======================================================================
537
538 void  StepData_StepWriter::StartComplex ()
539 {
540   AddString("( ",2); //skl 29.01.2003
541 }    // thelevel unchanged
542
543
544 //=======================================================================
545 //function : EndComplex
546 //purpose  : 
547 //=======================================================================
548
549 void  StepData_StepWriter::EndComplex ()
550 {  AddString(") ",2);  }    // thelevel unchanged
551
552
553 //  ....                SendField et ce qui va avec
554
555
556 //=======================================================================
557 //function : SendField
558 //purpose  : 
559 //=======================================================================
560
561 void StepData_StepWriter::SendField(const StepData_Field& fild,
562                                     const Handle(StepData_PDescr)& descr)
563 {
564   Standard_Boolean done = Standard_True;
565   Standard_Integer kind = fild.Kind (Standard_False);  // valeur interne
566
567   if (kind == 16) {
568     DeclareAndCast(StepData_SelectMember,sm,fild.Transient());
569     SendSelect (sm,descr);
570     return;
571   }
572   switch (kind) {
573 //   ici les cas simples; ensuite on caste et on voit
574     case 0 : SendUndef(); break;
575     case 1 : Send        (fild.Integer  ()); break;
576     case 2 : SendBoolean (fild.Boolean  ()); break;
577     case 3 : SendLogical (fild.Logical  ()); break;
578     case 4 : SendEnum    (fild.EnumText ()); break; // enum : descr ?
579     case 5 : Send        (fild.Real     ()); break;
580     case 6 : Send        (fild.String   ()); break;
581     case 7 : Send        (fild.Entity   ()); break;
582     case 8 : done = Standard_False; break;
583     case 9 : SendDerived (); break;
584     default: done = Standard_False; break;
585   }
586   if (done) return;
587
588 //  Que reste-t-il : les tableaux ...
589   Standard_Integer arity = fild.Arity();
590   if (arity == 0) {  SendUndef();  return;  }    // PAS NORMAL
591   if (arity == 1) {
592     OpenSub();
593     Standard_Integer i,low = fild.Lower(), up = low + fild.Length() - 1;
594     for (i = low; i <= up; i ++) {
595       kind = fild.ItemKind(i);
596       done = Standard_True;
597       switch (kind) {
598         case 0 : SendUndef();  break;
599         case 1 : Send        (fild.Integer  (i)); break;
600         case 2 : SendBoolean (fild.Boolean  (i)); break;
601         case 3 : SendLogical (fild.Logical  (i)); break;
602         case 4 : SendEnum    (fild.EnumText (i)); break;
603         case 5 : Send        (fild.Real     (i)); break;
604         case 6 : Send        (fild.String   (i)); break;
605         case 7 : Send        (fild.Entity   (i)); break;
606         default: SendUndef();  done = Standard_False; break;  // ANORMAL
607       }
608     }
609     CloseSub();
610     return;
611   }
612   if (arity == 2) {
613     OpenSub();
614     Standard_Integer   j,low1 = fild.Lower(1), up1 = low1 + fild.Length(1) - 1;
615     for (j = low1; j <= up1; j ++) {
616       Standard_Integer i=0,low2 = fild.Lower(2), up2 = low2 + fild.Length(2) - 1;
617       OpenSub();
618       for (i = low2; i <= up2; i ++) {
619         kind = fild.ItemKind(i,j);
620         done = Standard_True;
621         switch (kind) {
622         case 0 : SendUndef();  break;
623         case 1 : Send        (fild.Integer  (i,j)); break;
624         case 2 : SendBoolean (fild.Boolean  (i,j)); break;
625         case 3 : SendLogical (fild.Logical  (i,j)); break;
626         case 4 : SendEnum    (fild.EnumText (i,j)); break;
627         case 5 : Send        (fild.Real     (i,j)); break;
628         case 6 : Send        (fild.String   (i,j)); break;
629         case 7 : Send        (fild.Entity   (i,j)); break;
630         default: SendUndef();  done = Standard_False; break;  // ANORMAL
631         }
632       }
633       CloseSub();
634     }
635     CloseSub();
636     return;
637   }
638 }
639
640
641 //=======================================================================
642 //function : SendSelect
643 //purpose  : 
644 //=======================================================================
645
646 void StepData_StepWriter::SendSelect(const Handle(StepData_SelectMember)& sm,
647                                      const Handle(StepData_PDescr)& /*descr*/)
648 {
649   //    Cas du SelectMember. Traiter le Select puis la valeur
650   //    NB : traitement actuel non recursif (pas de SELNAME(SELNAME(..)) )
651   Standard_Boolean selname = Standard_False;
652   if (sm.IsNull()) return;  // ??
653   if (sm->HasName()) {
654     selname = Standard_True;
655     //    SendString (sm->Name());
656     //    AddString(textlist);     // SANS AJOUT DE PARAMETRE !!
657     OpenTypedSub (sm->Name());
658   }
659   Standard_Integer kind = sm->Kind();
660   switch (kind) {
661     case 0 : SendUndef(); break;
662     case 1 : Send        (sm->Integer  ()); break;
663     case 2 : SendBoolean (sm->Boolean  ()); break;
664     case 3 : SendLogical (sm->Logical  ()); break;
665     case 4 : SendEnum    (sm->EnumText ()); break; // enum : descr ?
666     case 5 : Send        (sm->Real     ()); break;
667     case 6 : Send        (sm->String   ()); break;
668     case 8 : SendArrReal (Handle(StepData_SelectArrReal)::DownCast(sm)->ArrReal()); break;
669     default: break;    // ??
670   }
671   if (selname) CloseSub();
672 }
673
674
675 //=======================================================================
676 //function : SendList
677 //purpose  : 
678 //=======================================================================
679
680 void  StepData_StepWriter::SendList(const StepData_FieldList& list,
681                                     const Handle(StepData_ESDescr)& descr)
682 {
683 // start entity  ?
684   Standard_Integer i, nb = list.NbFields();
685   for (i = 1; i <= nb; i ++) {
686     Handle(StepData_PDescr) pde;
687     if (!descr.IsNull()) pde  = descr->Field(i);
688     const StepData_Field fild = list.Field(i);
689     SendField (fild,pde);
690   }
691 // end entity  ?
692 }
693
694 //  ....                Send* de base
695
696
697 //=======================================================================
698 //function : OpenSub
699 //purpose  : 
700 //=======================================================================
701
702 void StepData_StepWriter::OpenSub ()
703 {
704   AddParam();
705   AddString(textlist);
706   thefirst = Standard_True;
707   thelevel ++;
708 }
709
710
711 //=======================================================================
712 //function : OpenTypedSub
713 //purpose  : 
714 //=======================================================================
715
716 void StepData_StepWriter::OpenTypedSub (const Standard_CString subtype)
717 {
718   AddParam();
719   if (subtype[0] != '\0') AddString (subtype,(Standard_Integer) strlen(subtype));
720   AddString(textlist);
721   thefirst = Standard_True;
722   thelevel ++;
723 }
724
725
726 //=======================================================================
727 //function : CloseSub
728 //purpose  : 
729 //=======================================================================
730
731 void StepData_StepWriter::CloseSub ()
732 {
733   AddString(textendlist);
734   thefirst = Standard_False;  // le parametre suivant une sous-liste n est donc pas 1er
735   thelevel --;
736 }
737
738
739 //=======================================================================
740 //function : AddParam
741 //purpose  : 
742 //=======================================================================
743
744 void StepData_StepWriter::AddParam ()
745 {
746   if (!thefirst) AddString(textparam);
747   thefirst = Standard_False;
748 }
749
750
751 //=======================================================================
752 //function : Send
753 //purpose  : 
754 //=======================================================================
755
756 void StepData_StepWriter::Send (const Standard_Integer val)
757 {
758   char lval[12];
759   AddParam();
760   sprintf(lval,"%d",val);
761   AddString(lval,(Standard_Integer) strlen(lval));
762 }
763
764
765 //=======================================================================
766 //function : Send
767 //purpose  : 
768 //=======================================================================
769
770 void StepData_StepWriter::Send (const Standard_Real val)
771 {
772 //    Valeur flottante, expurgee de "0000" qui trainent et de "E+00"
773   char lval[24];
774   Standard_Integer lng = thefloatw.Write(val,lval);
775   AddParam();
776   AddString(lval,lng);    // gere le format specifique : si besoin est
777 }
778
779 //  Send(String) : attention, on envoie un Texte ... donc entre '  '
780
781 //=======================================================================
782 //function : Send
783 //purpose  : 
784 //=======================================================================
785
786 void StepData_StepWriter::Send (const TCollection_AsciiString& val)
787 {
788   AddParam();
789   TCollection_AsciiString aval(val);  // on duplique pour trafiquer si besoin
790   Standard_Integer nb = aval.Length();  Standard_Integer nn = nb;
791   aval.AssignCat('\'');    // comme cela, Insert(i+1) est OK
792
793 //    Conversion des Caracteres speciaux
794   for (Standard_Integer i = nb; i > 0; i --) {
795     char uncar = aval.Value(i);
796     if (uncar == '\'') {  aval.Insert(i+1,'\'');  nn ++;    continue;  }
797     if (uncar == '\\') {  aval.Insert(i+1,'\\');  nn ++;    continue;  }
798     if (uncar == '\n') {  aval.SetValue(i,'\\');  aval.Insert(i+1,'\\');
799                           aval.Insert(i+1,'N' );  nn += 2;  continue;  }
800     if (uncar == '\t') {  aval.SetValue(i,'\\');  aval.Insert(i+1,'\\');
801                           aval.Insert(i+1,'T' );  nn += 2;  continue;  }
802   }
803   //:i2 abv 31 Aug 98: ProSTEP TR9: avoid wrapping text or do it at spaces
804   aval.Insert(1,'\'');
805   nn += 2;
806
807 //:i2  AddString ("\'",1); nn ++;
808
809 //    Attention au depassement des 72 caracteres
810   if (thecurr.CanGet(nn)) AddString(aval,0);
811   //:i2
812   else {
813     thefile->Append(thecurr.Moved());
814     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
815     if ( indst+nn <= StepLong ) thecurr.SetInitial(indst);
816     else thecurr.SetInitial(0);
817     if ( thecurr.CanGet(nn) ) AddString(aval,0);
818     else {
819       while ( nn >0 ) {
820         if (nn <= StepLong) {
821           thecurr.Add (aval);  // Ca yet, on a tout epuise
822           thecurr.FreezeInitial();
823           break;
824         }
825         Standard_Integer stop = StepLong; // position of last separator
826         for ( ; stop > 0 && aval.Value(stop) != ' '; stop-- );
827         if ( ! stop ) {
828           stop = StepLong;
829           for ( ; stop > 0 && aval.Value(stop) != '\\'; stop-- );
830           if ( ! stop ) {
831             stop = StepLong;
832             for ( ; stop > 0 && aval.Value(stop) != '_'; stop-- );
833             if ( ! stop ) stop = StepLong;
834           }
835         }
836         TCollection_AsciiString bval = aval.Split(stop);
837         thefile->Append(new TCollection_HAsciiString(aval));
838         aval = bval;
839         nn -= stop;
840       }
841     }
842   }
843 /* //:i2
844   else {
845     //    Il faut tronconner ...  lignes limitees a 72 caracteres (StepLong)
846     Standard_Integer ncurr = thecurr.Length();
847     Standard_Integer nbuff = StepLong - ncurr;
848     thecurr.Add (aval.ToCString(),nbuff);
849     thefile->Append(thecurr.Moved());
850     aval.Remove(1,nbuff);
851     nn -= nbuff;
852     while (nn > 0) {
853       if (nn <= StepLong) {
854         thecurr.Add (aval);  // Ca yet, on a tout epuise
855         thecurr.FreezeInitial();
856         break;
857       }
858       TCollection_AsciiString bval = aval.Split(StepLong);
859       thefile->Append(new TCollection_HAsciiString(bval));
860       nn -= StepLong;
861     }
862   }
863 //:i2 */  
864 //  thecurr.Add('\'');   deja mis dans aval au debut
865 }
866
867
868 //=======================================================================
869 //function : Send
870 //purpose  : 
871 //=======================================================================
872
873 void StepData_StepWriter::Send (const Handle(Standard_Transient)& val)
874 {
875   char lident[20];
876 //  Undefined ?
877   if (val.IsNull()) {
878 //   throw Interface_InterfaceMismatch("StepWriter : Sending Null Reference");
879     thechecks.CCheck(thenum)->AddFail("Null Reference");
880     SendUndef();
881     Comment(Standard_True);
882     SendComment(" NUL REF ");
883     Comment(Standard_False);
884     return;
885   }
886   Standard_Integer num = themodel->Number(val);
887 //  String ? (si non repertoriee dans le Modele)
888   if (num == 0) {
889     if (val->IsKind(STANDARD_TYPE(TCollection_HAsciiString))) {
890       DeclareAndCast(TCollection_HAsciiString,strval,val);
891       Send (TCollection_AsciiString(strval->ToCString()));
892       return;
893     }
894 //  SelectMember ? (toujours, si non repertoriee)
895 //  mais attention, pas de description attachee
896     else if (val->IsKind(STANDARD_TYPE(StepData_SelectMember))) {
897       DeclareAndCast(StepData_SelectMember,sm,val);
898       Handle(StepData_PDescr) descr;  // null
899       SendSelect (sm,descr);
900     }
901 //  Sinon, PAS NORMAL !
902     else {
903       thechecks.CCheck(thenum)->AddFail("UnknownReference");
904       SendUndef();
905       Comment(Standard_True);
906       SendComment(" UNKNOWN REF ");
907       Comment(Standard_False);
908 //      throw Interface_InterfaceMismatch("StepWriter : Sending Unknown Reference");
909     }
910   }
911 //  Cas normal : une bonne Entite, on envoie son Ident.
912   else {
913     Standard_Integer idnum = num, idtrue = 0;
914     if (thelabmode > 0) idtrue = themodel->IdentLabel(val);
915     if (thelabmode == 1) idnum = idtrue;
916     if (idnum == 0) idnum = num;
917     if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d",idnum);
918     else sprintf(lident,"%d:#%d",idnum,idtrue);
919     AddParam();
920     AddString(lident,(Standard_Integer) strlen(lident));
921   }
922 }
923
924
925 //=======================================================================
926 //function : SendBoolean
927 //purpose  : 
928 //=======================================================================
929
930 void StepData_StepWriter::SendBoolean (const Standard_Boolean val)
931 {
932   if (val) SendString(texttrue);
933   else     SendString(textfalse);
934 }
935
936
937 //=======================================================================
938 //function : SendLogical
939 //purpose  : 
940 //=======================================================================
941
942 void StepData_StepWriter::SendLogical (const StepData_Logical val)
943 {
944   if      (val == StepData_LTrue)   SendString(texttrue);
945   else if (val == StepData_LFalse)  SendString(textfalse);
946   else                              SendString(textunknown);
947 }
948
949
950 //  SendString : attention, on donne l'intitule exact
951
952 //=======================================================================
953 //function : SendString
954 //purpose  : 
955 //=======================================================================
956
957 void StepData_StepWriter::SendString (const TCollection_AsciiString& val)
958 {
959   AddParam();
960   AddString(val);
961 }
962
963 //  SendString : attention, on donne l'intitule exact
964
965 //=======================================================================
966 //function : SendString
967 //purpose  : 
968 //=======================================================================
969
970 void StepData_StepWriter::SendString (const Standard_CString val)
971 {
972   AddParam();
973   AddString(val,(Standard_Integer) strlen(val));
974 }
975
976 //  SendEnum : attention, on envoie un intitule d'Enum ... donc entre .  .
977
978 //=======================================================================
979 //function : SendEnum
980 //purpose  : 
981 //=======================================================================
982
983 void StepData_StepWriter::SendEnum (const TCollection_AsciiString& val)
984 {
985   if (val.Length() == 1 && val.Value(1) == '$')  {  SendUndef();  return;  }
986   AddParam();
987   TCollection_AsciiString aValue = val;
988   if (aValue.Value(1) != '.') aValue.Prepend('.');
989   if (aValue.Value(aValue.Length()) != '.') aValue+='.';
990   AddString(aValue,2);
991   
992 }
993
994 //  SendEnum : attention, on envoie un intitule d'Enum ... donc entre .  .
995
996 //=======================================================================
997 //function : SendEnum
998 //purpose  : 
999 //=======================================================================
1000
1001 void StepData_StepWriter::SendEnum (const Standard_CString val)
1002 {
1003   
1004   if (val[0] == '$' && val[1] == '\0')  {  SendUndef();  return;  }
1005   TCollection_AsciiString aValue(val);
1006   SendEnum(aValue);
1007 }
1008
1009
1010 //=======================================================================
1011 //function : SendArrReal
1012 //purpose  : 
1013 //=======================================================================
1014
1015 void StepData_StepWriter::SendArrReal (const Handle(TColStd_HArray1OfReal) &anArr)
1016 {
1017   AddString(textlist);
1018   if(anArr->Length()>0) {
1019     // add real
1020     Send(anArr->Value(1));
1021     for( Standard_Integer i=2; i<=anArr->Length(); i++) {
1022 //      AddString(textparam);
1023       //add real
1024       Send(anArr->Value(i));
1025     }
1026   }
1027   AddString(textendlist);
1028 }
1029
1030
1031 //=======================================================================
1032 //function : SendUndef
1033 //purpose  : 
1034 //=======================================================================
1035
1036 void StepData_StepWriter::SendUndef ()
1037 {
1038   AddParam();
1039   AddString(textundef);
1040 }
1041
1042
1043 //=======================================================================
1044 //function : SendDerived
1045 //purpose  : 
1046 //=======================================================================
1047
1048 void StepData_StepWriter::SendDerived ()
1049 {
1050   AddParam();
1051   AddString(textderived);
1052 }
1053
1054
1055 // EndEntity : s'il faut mettre ; a la ligne, l'aligner sur debut d'entite ...
1056
1057 //=======================================================================
1058 //function : EndEntity
1059 //purpose  : 
1060 //=======================================================================
1061
1062 void StepData_StepWriter::EndEntity ()
1063 {
1064   if (thelevel != 1) throw Interface_InterfaceMismatch("StepWriter : EndEntity");   // decompte de parentheses mauvais ...
1065   AddString(textendent);
1066   thelevel  = 0;        // on garde theindval : sera traite au prochain NewLine
1067   Standard_Boolean indent = theindent; theindent = Standard_False;
1068   NewLine(Standard_False); theindent = indent;
1069   themult = Standard_False;
1070 // pour forcer indentation si necessaire
1071 }
1072
1073
1074 //  gestion de la ligne courante (cf aussi NewLine/JoinLine)
1075
1076 //=======================================================================
1077 //function : AddString
1078 //purpose  : 
1079 //=======================================================================
1080
1081 void StepData_StepWriter::AddString(const TCollection_AsciiString& astr,
1082                                     const Standard_Integer more)
1083 {
1084   while (!thecurr.CanGet(astr.Length() + more)) {
1085     thefile->Append(thecurr.Moved());
1086     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1087     thecurr.SetInitial(indst);
1088   }
1089   thecurr.Add(astr);
1090 }
1091
1092
1093 //=======================================================================
1094 //function : AddString
1095 //purpose  : 
1096 //=======================================================================
1097
1098 void StepData_StepWriter::AddString(const Standard_CString astr,
1099                                     const Standard_Integer lnstr,
1100                                     const Standard_Integer more)
1101 {
1102   while (!thecurr.CanGet(lnstr + more)) {
1103     thefile->Append(thecurr.Moved());
1104     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1105     thecurr.SetInitial(indst);
1106   }
1107   thecurr.Add(astr,lnstr);
1108 }
1109
1110
1111 //   ENVOI FINAL
1112
1113
1114 //=======================================================================
1115 //function : CheckList
1116 //purpose  : 
1117 //=======================================================================
1118
1119 Interface_CheckIterator  StepData_StepWriter::CheckList () const
1120 {
1121   return thechecks;
1122 }
1123
1124
1125 //=======================================================================
1126 //function : NbLines
1127 //purpose  : 
1128 //=======================================================================
1129
1130 Standard_Integer  StepData_StepWriter::NbLines () const
1131 {  return thefile->Length();  }
1132
1133
1134 //=======================================================================
1135 //function : Line
1136 //purpose  : 
1137 //=======================================================================
1138
1139 Handle(TCollection_HAsciiString) StepData_StepWriter::Line
1140        (const Standard_Integer num) const
1141 {  return thefile->Value(num);  }
1142
1143
1144 //=======================================================================
1145 //function : Printw
1146 //purpose  : 
1147 //=======================================================================
1148
1149 Standard_Boolean StepData_StepWriter::Print (Standard_OStream& S)
1150 {
1151   Standard_Boolean isGood = (S.good());
1152   Standard_Integer nb = thefile->Length();
1153   for (Standard_Integer i = 1; i <= nb && isGood; i ++) 
1154     S << thefile->Value(i)->ToCString() << "\n";
1155   
1156   S<< std::flush;
1157   isGood = (S && S.good());
1158   
1159   return  isGood;
1160   
1161 }