0024186: Eliminate remaining compiler warnings in MSVC++ 2010 64 bit with warning...
[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)
417 {
418   thecurr.SetKeep();
419 }
420
421
422 //=======================================================================
423 //function : Indent
424 //purpose  : 
425 //=======================================================================
426
427 void StepData_StepWriter::Indent (const Standard_Boolean onent)
428 {  theindent = onent;  }
429
430
431 //=======================================================================
432 //function : SendIdent
433 //purpose  : 
434 //=======================================================================
435
436 void StepData_StepWriter::SendIdent(const Standard_Integer ident)
437 {
438   char lident[12];
439   sprintf(lident,"#%d =",ident);
440   thecurr.Clear();
441   thecurr.Add (lident);
442   themult = Standard_False;
443 }
444
445
446 //=======================================================================
447 //function : SendScope
448 //purpose  : 
449 //=======================================================================
450
451 void StepData_StepWriter::SendScope ()
452 {  AddString(textscope);  }
453
454
455 //=======================================================================
456 //function : SendEndscope
457 //purpose  : 
458 //=======================================================================
459
460 void StepData_StepWriter::SendEndscope ()
461 {
462   NewLine(Standard_False);
463   thefile->Append(new TCollection_HAsciiString(textendscope));
464 }
465
466
467 //=======================================================================
468 //function : Comment
469 //purpose  : 
470 //=======================================================================
471
472 void StepData_StepWriter::Comment (const Standard_Boolean mode)
473 {
474   if (mode && !thecomm) AddString(textcomm,20);
475   if (!mode && thecomm) AddString(textendcomm);
476   thecomm = mode;
477 }
478
479
480 //=======================================================================
481 //function : SendComment
482 //purpose  : 
483 //=======================================================================
484
485 void StepData_StepWriter::SendComment(const Handle(TCollection_HAsciiString)& text)
486 {
487   if (!thecomm) Interface_InterfaceMismatch::Raise("StepWriter : Comment");
488   AddString(text->ToCString(),text->Length());
489 }
490
491
492 //=======================================================================
493 //function : SendComment
494 //purpose  : 
495 //=======================================================================
496
497 void StepData_StepWriter::SendComment (const Standard_CString text)
498 {
499   if (!thecomm) Interface_InterfaceMismatch::Raise("StepWriter : Comment");
500   AddString(text,(Standard_Integer) strlen(text));
501 }
502
503
504 //=======================================================================
505 //function : StartEntity
506 //purpose  : 
507 //=======================================================================
508
509 void StepData_StepWriter::StartEntity(const TCollection_AsciiString& atype)
510 {
511   if (atype.Length() == 0) return;
512   if (themult) {
513     if (thelevel != 1) Interface_InterfaceMismatch::Raise
514       ("StepWriter : StartEntity");   // decompte de parentheses mauvais ...
515     AddString(textendlist);
516     AddString(" ",1); //skl 29.01.2003
517   }
518   themult = Standard_True;
519   //AddString(" ",1);  //skl 29.01.2003
520   AddString(atype);
521   thelevel  = 0;
522   theindval = thecurr.Length();
523   thecurr.SetInitial(0);
524   thefirst  = Standard_True;
525   OpenSub();
526 }
527
528
529 //=======================================================================
530 //function : StartComplex
531 //purpose  : 
532 //=======================================================================
533
534 void  StepData_StepWriter::StartComplex ()
535 {
536   AddString("( ",2); //skl 29.01.2003
537 }    // thelevel unchanged
538
539
540 //=======================================================================
541 //function : EndComplex
542 //purpose  : 
543 //=======================================================================
544
545 void  StepData_StepWriter::EndComplex ()
546 {  AddString(") ",2);  }    // thelevel unchanged
547
548
549 //  ....                SendField et ce qui va avec
550
551
552 //=======================================================================
553 //function : SendField
554 //purpose  : 
555 //=======================================================================
556
557 void StepData_StepWriter::SendField(const StepData_Field& fild,
558                                     const Handle(StepData_PDescr)& descr)
559 {
560   Standard_Boolean done = Standard_True;
561   Standard_Integer kind = fild.Kind (Standard_False);  // valeur interne
562
563   if (kind == 16) {
564     DeclareAndCast(StepData_SelectMember,sm,fild.Transient());
565     SendSelect (sm,descr);
566     return;
567   }
568   switch (kind) {
569 //   ici les cas simples; ensuite on caste et on voit
570     case 0 : SendUndef(); break;
571     case 1 : Send        (fild.Integer  ()); break;
572     case 2 : SendBoolean (fild.Boolean  ()); break;
573     case 3 : SendLogical (fild.Logical  ()); break;
574     case 4 : SendEnum    (fild.EnumText ()); break; // enum : descr ?
575     case 5 : Send        (fild.Real     ()); break;
576     case 6 : Send        (fild.String   ()); break;
577     case 7 : Send        (fild.Entity   ()); break;
578     case 8 : done = Standard_False; break;
579     case 9 : SendDerived (); break;
580     default: done = Standard_False; break;
581   }
582   if (done) return;
583
584 //  Que reste-t-il : les tableaux ...
585   Standard_Integer arity = fild.Arity();
586   if (arity == 0) {  SendUndef();  return;  }    // PAS NORMAL
587   if (arity == 1) {
588     OpenSub();
589     Standard_Integer i,low = fild.Lower(), up = low + fild.Length() - 1;
590     for (i = low; i <= up; i ++) {
591       kind = fild.ItemKind(i);
592       done = Standard_True;
593       switch (kind) {
594         case 0 : SendUndef();  break;
595         case 1 : Send        (fild.Integer  (i)); break;
596         case 2 : SendBoolean (fild.Boolean  (i)); break;
597         case 3 : SendLogical (fild.Logical  (i)); break;
598         case 4 : SendEnum    (fild.EnumText (i)); break;
599         case 5 : Send        (fild.Real     (i)); break;
600         case 6 : Send        (fild.String   (i)); break;
601         case 7 : Send        (fild.Entity   (i)); break;
602         default: SendUndef();  done = Standard_False; break;  // ANORMAL
603       }
604     }
605     CloseSub();
606     return;
607   }
608   if (arity == 2) {
609     OpenSub();
610     Standard_Integer   j,low1 = fild.Lower(1), up1 = low1 + fild.Length(1) - 1;
611     for (j = low1; j <= up1; j ++) {
612       Standard_Integer i=0,low2 = fild.Lower(2), up2 = low2 + fild.Length(2) - 1;
613       OpenSub();
614       for (i = low2; i <= up2; i ++) {
615         kind = fild.ItemKind(i,j);
616         done = Standard_True;
617         switch (kind) {
618         case 0 : SendUndef();  break;
619         case 1 : Send        (fild.Integer  (i,j)); break;
620         case 2 : SendBoolean (fild.Boolean  (i,j)); break;
621         case 3 : SendLogical (fild.Logical  (i,j)); break;
622         case 4 : SendEnum    (fild.EnumText (i,j)); break;
623         case 5 : Send        (fild.Real     (i,j)); break;
624         case 6 : Send        (fild.String   (i,j)); break;
625         case 7 : Send        (fild.Entity   (i,j)); break;
626         default: SendUndef();  done = Standard_False; break;  // ANORMAL
627         }
628       }
629       CloseSub();
630     }
631     CloseSub();
632     return;
633   }
634 }
635
636
637 //=======================================================================
638 //function : SendSelect
639 //purpose  : 
640 //=======================================================================
641
642 void StepData_StepWriter::SendSelect(const Handle(StepData_SelectMember)& sm,
643                                      const Handle(StepData_PDescr)& /*descr*/)
644 {
645   //    Cas du SelectMember. Traiter le Select puis la valeur
646   //    NB : traitement actuel non recursif (pas de SELNAME(SELNAME(..)) )
647   Standard_Boolean selname = Standard_False;
648   if (sm.IsNull()) return;  // ??
649   if (sm->HasName()) {
650     selname = Standard_True;
651     //    SendString (sm->Name());
652     //    AddString(textlist);     // SANS AJOUT DE PARAMETRE !!
653     OpenTypedSub (sm->Name());
654   }
655   Standard_Integer kind = sm->Kind();
656   switch (kind) {
657     case 0 : SendUndef(); break;
658     case 1 : Send        (sm->Integer  ()); break;
659     case 2 : SendBoolean (sm->Boolean  ()); break;
660     case 3 : SendLogical (sm->Logical  ()); break;
661     case 4 : SendEnum    (sm->EnumText ()); break; // enum : descr ?
662     case 5 : Send        (sm->Real     ()); break;
663     case 6 : Send        (sm->String   ()); break;
664     case 8 : SendArrReal (Handle(StepData_SelectArrReal)::DownCast(sm)->ArrReal()); break;
665     default: break;    // ??
666   }
667   if (selname) CloseSub();
668 }
669
670
671 //=======================================================================
672 //function : SendList
673 //purpose  : 
674 //=======================================================================
675
676 void  StepData_StepWriter::SendList(const StepData_FieldList& list,
677                                     const Handle(StepData_ESDescr)& descr)
678 {
679 // start entity  ?
680   Standard_Integer i, nb = list.NbFields();
681   for (i = 1; i <= nb; i ++) {
682     Handle(StepData_PDescr) pde;
683     if (!descr.IsNull()) pde  = descr->Field(i);
684     const StepData_Field fild = list.Field(i);
685     SendField (fild,pde);
686   }
687 // end entity  ?
688 }
689
690 //  ....                Send* de base
691
692
693 //=======================================================================
694 //function : OpenSub
695 //purpose  : 
696 //=======================================================================
697
698 void StepData_StepWriter::OpenSub ()
699 {
700   AddParam();
701   AddString(textlist);
702   thefirst = Standard_True;
703   thelevel ++;
704 }
705
706
707 //=======================================================================
708 //function : OpenTypedSub
709 //purpose  : 
710 //=======================================================================
711
712 void StepData_StepWriter::OpenTypedSub (const Standard_CString subtype)
713 {
714   AddParam();
715   if (subtype[0] != '\0') AddString (subtype,(Standard_Integer) strlen(subtype));
716   AddString(textlist);
717   thefirst = Standard_True;
718   thelevel ++;
719 }
720
721
722 //=======================================================================
723 //function : CloseSub
724 //purpose  : 
725 //=======================================================================
726
727 void StepData_StepWriter::CloseSub ()
728 {
729   AddString(textendlist);
730   thefirst = Standard_False;  // le parametre suivant une sous-liste n est donc pas 1er
731   thelevel --;
732 }
733
734
735 //=======================================================================
736 //function : AddParam
737 //purpose  : 
738 //=======================================================================
739
740 void StepData_StepWriter::AddParam ()
741 {
742   if (!thefirst) AddString(textparam);
743   thefirst = Standard_False;
744 }
745
746
747 //=======================================================================
748 //function : Send
749 //purpose  : 
750 //=======================================================================
751
752 void StepData_StepWriter::Send (const Standard_Integer val)
753 {
754   char lval[12];
755   AddParam();
756   sprintf(lval,"%d",val);
757   AddString(lval,(Standard_Integer) strlen(lval));
758 }
759
760
761 //=======================================================================
762 //function : Send
763 //purpose  : 
764 //=======================================================================
765
766 void StepData_StepWriter::Send (const Standard_Real val)
767 {
768 //    Valeur flottante, expurgee de "0000" qui trainent et de "E+00"
769   char lval[24];
770   Standard_Integer lng = thefloatw.Write(val,lval);
771   AddParam();
772   AddString(lval,lng);    // gere le format specifique : si besoin est
773 }
774
775 //  Send(String) : attention, on envoie un Texte ... donc entre '  '
776
777 //=======================================================================
778 //function : Send
779 //purpose  : 
780 //=======================================================================
781
782 void StepData_StepWriter::Send (const TCollection_AsciiString& val)
783 {
784   AddParam();
785   TCollection_AsciiString aval(val);  // on duplique pour trafiquer si besoin
786   Standard_Integer nb = aval.Length();  Standard_Integer nn = nb;
787   aval.AssignCat('\'');    // comme cela, Insert(i+1) est OK
788
789 //    Conversion des Caracteres speciaux
790   for (Standard_Integer i = nb; i > 0; i --) {
791     char uncar = aval.Value(i);
792     if (uncar == '\'') {  aval.Insert(i+1,'\'');  nn ++;    continue;  }
793     if (uncar == '\\') {  aval.Insert(i+1,'\\');  nn ++;    continue;  }
794     if (uncar == '\n') {  aval.SetValue(i,'\\');  aval.Insert(i+1,'\\');
795                           aval.Insert(i+1,'N' );  nn += 2;  continue;  }
796     if (uncar == '\t') {  aval.SetValue(i,'\\');  aval.Insert(i+1,'\\');
797                           aval.Insert(i+1,'T' );  nn += 2;  continue;  }
798   }
799   //:i2 abv 31 Aug 98: ProSTEP TR9: avoid wrapping text or do it at spaces
800   aval.Insert(1,'\'');
801   nn += 2;
802
803 //:i2  AddString ("\'",1); nn ++;
804
805 //    Attention au depassement des 72 caracteres
806   if (thecurr.CanGet(nn)) AddString(aval,0);
807   //:i2
808   else {
809     thefile->Append(thecurr.Moved());
810     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
811     if ( indst+nn <= StepLong ) thecurr.SetInitial(indst);
812     else thecurr.SetInitial(0);
813     if ( thecurr.CanGet(nn) ) AddString(aval,0);
814     else {
815       while ( nn >0 ) {
816         if (nn <= StepLong) {
817           thecurr.Add (aval);  // Ca yet, on a tout epuise
818           thecurr.FreezeInitial();
819           break;
820         }
821         Standard_Integer stop = StepLong; // position of last separator
822         for ( ; stop > 0 && aval.Value(stop) != ' '; stop-- );
823         if ( ! stop ) {
824           stop = StepLong;
825           for ( ; stop > 0 && aval.Value(stop) != '\\'; stop-- );
826           if ( ! stop ) {
827             stop = StepLong;
828             for ( ; stop > 0 && aval.Value(stop) != '_'; stop-- );
829             if ( ! stop ) stop = StepLong;
830           }
831         }
832         TCollection_AsciiString bval = aval.Split(stop);
833         thefile->Append(new TCollection_HAsciiString(aval));
834         aval = bval;
835         nn -= stop;
836       }
837     }
838   }
839 /* //:i2
840   else {
841     //    Il faut tronconner ...  lignes limitees a 72 caracteres (StepLong)
842     Standard_Integer ncurr = thecurr.Length();
843     Standard_Integer nbuff = StepLong - ncurr;
844     thecurr.Add (aval.ToCString(),nbuff);
845     thefile->Append(thecurr.Moved());
846     aval.Remove(1,nbuff);
847     nn -= nbuff;
848     while (nn > 0) {
849       if (nn <= StepLong) {
850         thecurr.Add (aval);  // Ca yet, on a tout epuise
851         thecurr.FreezeInitial();
852         break;
853       }
854       TCollection_AsciiString bval = aval.Split(StepLong);
855       thefile->Append(new TCollection_HAsciiString(bval));
856       nn -= StepLong;
857     }
858   }
859 //:i2 */  
860 //  thecurr.Add('\'');   deja mis dans aval au debut
861 }
862
863
864 //=======================================================================
865 //function : Send
866 //purpose  : 
867 //=======================================================================
868
869 void StepData_StepWriter::Send (const Handle(Standard_Transient)& val)
870 {
871   char lident[20];
872 //  Undefined ?
873   if (val.IsNull()) {
874 //   Interface_InterfaceMismatch::Raise("StepWriter : Sending Null Reference");
875     thechecks.CCheck(thenum)->AddFail("Null Reference");
876     SendUndef();
877     Comment(Standard_True);
878     SendComment(" NUL REF ");
879     Comment(Standard_False);
880     return;
881   }
882   Standard_Integer num = themodel->Number(val);
883 //  String ? (si non repertoriee dans le Modele)
884   if (num == 0) {
885     if (val->IsKind(STANDARD_TYPE(TCollection_HAsciiString))) {
886       DeclareAndCast(TCollection_HAsciiString,strval,val);
887       Send (TCollection_AsciiString(strval->ToCString()));
888       return;
889     }
890 //  SelectMember ? (toujours, si non repertoriee)
891 //  mais attention, pas de description attachee
892     else if (val->IsKind(STANDARD_TYPE(StepData_SelectMember))) {
893       DeclareAndCast(StepData_SelectMember,sm,val);
894       Handle(StepData_PDescr) descr;  // null
895       SendSelect (sm,descr);
896     }
897 //  Sinon, PAS NORMAL !
898     else {
899       thechecks.CCheck(thenum)->AddFail("UnknownReference");
900       SendUndef();
901       Comment(Standard_True);
902       SendComment(" UNKNOWN REF ");
903       Comment(Standard_False);
904 //      Interface_InterfaceMismatch::Raise("StepWriter : Sending Unknown Reference");
905     }
906   }
907 //  Cas normal : une bonne Entite, on envoie son Ident.
908   else {
909     Standard_Integer idnum = num, idtrue = 0;
910     if (thelabmode > 0) idtrue = themodel->IdentLabel(val);
911     if (thelabmode == 1) idnum = idtrue;
912     if (idnum == 0) idnum = num;
913     if (thelabmode < 2 || idnum == idtrue) sprintf(lident,"#%d",idnum);
914     else sprintf(lident,"%d:#%d",idnum,idtrue);
915     AddParam();
916     AddString(lident,(Standard_Integer) strlen(lident));
917   }
918 }
919
920
921 //=======================================================================
922 //function : SendBoolean
923 //purpose  : 
924 //=======================================================================
925
926 void StepData_StepWriter::SendBoolean (const Standard_Boolean val)
927 {
928   if (val) SendString(texttrue);
929   else     SendString(textfalse);
930 }
931
932
933 //=======================================================================
934 //function : SendLogical
935 //purpose  : 
936 //=======================================================================
937
938 void StepData_StepWriter::SendLogical (const StepData_Logical val)
939 {
940   if      (val == StepData_LTrue)   SendString(texttrue);
941   else if (val == StepData_LFalse)  SendString(textfalse);
942   else                              SendString(textunknown);
943 }
944
945
946 //  SendString : attention, on donne l'intitule exact
947
948 //=======================================================================
949 //function : SendString
950 //purpose  : 
951 //=======================================================================
952
953 void StepData_StepWriter::SendString (const TCollection_AsciiString& val)
954 {
955   AddParam();
956   AddString(val);
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 Standard_CString val)
967 {
968   AddParam();
969   AddString(val,(Standard_Integer) strlen(val));
970 }
971
972 //  SendEnum : attention, on envoie un intitule d'Enum ... donc entre .  .
973
974 //=======================================================================
975 //function : SendEnum
976 //purpose  : 
977 //=======================================================================
978
979 void StepData_StepWriter::SendEnum (const TCollection_AsciiString& val)
980 {
981   if (val.Length() == 1 && val.Value(1) == '$')  {  SendUndef();  return;  }
982   AddParam();
983   TCollection_AsciiString aValue = val;
984   if (aValue.Value(1) != '.') aValue.Prepend('.');
985   if (aValue.Value(aValue.Length()) != '.') aValue+='.';
986   AddString(aValue,2);
987   
988 }
989
990 //  SendEnum : attention, on envoie un intitule d'Enum ... donc entre .  .
991
992 //=======================================================================
993 //function : SendEnum
994 //purpose  : 
995 //=======================================================================
996
997 void StepData_StepWriter::SendEnum (const Standard_CString val)
998 {
999   
1000   if (val[0] == '$' && val[1] == '\0')  {  SendUndef();  return;  }
1001   TCollection_AsciiString aValue(val);
1002   SendEnum(aValue);
1003 }
1004
1005
1006 //=======================================================================
1007 //function : SendArrReal
1008 //purpose  : 
1009 //=======================================================================
1010
1011 void StepData_StepWriter::SendArrReal (const Handle(TColStd_HArray1OfReal) &anArr)
1012 {
1013   AddString(textlist);
1014   if(anArr->Length()>0) {
1015     // add real
1016     Send(anArr->Value(1));
1017     for( Standard_Integer i=2; i<=anArr->Length(); i++) {
1018 //      AddString(textparam);
1019       //add real
1020       Send(anArr->Value(i));
1021     }
1022   }
1023   AddString(textendlist);
1024 }
1025
1026
1027 //=======================================================================
1028 //function : SendUndef
1029 //purpose  : 
1030 //=======================================================================
1031
1032 void StepData_StepWriter::SendUndef ()
1033 {
1034   AddParam();
1035   AddString(textundef);
1036 }
1037
1038
1039 //=======================================================================
1040 //function : SendDerived
1041 //purpose  : 
1042 //=======================================================================
1043
1044 void StepData_StepWriter::SendDerived ()
1045 {
1046   AddParam();
1047   AddString(textderived);
1048 }
1049
1050
1051 // EndEntity : s'il faut mettre ; a la ligne, l'aligner sur debut d'entite ...
1052
1053 //=======================================================================
1054 //function : EndEntity
1055 //purpose  : 
1056 //=======================================================================
1057
1058 void StepData_StepWriter::EndEntity ()
1059 {
1060   if (thelevel != 1) Interface_InterfaceMismatch::Raise
1061     ("StepWriter : EndEntity");   // decompte de parentheses mauvais ...
1062   AddString(textendent);
1063   thelevel  = 0;        // on garde theindval : sera traite au prochain NewLine
1064   Standard_Boolean indent = theindent; theindent = Standard_False;
1065   NewLine(Standard_False); theindent = indent;
1066   themult = Standard_False;
1067 // pour forcer indentation si necessaire
1068 }
1069
1070
1071 //  gestion de la ligne courante (cf aussi NewLine/JoinLine)
1072
1073 //=======================================================================
1074 //function : AddString
1075 //purpose  : 
1076 //=======================================================================
1077
1078 void StepData_StepWriter::AddString(const TCollection_AsciiString& astr,
1079                                     const Standard_Integer more)
1080 {
1081   while (!thecurr.CanGet(astr.Length() + more)) {
1082     thefile->Append(thecurr.Moved());
1083     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1084     thecurr.SetInitial(indst);
1085   }
1086   thecurr.Add(astr);
1087 }
1088
1089
1090 //=======================================================================
1091 //function : AddString
1092 //purpose  : 
1093 //=======================================================================
1094
1095 void StepData_StepWriter::AddString(const Standard_CString astr,
1096                                     const Standard_Integer lnstr,
1097                                     const Standard_Integer more)
1098 {
1099   while (!thecurr.CanGet(lnstr + more)) {
1100     thefile->Append(thecurr.Moved());
1101     Standard_Integer indst = thelevel * 2; if (theindent) indst += theindval;
1102     thecurr.SetInitial(indst);
1103   }
1104   thecurr.Add(astr,lnstr);
1105 }
1106
1107
1108 //   ENVOI FINAL
1109
1110
1111 //=======================================================================
1112 //function : CheckList
1113 //purpose  : 
1114 //=======================================================================
1115
1116 Interface_CheckIterator  StepData_StepWriter::CheckList () const
1117 {
1118   return thechecks;
1119 }
1120
1121
1122 //=======================================================================
1123 //function : NbLines
1124 //purpose  : 
1125 //=======================================================================
1126
1127 Standard_Integer  StepData_StepWriter::NbLines () const
1128 {  return thefile->Length();  }
1129
1130
1131 //=======================================================================
1132 //function : Line
1133 //purpose  : 
1134 //=======================================================================
1135
1136 Handle(TCollection_HAsciiString) StepData_StepWriter::Line
1137        (const Standard_Integer num) const
1138 {  return thefile->Value(num);  }
1139
1140
1141 //=======================================================================
1142 //function : Printw
1143 //purpose  : 
1144 //=======================================================================
1145
1146 Standard_Boolean StepData_StepWriter::Print (Standard_OStream& S)
1147 {
1148   Standard_Boolean isGood = (S.good());
1149   Standard_Integer nb = thefile->Length();
1150   for (Standard_Integer i = 1; i <= nb && isGood; i ++) 
1151     S << thefile->Value(i)->ToCString() << "\n";
1152   
1153   S<< flush;
1154   isGood = (S && S.good());
1155   
1156   return  isGood;
1157   
1158 }