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