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