0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / IGESData / IGESData_IGESWriter.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <gp_XY.hxx>
16 #include <gp_XYZ.hxx>
17 #include <IGESData_ColorEntity.hxx>
18 #include <IGESData_DefType.hxx>
19 #include <IGESData_IGESEntity.hxx>
20 #include <IGESData_IGESModel.hxx>
21 #include <IGESData_IGESWriter.hxx>
22 #include <IGESData_Protocol.hxx>
23 #include <IGESData_ReadWriteModule.hxx>
24 #include <IGESData_UndefinedEntity.hxx>
25 #include <IGESData_WriterLib.hxx>
26 #include <Interface_EntityIterator.hxx>
27 #include <Interface_FloatWriter.hxx>
28 #include <Interface_InterfaceMismatch.hxx>
29 #include <Interface_Macros.hxx>
30 #include <Interface_ParamList.hxx>
31 #include <Interface_ParamSet.hxx>
32 #include <Interface_ReportEntity.hxx>
33 #include <Message.hxx>
34 #include <Message_Messenger.hxx>
35 #include <Standard_PCharacter.hxx>
36 #include <TCollection_HAsciiString.hxx>
37
38 #include <stdio.h>
39 #define MaxcarsG 72
40 #define MaxcarsP 64
41
42 //#define PATIENCELOG
43
44
45 // Constructeur complet : taille OK, et se remplit depuis le modele en direct
46
47 IGESData_IGESWriter::IGESData_IGESWriter
48   (const Handle(IGESData_IGESModel)& amodel)
49     : thedirs(0,amodel->NbEntities()) , thepnum(1,amodel->NbEntities()+1),
50       thecurr (MaxcarsG+1) , themodew (0) , thefloatw (9)
51 {
52   themodel = amodel;
53   thehead  = new TColStd_HSequenceOfHAsciiString();
54   thesep   = ',';
55   theendm  = ';';
56   thepars  = new TColStd_HSequenceOfHAsciiString();
57   thepnum.SetValue(1,1);     // debut des parametres de la 1re entite
58   thesect  = 0;
59   thepnum.Init(0);
60 //  Format flottant : cf FloatWriter
61 }
62
63     IGESData_IGESWriter::IGESData_IGESWriter ()
64     : thedirs (0,0) , thepnum (1,1) , thecurr (MaxcarsG+1) , thefloatw (9)      {  }
65
66     IGESData_IGESWriter::IGESData_IGESWriter (const IGESData_IGESWriter& )
67     : thedirs (0,0) , thepnum (1,1) , thecurr (MaxcarsG+1) , thefloatw (9)    {  }
68
69
70 //  ....                Controle d Envoi des Flottants                ....
71
72     Interface_FloatWriter& IGESData_IGESWriter::FloatWriter ()
73       {  return thefloatw;  }    // s y reporter
74
75     Standard_Integer&  IGESData_IGESWriter::WriteMode ()
76       {  return themodew;  }
77
78 //  #####################################################################
79 //  ########                GENERATION DU FICHIER                ########
80
81 //=======================================================================
82 //function : SendStartLine
83 //purpose  :
84 //=======================================================================
85 void IGESData_IGESWriter::SendStartLine (const Standard_CString startline)
86 {
87   Standard_PCharacter pstartline;
88   //
89   pstartline=(Standard_PCharacter)startline;
90   //
91   Standard_Size lst = strlen (startline);
92   if (lst == 0) return;
93   if (thestar.IsNull()) thestar = new TColStd_HSequenceOfHAsciiString();
94   if (lst <= (Standard_Size)MaxcarsG) {
95     thestar->Append (new TCollection_HAsciiString(startline));
96     return;
97   }
98 //  Trop longue : on passe par bouts
99   char startchar = startline[MaxcarsG];
100   pstartline[MaxcarsG] = '\0';
101   SendStartLine(startline);
102   pstartline[MaxcarsG] = startchar;
103   SendStartLine (&startline[MaxcarsG]);
104 }
105
106     void IGESData_IGESWriter::SendModel
107   (const Handle(IGESData_Protocol)& protocol)
108 {
109   Message_Messenger::StreamBuffer sout = Message::SendInfo();
110   IGESData_WriterLib lib(protocol);
111
112   Standard_Integer nb = themodel->NbEntities();
113 #ifdef PATIENCELOG
114   sout<< " IGESWriter : " << nb << " Entities (* = 1000 Ent.s)" << std::endl;
115 #endif
116   SectionS   ();
117   Standard_Integer ns = themodel->NbStartLines();
118   Standard_Integer i; // svv Jan11 2000 : porting on DEC
119   for (i = 1; i <= ns; i ++) SendStartLine (themodel->StartLine(i));
120   SectionG   (themodel->GlobalSection());
121   SectionsDP ();
122   for (i = 1; i <= nb; i ++) {
123     Handle(IGESData_IGESEntity) ent = themodel->Entity(i);
124     Handle(IGESData_IGESEntity) cnt = ent;
125 #ifdef PATIENCELOG
126     if (i % 1000 == 1) std::cout << "*" << std::flush;
127 #endif
128 //  Attention aux cas d erreur : contenu redefini
129     if (themodel->IsRedefinedContent(i)) {
130       sout << " --  IGESWriter : Erroneous Entity N0."<<i<<"  --"<<std::endl;
131       Handle(Interface_ReportEntity) rep = themodel->ReportEntity(i);
132       if (!rep.IsNull()) cnt = GetCasted(IGESData_IGESEntity,rep->Content());
133       if (cnt.IsNull())  cnt = ent;    // secours
134     }
135
136     DirPart         (cnt);
137     OwnParams       (ent);  // preparation : porte sur le vrai <ent> ...
138
139 //  Envoi proprement dit des Parametres proprement definis
140     Handle(IGESData_ReadWriteModule) module;  Standard_Integer CN;
141 //  Differents cas
142     if (lib.Select(cnt,module,CN))
143       module->WriteOwnParams (CN,cnt,*this);
144     else if (cnt->IsKind(STANDARD_TYPE(IGESData_UndefinedEntity))) {
145       DeclareAndCast(IGESData_UndefinedEntity,undent,cnt);
146       undent->WriteOwnParams (*this);
147     }
148     else sout<<" -- IGESWriter : Not Processed for n0."<<i<<" in file,  Type "
149       <<cnt->TypeNumber()<<"  Form "<<cnt->FormNumber()<<std::endl;
150
151     Associativities (cnt);
152     Properties      (cnt);
153     EndEntity ();
154   }
155 #ifdef PATIENCELOG
156   std::cout << " Envoi des Entites Termine"<<std::endl;
157 #endif
158   SectionT();
159 }
160
161
162     void IGESData_IGESWriter::SectionS ()
163 {
164   if (thesect != 0) throw Interface_InterfaceError("IGESWriter : SectionS");
165   thesect = 1;
166 }
167
168     void IGESData_IGESWriter::SectionG (const IGESData_GlobalSection& header)
169 {
170   if (thesect != 1) throw Interface_InterfaceError("IGESWriter : SectionG");
171   thesect = 2;
172   thesep  = header.Separator();
173   theendm = header.EndMark();
174   thecurr.SetMax (MaxcarsG);
175   //   Important : les Parametres sont sortis sous leur forme definitive
176   //   (c-a-d Hollerith pour les Textes ...)
177   Handle(Interface_ParamSet) gl = header.Params();
178   Standard_Integer nb = gl->NbParams();
179   for (Standard_Integer i = 1; i <= nb; i ++) {
180     const Interface_FileParameter& FP = gl->Param(i);
181     AddString(FP.CValue());
182     if (i < nb) AddChar(thesep);
183     else        AddChar(theendm);
184   }
185   if (thecurr.Length() > 0) thehead->Append(thecurr.Moved());
186 }
187
188     void IGESData_IGESWriter::SectionsDP ()
189 {
190   if (thesect != 2) throw Interface_InterfaceError("IGESWriter : SectionsDP");
191   thesect = 3;
192   thecurr.SetMax (MaxcarsP);
193   thestep = IGESData_ReadEnd;
194 }
195
196     void IGESData_IGESWriter::SectionT ()
197 {
198   if (thesect != 3) throw Interface_InterfaceError("IGESWriter : SectionT");
199   thesect = 4;
200   thepnum.SetValue(thepnum.Length(),thepars->Length()+1);
201 }
202
203
204     void IGESData_IGESWriter::DirPart
205       (const Handle(IGESData_IGESEntity)& anent)
206 {
207   if (thesect != 3 && thestep != IGESData_ReadEnd)
208     throw Interface_InterfaceError("IGESWriter : DirPart");
209   Standard_Integer v[17]; Standard_Character res1[9],res2[9],label[9],snum[9];
210   Standard_Integer nument = themodel->Number(anent);
211   if (nument == 0) return;
212   IGESData_DirPart& DP = thedirs.ChangeValue(nument);
213 //                                            Remplissage du DirPart
214   v[0] = anent->TypeNumber();
215   v[1] = 0;               // numero en section P : calcule ulterieurement
216   if (anent->HasStructure())           v[2] = - themodel->DNum(anent->DirFieldEntity(3));
217   else                                 v[2] = 0;
218
219   IGESData_DefType linet = anent->DefLineFont();
220   if (linet == IGESData_DefReference)  v[3] = - themodel->DNum(anent->DirFieldEntity(4));
221   else if (linet == IGESData_DefValue) v[3] = anent->RankLineFont();
222   else                                 v[3] = 0;
223
224   IGESData_DefList levt = anent->DefLevel();
225   if (levt == IGESData_DefSeveral)     v[4] = - themodel->DNum(anent->DirFieldEntity(5));
226   else if (levt == IGESData_DefOne)    v[4] = anent->Level();
227   else                                 v[4] = 0;
228
229   IGESData_DefList viewt = anent->DefView();
230   if (viewt == IGESData_DefSeveral || viewt == IGESData_DefOne)
231     v[5]                                    = themodel->DNum(anent->DirFieldEntity(6));
232   else                                 v[5] = 0;
233
234   if (anent->HasTransf())              v[6] = themodel->DNum(anent->DirFieldEntity(7));
235   else                                 v[6] = 0;
236
237   if (anent->HasLabelDisplay())        v[7] = themodel->DNum(anent->DirFieldEntity(8));
238   else                                 v[7] = 0;
239
240   v[8] = anent->BlankStatus();
241   v[9] = anent->SubordinateStatus();
242   v[10] = anent->UseFlag();
243   v[11] = anent->HierarchyStatus();
244   v[12] = v[0];                      // type repete
245   v[13] = anent->LineWeightNumber();
246
247   IGESData_DefType colt = anent->DefColor();
248   if (colt == IGESData_DefReference)   v[14] = - themodel->DNum(anent->DirFieldEntity(13));
249   else if (colt == IGESData_DefValue)  v[14] = anent->RankColor();
250   else                                 v[14] = 0;
251
252   v[15] = 0;                        // nb lignes section P : calcule plus tard
253   v[16] = anent->FormNumber();
254
255   anent->CResValues(res1,res2);
256   Standard_Integer i; // svv Jan11 2000 : porting on DEC
257   for (i = 0; i < 8; i ++) label[i] = snum[i] = ' ';
258   if (anent->HasShortLabel()) {
259     Handle(TCollection_HAsciiString) slab = anent->ShortLabel();
260     for (i = 0; i < slab->Length(); i ++) label[i] = slab->Value(i+1);
261   }
262   if (anent->HasSubScriptNumber()) {
263     Standard_Integer sn = anent->SubScriptNumber();  // -> cadres a droite
264     snum[7] = '0';    i = 7;
265     while (sn != 0) {
266       snum[i] = (char) ((sn % 10) + 48);
267       sn = sn / 10;   i --;
268     }
269   }
270
271   DP.Init(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],
272           v[13],v[14],v[15],v[16],res1,res2,label,snum);
273 //  DP ChangeValue donc mis a jour d office
274   thestep = IGESData_ReadDir;
275 }
276
277     void IGESData_IGESWriter::OwnParams
278   (const Handle(IGESData_IGESEntity)& anent)
279 {
280   char text[20];
281   if (thesect != 3 && thestep != IGESData_ReadDir)
282     throw Interface_InterfaceError("IGESWriter : OwnParams");
283   thepnum.SetValue(themodel->Number(anent),thepars->Length()+1);
284   thecurr.Clear();
285   sprintf(text,"%d",anent->TypeNumber());
286   AddString(text);
287   thestep = IGESData_ReadOwn;
288 }
289
290     void IGESData_IGESWriter::Properties
291   (const Handle(IGESData_IGESEntity)& anent)
292 {
293   if (thesect != 3 && thestep != IGESData_ReadOwn)
294     throw Interface_InterfaceError("IGESWriter : Properties");
295   thestep = IGESData_ReadProps;
296   if (!anent->ArePresentProperties()) return;
297   Send(anent->NbProperties());
298   for (Interface_EntityIterator iter = anent->Properties();
299        iter.More(); iter.Next()) {
300     DeclareAndCast(IGESData_IGESEntity,localent,iter.Value());
301     Send(localent);
302   }
303 }
304
305     void IGESData_IGESWriter::Associativities
306   (const Handle(IGESData_IGESEntity)& anent)
307 {
308   if (thesect != 3 && thestep != IGESData_ReadOwn)
309     throw Interface_InterfaceError("IGESWriter : Associativities");
310   thestep = IGESData_ReadAssocs;
311   if (!anent->ArePresentAssociativities() && !anent->ArePresentProperties())
312     return;  // Properties suivent : ne pas les omettre !
313   Send(anent->NbAssociativities());
314   for (Interface_EntityIterator iter = anent->Associativities();
315        iter.More(); iter.Next()) {
316     DeclareAndCast(IGESData_IGESEntity,localent,iter.Value());
317     Send(localent);
318   }
319   thestep = IGESData_ReadAssocs;
320 }
321
322     void IGESData_IGESWriter::EndEntity ()
323 {
324   if (thesect != 3 && thestep != IGESData_ReadOwn)
325     throw Interface_InterfaceError("IGESWriter : EndEntity");
326   AddChar(theendm);
327   if (thecurr.Length() > 0) thepars->Append(thecurr.Moved());
328   thestep = IGESData_ReadEnd;
329 }
330
331 //  ....                    Alimentation des parametres                    ....
332
333     void IGESData_IGESWriter::AddString
334   (const Handle(TCollection_HAsciiString)& val, const Standard_Integer more)
335 {
336   if (val.IsNull()) return;
337   AddString (val->ToCString(),val->Length(),more);
338 }
339
340     void IGESData_IGESWriter::AddString
341   (const Standard_CString val, const Standard_Integer lnval,
342    const Standard_Integer more)
343 {
344   Standard_Integer lnstr = lnval;
345   if (lnstr <= 0)  lnstr = (Standard_Integer)strlen(val);
346   if (!thecurr.CanGet (lnstr + more + 1)) {
347 // + 1 (18-SEP-1996) pour etre sur que le separateur n est pas en tete de ligne
348     if (thesect < 3) thehead->Append(thecurr.Moved());
349     else             thepars->Append(thecurr.Moved());
350   }
351   Standard_Integer maxcars  = (thesect == 3 ? MaxcarsP : MaxcarsG);
352   Standard_Integer n2 = 0;
353 // ..  pb de taille limite (30-DEC-1996)
354   while (lnstr > maxcars) {
355     thecurr.Add (&val[n2],lnstr);
356     if (thesect < 3) thehead->Append(thecurr.Moved());
357     else             thepars->Append(thecurr.Moved());
358     n2 += maxcars;  lnstr -= maxcars;
359   }
360   thecurr.Add (&val[n2],lnstr);
361 }
362
363     void IGESData_IGESWriter::AddChar
364   (const Standard_Character val,
365    const Standard_Integer more)
366 {
367 //   1 seul caractere : cas particulier simplifie
368   char text[2];
369   text[0] = val;
370   text[1] = '\0';
371   if (!thecurr.CanGet (1 + more)) {
372     if (thesect < 3) thehead->Append(thecurr.Moved());
373     else             thepars->Append(thecurr.Moved());
374   }
375   thecurr.Add (text,1);
376 }
377
378
379     void IGESData_IGESWriter::SendVoid ()
380       {  AddChar(thesep);  }
381
382     void IGESData_IGESWriter::Send (const Standard_Integer val)
383 {
384   char text[20];
385   AddChar(thesep);
386   sprintf(text,"%d",val);
387   AddString(text);
388 }
389
390     void IGESData_IGESWriter::SendBoolean (const Standard_Boolean val)
391 {
392   AddChar(thesep);
393   if (val) AddString("1");
394   else     AddString("0");
395 }
396
397     void IGESData_IGESWriter::Send (const Standard_Real val)
398 {
399 //    Valeur flottante, expurgee de "0000" qui trainent et de "E+00"
400   char lval[24];
401   AddChar(thesep);
402   Standard_Integer lng = thefloatw.Write (val,lval);
403   AddString(lval,lng);
404 }
405
406     void IGESData_IGESWriter::Send (const Handle(TCollection_HAsciiString)& val)
407 {
408   AddChar(thesep);
409   if (val.IsNull()) return;
410   Standard_Integer lns = val->Length();
411   if (lns == 0) return;     // string vide : void vaut mieux que 0H
412   Handle(TCollection_HAsciiString) hol = new TCollection_HAsciiString(lns);
413   hol->AssignCat("H");  hol->AssignCat(val->ToCString());
414   AddString(hol);
415 }
416
417     void IGESData_IGESWriter::Send
418   (const Handle(IGESData_IGESEntity)& val, const Standard_Boolean negative)
419 {
420   Standard_Integer num = 0;
421   if (!val.IsNull()) num = themodel->DNum(val);
422   if (negative) num = -num;
423   Send(num);    // qui faut tout, une fois Entity convertie en Integer
424 }
425
426     void IGESData_IGESWriter::Send (const gp_XY&  val)
427       {  Send(val.X());  Send(val.Y());  }
428
429     void IGESData_IGESWriter::Send (const gp_XYZ& val)
430       {  Send(val.X());  Send(val.Y());  Send(val.Z());  }
431
432
433     void IGESData_IGESWriter::SendString (const Handle(TCollection_HAsciiString)& val)
434 {
435   AddChar(thesep);
436   AddString(val);    // envoi en l etat
437 }
438
439
440 //  ....                            Envoi final                            ....
441
442     Handle(TColStd_HSequenceOfHAsciiString) IGESData_IGESWriter::SectionStrings
443   (const Standard_Integer num) const
444 {
445   Handle(TColStd_HSequenceOfHAsciiString) res;
446   if (num == 1) res = thestar;
447   if (num == 2) res = thehead;
448   if (num >= 3) res = thepars;
449   return res;
450 }
451
452 static void writefnes (Standard_OStream& S, const Standard_CString ligne)
453 {
454   char val;
455   for (Standard_Integer i = 0; i < 80; i ++) {
456     if (ligne[i] == '\0') return;
457     val = (char)(ligne[i] ^ (150 + (i & 3)));
458     S << val;
459   }
460 }
461
462 Standard_Boolean IGESData_IGESWriter::Print (Standard_OStream& S) const
463 {
464 //  ATTENTION MODEFNES : si themodew = 10 ... alors on ecrit du FNES
465 //  quesaco ? fnes = iges + xor sur les caracteres (150,151,152,153,150...)
466 //   avec en plus une ligne qcq en tete ...
467 //  donc tous les 4 car.s, on fait un tour de modulo. ainsi a 64 et a 72 ...
468 //  On a une mini-routine qui ecrit un morceau de texte "en fnes", et les
469 //  blancs qui sont optimises (quand meme ...)
470
471   Standard_Boolean isGood = (S.good() );
472   Standard_Boolean fnes = (themodew >= 10);
473   if(!isGood)
474     return isGood;
475   char ligne[256];
476 #ifdef PATIENCELOG
477   Standard_Integer lignespatience = 1000;
478 #endif
479   char blancs[73];
480   Standard_Integer i; // svv Jan11 2000 : porting on DEC
481   for (i = 0; i < MaxcarsG; i ++) blancs[i] = ' ';
482   blancs[MaxcarsG] = '\0';
483   if (fnes)
484   {
485     for (i = 0; i < MaxcarsG; i ++)
486       blancs[i] = (char)(blancs[i] ^ (150 + (i & 3)));
487   }
488
489   if (thesect != 4) throw Interface_InterfaceError("IGESWriter not ready for Print");
490 //  Start Section (assez simple, somme toute). Attention si commentaires
491   Handle(TCollection_HAsciiString) line;
492   Standard_Integer nbs = 1;
493   if (thestar.IsNull()) {
494     if (fnes) {
495       S << "                              ***  EUCLID/STRIM  DESKTOP CLIPBOARD  ***"<<std::endl;
496       writefnes (S,"                                                                        S0000001");
497     }
498     else S <<"                                                                        S0000001";
499 //      123456789 123456789 123456789 123456789 123456789 123456789 123456789 12
500     S << std::endl;
501   } else {
502     nbs = thestar->Length();
503     for (i = 1; i <= nbs; i ++) {
504       char finlin[20];
505       sprintf(finlin,"S%7.7d",i);
506       line = thestar->Value(i);
507
508       if (fnes) writefnes (S,line->ToCString());
509       else S << line->ToCString();
510 //    for (Standard_Integer k = line->Length()+1; k <= MaxcarsG; k ++)  aSender <<' ';
511       S << &blancs[line->Length()];
512       if (fnes) writefnes (S,finlin);
513       else S << finlin;
514       S << std::endl;
515     }
516   }
517 #ifdef PATIENCELOG
518   std::cout << "Global Section : " << std::flush;
519 #endif
520   isGood = S.good();
521 //  Global Section  :  convertie dans <thehead>
522   Standard_Integer nbg = thehead->Length();
523   for (i = 1; i <= nbg && isGood ;i++) {
524     char finlin[20];
525     sprintf(finlin,"G%7.7d",i);
526     line = thehead->Value(i);
527
528     if (fnes) writefnes (S,line->ToCString());
529     else S << line->ToCString();
530 //    for (Standard_Integer k = line->Length()+1; k <= MaxcarsG; k ++)  aSender <<' ';
531     S << &blancs[line->Length()];
532     if (fnes) writefnes (S,finlin);
533     else S << finlin;
534     S << std::endl;
535     isGood = S.good();
536   }
537   if(!isGood)
538     return isGood;
539 #ifdef PATIENCELOG
540   std::cout << nbg << " lines" << std::endl;
541 #endif
542
543 //  Directory Section
544   Standard_Integer nbd = thedirs.Upper();   // 0 -> NbEnts
545 #ifdef PATIENCELOG
546   std::cout << "\nDirectory section : " << nbd << " Entites" << std::endl;
547 #endif
548   for (i = 1; i <= nbd && isGood ; i ++) {
549     Standard_Integer v[17]; char res1[9],res2[9],lab[9],num[9];
550     thedirs.Value(i).Values(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],
551                             v[10],v[11],v[12],v[13],v[14],v[15],v[16],
552                             res1,res2,lab,num);
553     v[1]  = thepnum.Value(i);  // debut en P
554     v[15] = thepnum.Value(i+1)-thepnum.Value(i);  // nb de lignes en P
555     sprintf(ligne,"%8d%8d%8d%8d%8d%8d%8d%8d%2.2d%2.2d%2.2d%2.2dD%7.7d",
556             v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],
557             v[8],v[9],v[10],v[11] ,2*i-1);
558     if (fnes) writefnes (S,ligne);
559     else S << ligne;
560     S << "\n";
561     sprintf(ligne,"%8d%8d%8d%8d%8d%8s%8s%8s%8sD%7.7d",
562             v[0],v[13],v[14],v[15],v[16],res1,res2,lab,num,2*i);
563     if (fnes) writefnes (S,ligne);
564     else S << ligne;
565     S << "\n";
566 //    std::cout << "Ent.no "<<i<<" No en P "<<thepnum.Value(i)<<
567 //      " Lignes P:"<<thepnum.Value(i+1)-thepnum.Value(i)<<std::endl;
568 //    for (j = 0; j < 17; j ++) S <<v[j]<<" ";
569 //    S <<res1<<res2<<" label:"<<lab<<" subnum:"<<num<<std::endl;
570     isGood = S.good();
571   }
572   if(!isGood)
573     return isGood;
574 //  Parameter Section
575 #ifdef PATIENCELOG
576   std::cout<<" Parameter Section : "<<thepnum.Value(nbd)-1
577       <<" lines (* = 1000 lines) "<<std::flush;
578 #endif
579
580   blancs[MaxcarsP] = '\0';
581   for (i = 1; i <= nbd && isGood; i ++) {
582     for (Standard_Integer j = thepnum.Value(i); j < thepnum.Value(i+1); j ++) {
583       char finlin[32];
584       sprintf(finlin," %7.7dP%7.7d",2*i-1,j);
585       line = thepars->Value(j);
586 //      line->LeftJustify(MaxcarsP,' ');  remplace par plus economique ! :
587
588       if (fnes) writefnes (S,line->ToCString());
589       else S << line->ToCString();
590 //      for (Standard_Integer k = line->Length()+1; k <= MaxcarsP; k ++)aSender <<' ';
591       S << &blancs[line->Length()];
592       if (fnes) writefnes (S,finlin);
593       else S << finlin;
594       S << std::endl;
595       isGood = S.good();
596 #ifdef PATIENCELOG
597       lignespatience --;
598       if (lignespatience <= 0) {  std::cout<<"*"<<std::flush;  lignespatience = 1000;  }
599 #endif
600     }
601   }
602   if(!isGood)
603     return isGood;
604 //  Terminal Section (pas trop compliquee, ma foi)
605   sprintf (ligne,
606     "S%7dG%7dD%7dP%7d                                        T0000001",
607            nbs,nbg,nbd*2,thepnum.Value(thepnum.Length())-1);
608 //   12345678- 16- 24- 32  56789 123456789 123456789 123456789 12
609   if (fnes) writefnes (S,ligne);
610   else S << ligne;
611   S << "\n";
612   S.flush();
613   isGood = S.good();
614 #ifdef PATIENCELOG
615   std::cout <<"\n Section T (lines counts) : G "<<nbg<<"   D "<<nbd
616        <<"   P "<<thepnum.Value(thepnum.Length())-1<<"   T 1"<<std::endl;
617 #endif
618   return isGood;
619 }