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