0025367: IGES and BRep persistence - support unicode file names on Windows
[occt.git] / src / IFSelect / IFSelect_SessionFile.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 #include <IFSelect_SessionFile.ixx>
15 #include <IFSelect_SessionDumper.hxx>
16 #include <IFSelect_BasicDumper.hxx>
17 #include <IFSelect_IntParam.hxx>
18 #include <IFSelect_Selection.hxx>
19 #include <IFSelect_SelectExtract.hxx>
20 #include <IFSelect_SelectDeduct.hxx>
21 #include <IFSelect_SelectControl.hxx>
22 #include <IFSelect_SelectCombine.hxx>
23 #include <IFSelect_SelectAnyType.hxx>
24 #include <IFSelect_SelectAnyList.hxx>
25 #include <IFSelect_Dispatch.hxx>
26 #include <IFSelect_Modifier.hxx>
27 #include <IFSelect_Transformer.hxx>
28 #include <TCollection_HAsciiString.hxx>
29 #include <TColStd_HSequenceOfInteger.hxx>
30
31 #include <Message_Messenger.hxx>
32 #include <Message.hxx>
33 #include <Interface_Macros.hxx>
34 #include <stdio.h>
35
36 #include <OSD_OpenFile.hxx>
37
38
39 static int deja = 0;
40
41
42     IFSelect_SessionFile::IFSelect_SessionFile
43   (const Handle(IFSelect_WorkSession)& WS)
44 {
45   ClearLines();
46   themode = Standard_False;
47   if (!deja) {    // au moins celui-la :
48     Handle(IFSelect_BasicDumper) basedumper = new IFSelect_BasicDumper;
49     deja = 1;
50   }
51   thedone = Standard_False;
52   thelastgen = 0;
53   thesess = WS;
54 }
55
56     IFSelect_SessionFile::IFSelect_SessionFile
57   (const Handle(IFSelect_WorkSession)& WS, const Standard_CString filename)
58 {
59   ClearLines();
60   themode = Standard_True;
61   if (!deja) {    // au moins celui-la :
62     Handle(IFSelect_BasicDumper) basedumper = new IFSelect_BasicDumper;
63     deja = 1;
64   }
65   thedone = Standard_False;
66   theownflag = Standard_False;
67   thelastgen = 0;
68   thesess = WS;
69   thedone = (Write (filename) == 0);
70 //  Close fait par Write (selon les cas)
71 }
72
73
74     void  IFSelect_SessionFile::ClearLines ()
75       {  thelist.Clear();  thenl = 0;  }
76
77     Standard_Integer  IFSelect_SessionFile::NbLines () const
78       {  return thelist.Length();  }
79
80
81     const TCollection_AsciiString&  IFSelect_SessionFile::Line
82   (const Standard_Integer num) const
83       {  return thelist.Value(num);  }
84
85
86     void  IFSelect_SessionFile::AddLine (const Standard_CString line)
87       {  thelist.Append (TCollection_AsciiString(line) );  }
88
89     void  IFSelect_SessionFile::RemoveLastLine ()
90       {  if (thelist.Length() > 1) thelist.Remove(thelist.Length());  }
91
92
93     Standard_Boolean  IFSelect_SessionFile::WriteFile
94   (const Standard_CString filename)
95 {
96   FILE* lefic = OSD_OpenFile(filename,"w");
97   Standard_Integer nbl = thelist.Length();
98   for (Standard_Integer i = 1; i <= nbl; i ++)
99     fprintf (lefic,"%s\n",thelist.Value(i).ToCString());
100   fclose ( lefic );
101   ClearLines();
102   return Standard_True;
103 }
104
105     Standard_Boolean  IFSelect_SessionFile::ReadFile
106   (const Standard_CString filename)
107 {
108   char ligne[201];
109   FILE* lefic = OSD_OpenFile(filename,"r");
110   if (!lefic) return Standard_False;
111   ClearLines();
112 //  read mode : lire les lignes
113 //  On charge le fichier dans "thelist"
114   Standard_Boolean header = Standard_False;
115   for(;;) {
116     ligne[0] = '\0';
117     fgets(ligne,200,lefic);
118     if (feof(lefic)) break;
119     if (ligne[0] == '\0') continue;
120 //  D abord ligne initiale ?
121     if (!header)
122       {  if (!RecognizeFile(ligne)) break;  header = Standard_True;  }
123     ligne[200] = '\0';  // fin forcee ...
124     TCollection_AsciiString onemore(ligne);
125     thelist.Append(onemore);
126   }
127   fclose ( lefic );
128   return header;
129 }
130
131     Standard_Boolean  IFSelect_SessionFile::RecognizeFile
132   (const Standard_CString headerline)
133 {
134   Handle(Message_Messenger) sout = Message::DefaultMessenger();
135
136   SplitLine (headerline);
137   if (theline.Length() != 4) { sout<<"File Form Incorrect"<<endl; return Standard_False; }
138   Handle(Standard_Type) sesstype = thesess->DynamicType();
139   if (!theline.Value(1).IsEqual("!XSTEP")  ||
140       !theline.Value(2).IsEqual("SESSION") ||
141       !theline.Value(4).IsEqual(sesstype->Name()) )
142     { sout<<"Lineno."<<thenl<<" : File Header Description Incorrect"<<endl; return Standard_False; }
143 //   Value(3) definit la VERSION du format de fichier
144   return Standard_True;
145 }
146
147
148     Standard_Integer  IFSelect_SessionFile::Write
149   (const Standard_CString filename)
150 {
151   thenewnum = 0;
152   Standard_Integer stat = WriteSession();
153   if (stat != 0) return stat;
154   stat = WriteEnd();
155   if (stat != 0) return stat;
156   return (WriteFile(filename) ? 0 : -1);
157 }
158
159     Standard_Integer  IFSelect_SessionFile::Read
160   (const Standard_CString filename)
161 {
162   if (!ReadFile(filename)) return -1;
163   thenewnum = 0;
164   Standard_Integer stat = ReadSession();
165   if (stat != 0) return stat;
166   stat = ReadEnd();
167   return stat;
168 }
169
170
171 //  ##################################################################
172 //  ########        WriteSession : Ecriture du contenu        ########
173
174     Standard_Integer  IFSelect_SessionFile::WriteSession ()
175 {
176   char laligne[200];
177   thedone = Standard_True;
178 //  ...  Preparation Specifique
179   thenames.Nullify();
180   Standard_Integer nbidents = thesess->MaxIdent();
181   thenums = new TColStd_HArray1OfInteger (0,nbidents); thenums->Init(0);
182   Standard_Integer i; // svv Jan11 2000 : porting on DEC
183   for ( i = 1; i <= nbidents; i ++) {
184     Handle(Standard_Transient) item = thesess->Item(i);
185     if (!item.IsNull()) thenums->SetValue(i,-1);
186   }
187
188 //  ...  ECRITURE
189   sprintf (laligne,"!XSTEP SESSION V1 %s",thesess->DynamicType()->Name());
190   WriteLine(laligne,'\n');
191   sprintf (laligne,"!GENERALS");
192   WriteLine(laligne,'\n');
193   sprintf (laligne,"ErrorHandle %d", (thesess->ErrorHandle() ? 1 : 0));
194   WriteLine(laligne,'\n');
195   Handle(TColStd_HSequenceOfInteger) idents;
196   Standard_Integer nb;
197   Handle(TCollection_HAsciiString) name;
198
199   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_IntParam));
200   nb = idents->Length();
201   if (nb > 0) WriteLine ("!INTEGERS",'\n');
202   Standard_Integer j; // svv Jan11 2000 : porting on DEC
203   for (j = 1; j <= nb; j ++) {
204     i = idents->Value(j);
205     Handle(IFSelect_IntParam) P = thesess->IntParam(i);
206     name = thesess->Name(P);
207     if (name.IsNull()) {
208       thenewnum ++;  idents->SetValue(i,thenewnum);
209       sprintf(laligne," #%d %d",thenewnum,P->Value());
210     }
211     else  sprintf(laligne," %s %d",name->ToCString(),P->Value());
212     WriteLine(laligne,'\n');
213   }
214
215   idents = thesess->ItemIdents(STANDARD_TYPE(TCollection_HAsciiString));
216   nb = idents->Length();
217   if (nb > 0) WriteLine ("!TEXTS",'\n');
218   for (j = 1; j <= nb; j ++) {
219     i = idents->Value(j);
220     Handle(TCollection_HAsciiString) P = thesess->TextParam(i);
221     name = thesess->Name(P);
222     if (name.IsNull()) {
223       thenewnum ++;  thenums->SetValue(i,thenewnum);
224       sprintf(laligne," #%d %s",thenewnum,P->ToCString());
225     }
226     else  sprintf(laligne," %s %s",name->ToCString(),P->ToCString());
227     WriteLine(laligne,'\n');
228   }
229
230   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_Selection));
231   nb = idents->Length();
232   if (nb > 0) WriteLine ("!SELECTIONS",'\n');
233   for (j = 1; j <= nb; j ++) {
234     i = idents->Value(j);
235     Handle(IFSelect_Selection) P = thesess->Selection(i);
236     NewItem (i,P);
237 //  ..  Ecritures particulieres
238 //  ->  Traiter les principaux sous-types : Extract,AnyList,AnyType
239     DeclareAndCast(IFSelect_SelectExtract,sxt,P);
240     if (!sxt.IsNull()) {
241       sprintf(laligne," %c", (sxt->IsDirect() ? 'D' : 'R'));
242       WriteLine(laligne);
243     }
244     DeclareAndCast(IFSelect_SelectAnyList,sli,P);
245     if (!sli.IsNull()) {
246       SetOwn(Standard_False);
247       WriteLine(" LIST");
248       SendItem(sli->Lower());
249       SendItem(sli->Upper());
250       SetOwn(Standard_True);
251     }
252 //  ..  Ecritures specifiques selon dumpers
253     WriteOwn(P);
254     WriteLine("",'\n');
255   }
256
257   SetOwn(Standard_False);
258   if (nb > 0) WriteLine ("!SOURCES",'\n');
259   for (j = 1; j <= nb; j ++) {
260     i = idents->Value(j);
261     Handle(IFSelect_Selection) P = thesess->Selection(i);
262     Standard_Integer nbs = thesess->NbSources(P);
263     if (nbs == 0) continue;
264     name = thesess->Name(P);
265     if (name.IsNull())  sprintf(laligne," #%d %d",thenums->Value(i),nbs);
266     else                sprintf(laligne," %s %d",name->ToCString(),nbs);
267     WriteLine(laligne);
268     for (Standard_Integer k = 1; k <= nbs; k ++)
269       SendItem (thesess->Source(P,k));
270     WriteLine("",'\n');
271   }
272
273   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_GeneralModifier));
274   nb = idents->Length();
275   if (nb > 0) WriteLine ("!MODIFIERS",'\n');
276   for (j = 1; j <= nb; j ++) {
277 //  Description de base des Modifiers, donc sans Selection ni Dispatch-Rank
278     i = idents->Value(j);
279     Handle(IFSelect_GeneralModifier) P = thesess->GeneralModifier(i);
280     NewItem (i,P);
281     SetOwn(Standard_True);
282 //  ..  Ecritures specifiques selon dumpers
283     WriteOwn(P);
284     WriteLine("",'\n');
285   }
286
287   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_Transformer));
288   nb = idents->Length();
289   if (nb > 0) WriteLine ("!TRANSFORMERS",'\n');
290   for (j = 1; j <= nb; j ++) {
291 //  Description des Transformers
292     i = idents->Value(j);
293     Handle(IFSelect_Transformer) P = thesess->Transformer(i);
294     NewItem (i,P);
295     SetOwn(Standard_True);
296 //  ..  Ecritures specifiques selon dumpers
297     WriteOwn(P);
298     WriteLine("",'\n');
299   }
300
301   SetOwn(Standard_False);
302   idents = thesess->ItemIdents(STANDARD_TYPE(IFSelect_Dispatch));
303   nb = idents->Length();
304   if (nb > 0) WriteLine ("!DISPATCHES",'\n');
305   for (j = 1; j <= nb; j ++) {
306     i = idents->Value(j);
307     Handle(IFSelect_Dispatch) P = thesess->Dispatch(i);
308     NewItem (i,P);
309 //  ..  Final Selection
310     SetOwn(Standard_False);
311     SendItem(P->FinalSelection());
312     SetOwn(Standard_True);
313 //  ..  Ecritures specifiques selon dumpers
314     WriteOwn(P);
315     WriteLine("",'\n');
316   }
317
318   WriteLine ("!FILENAMING");
319   SetOwn(Standard_False);
320   Handle(TCollection_HAsciiString) namingpart = thesess->FilePrefix();
321   if (namingpart->IsEmpty()) namingpart.Nullify();
322   if (namingpart.IsNull()) SendVoid();
323   else SendText(namingpart->ToCString());
324   namingpart = thesess->DefaultFileRoot();
325   if (namingpart->IsEmpty()) namingpart.Nullify();
326   if (namingpart.IsNull()) SendVoid();
327   else SendText(namingpart->ToCString());
328   namingpart = thesess->FileExtension();
329   if (namingpart->IsEmpty()) namingpart.Nullify();
330   if (namingpart.IsNull()) SendVoid();
331   else SendText(namingpart->ToCString());
332   WriteLine("",'\n');
333
334   for (j = 1; j <= nb; j ++) {
335     i = idents->Value(j);
336     Handle(IFSelect_Dispatch) P = thesess->Dispatch(i);
337     if (!P->HasRootName()) continue;
338     namingpart = P->RootName();
339     SetOwn(Standard_False);
340     SendItem(P);
341     sprintf(laligne," %s",namingpart->ToCString());
342     WriteLine(laligne,' ');
343     WriteLine("",'\n');
344   }
345
346 //   Pour les Modifiers, ATTENTION car il faut respecter l ORDRE effectif
347 //   Or il y a deux listes : Model Modifiers; File Modifiers
348 //   Les Modifiers eux-memes ont deja ete ecrits
349 //   Ici, on ecrit simplement leur utilisation dans l envoi final
350   for (Standard_Integer formod = 1; formod >= 0; formod --) {
351     idents = thesess->FinalModifierIdents((formod > 0));  // donnes dans l ordre d application
352     nb = idents->Length();
353     if (nb == 0) continue;
354     if (formod > 0) WriteLine ("!MODELMODIFIERS",'\n');
355     else            WriteLine ("!FILEMODIFIERS",'\n');
356     for (j = 1; j <= nb; j ++) {
357       i = idents->Value(j);
358       Handle(IFSelect_GeneralModifier) P = thesess->GeneralModifier(i);
359       SetOwn(Standard_False);
360       SendItem(P);
361       //  ..  Parametres Generaux (les specifiques ont deja ete envoyes)
362       SendItem(P->Selection());
363       SendItem(P->Dispatch());
364       WriteLine("",'\n');
365     }
366   }
367
368 //  ...  Conclusion
369   theline.Clear();
370   return 0;
371 }
372
373     Standard_Integer  IFSelect_SessionFile::WriteEnd ()
374 {
375   WriteLine("!XSTEP END",'\n');   // sinon, cf sous-types de SessionFile ...
376   return 0;
377 }
378
379
380     void  IFSelect_SessionFile::WriteLine
381   (const Standard_CString line, const Standard_Character follow)
382 {
383   if (line[0] != '\0') thebuff.AssignCat (line);
384   if (follow == '\0') return;
385   if (follow != '\n') thebuff.AssignCat(follow);
386   else {
387     thelist.Append(thebuff);
388     thebuff.Clear();
389     thenl ++;
390   }
391 }
392
393     Standard_Boolean  IFSelect_SessionFile::WriteOwn
394   (const Handle(Standard_Transient)& item)
395 {
396   if (item.IsNull()) return Standard_False;
397   SetOwn(Standard_True);
398   Handle(IFSelect_SessionDumper) dumper = IFSelect_SessionDumper::First();
399   while (!dumper.IsNull()) {
400     if (dumper->WriteOwn(*this,item)) break;
401     dumper = dumper->Next();
402   }
403   SetOwn(Standard_False);
404   return (!dumper.IsNull());    // IsNull -> echec
405 }
406
407
408
409 //  ##################################################################
410 //  ########        ReadSession  :  Lecture du contenu        ########
411
412     Standard_Integer  IFSelect_SessionFile::ReadSession ()
413 {
414   Handle(Message_Messenger) sout = Message::DefaultMessenger();
415
416   thedone = Standard_True;
417 //  ...  Preparation Specifique
418   thenums.Nullify();
419   thenames = new Dico_DictionaryOfInteger;
420 //  ..  Donnees generales, controle
421   if (!ReadLine()) return 1;
422   if (theline.Length() != 4) { sout<<"File Form Incorrect"<<endl; return 1; }
423   Handle(Standard_Type) sesstype = thesess->DynamicType();
424   if (!theline.Value(1).IsEqual("!XSTEP")  ||
425       !theline.Value(2).IsEqual("SESSION") ||
426       !theline.Value(4).IsEqual(sesstype->Name()) )
427     { sout<<"Lineno."<<thenl<<" : File Header Description Incorrect"<<endl; return 1; }
428 //   Value(3) definit la VERSION du format de fichier
429   if (!ReadLine()) return 1;
430
431 //  ..  Parametres Generaux
432   Standard_Integer rubr =
433     (theline.Length() == 1 && theline.Value(1).IsEqual("!GENERALS"));
434   while (rubr) {
435     if (!ReadLine()) return 1;
436     if (theline.Length() == 0) continue;
437     const TCollection_AsciiString& ungen = theline.Value(1);
438     if (ungen.Value(1) == '!') break;  // fin des generaux
439     if (ungen.IsEqual("ErrorHandle")) {
440       if (theline.Length() != 2)
441         { sout<<"Lineno."<<thenl<<" : ErrorHandle Description Incorrect"<<endl; continue; }
442       if      (theline.Value(2).IsEqual("0"))
443         thesess->SetErrorHandle(Standard_False);
444       else if (theline.Value(2).IsEqual("1"))
445         thesess->SetErrorHandle(Standard_True);
446       else { sout<<"Lineno."<<thenl<<" : ErrorHandle Incorrect : "<<theline.Value(2)<<endl; continue; }
447       continue;
448     }
449     else sout<<"Lineno."<<thenl<<" : Unknown General Parameter : "<<ungen<<" , ignored"<<endl;
450   }
451
452 //  ..  IntParams
453 //   deja fait  if (!ReadLine()) return 1;
454   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!INTEGERS"));
455   while (rubr) {
456     if (!ReadLine()) return 1;
457     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
458     if (theline.Length() != 2)
459       { sout<<"Lineno."<<thenl<<" : An Integer Parameter is badly defined"<<endl; continue; }
460     Handle(IFSelect_IntParam) par = new IFSelect_IntParam;
461     par->SetValue ( atoi(theline.Value(2).ToCString()) );
462     AddItem (par);
463   }
464
465 //  .. TextParams (ligne de garde deja lue)
466   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!TEXTS"));
467   while (rubr) {
468     if (!ReadLine()) return 1;
469     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
470     if (theline.Length() != 2)
471       { sout<<"Lineno."<<thenl<<" : A Text Parameter is badly defined"<<endl; continue; }
472 //    Attention, un texte peut contenir des blancs ...  repartir de line(thenl)
473     TCollection_AsciiString oneline = thelist.Value(thenl);
474     Standard_Integer iw = 0, inc = 0;
475     for (Standard_Integer ic = 1; ic <= oneline.Length(); ic ++) {
476       char unc = oneline.Value(1);
477       inc = ic;
478       if (unc == ' ') iw = 1;
479       else if (iw > 0) break;
480     }
481     oneline.Remove (1,inc);
482     AddItem ( new TCollection_HAsciiString (oneline.ToCString()) );
483   }
484
485 //  .. Selections (ligne de garde deja lue)
486   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!SELECTIONS"));
487   while (rubr) {
488     if (!ReadLine()) return 1;
489     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
490     if (theline.Length() < 2)
491       { sout<<"Lineno."<<thenl<<" : A Selection is badly defined"<<endl; continue; }
492 //  ..  Analyse de certains cas generaux
493     Handle(IFSelect_IntParam) low,up;
494     Standard_Integer firstown = 3;
495     Standard_Integer direct   = 0;
496     Standard_Integer numlist  = 0;
497     if (theline.Length() > 2) {
498       if      (theline.Value(3).IsEqual("D")) direct = 1;
499       else if (theline.Value(3).IsEqual("R")) direct = -1;
500       if (direct != 0) firstown ++;
501       if (firstown+2 <= theline.Length()) {
502         if (theline.Value(firstown).IsEqual("LIST"))  {
503           numlist = firstown;  firstown += 3;
504           low = GetCasted(IFSelect_IntParam,ItemValue(numlist+1));
505           up  = GetCasted(IFSelect_IntParam,ItemValue(numlist+2));
506         }
507       }
508       SetLastGeneral (firstown-1);
509     }
510     Handle(Standard_Transient) item;   // a fournir ...
511     ReadOwn(item);
512     if (item.IsNull()) continue;
513     DeclareAndCast(IFSelect_SelectExtract,sxt,item);
514     if (!sxt.IsNull()) {
515       if (direct == 0) sout<<"Lineno."<<thenl<<" : A SelectExtract is badly defined"<<endl;
516       else  sxt->SetDirect( (direct > 0) );
517     }
518     DeclareAndCast(IFSelect_SelectAnyList,sli,item);
519     if (!sli.IsNull()) {
520       if (numlist == 0) sout<<"Lineno."<<thenl<<" : A SelectAnyList is badly defined"<<endl;
521       else sli->SetRange(low,up);
522     }
523     AddItem(item);
524   }
525
526 //  .. Sources
527   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!SOURCES"));
528   while (rubr) {
529     if (!ReadLine()) return 1;
530     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
531     if (theline.Length() < 3)
532       { sout<<"Lineno."<<thenl<<" : A Selection Source List is badly defined"<<endl; continue; }
533     DeclareAndCast(IFSelect_Selection,sel,ItemValue(1));
534     if (sel.IsNull())
535       { sout<<"Lineno."<<thenl<<" : A Source List is not for a Selection"<<endl; continue; }
536     Standard_Integer nbs = atoi(theline.Value(2).ToCString());
537 //  .. Differents cas reconnus
538     DeclareAndCast(IFSelect_SelectExtract,sxt,sel);
539     if (!sxt.IsNull()) {
540       if (nbs > 1)
541         sout<<"Lineno."<<thenl<<" : SelectExtract, more than one source, followings ignored"<<endl;
542       DeclareAndCast(IFSelect_Selection,source,ItemValue(3));
543       sxt->SetInput(source);
544     }
545     DeclareAndCast(IFSelect_SelectDeduct,sdt,sel);
546     if (!sdt.IsNull()) {
547       if (nbs > 1)
548         sout<<"Lineno."<<thenl<<" : SelectDeduct, more than one source, followings ignored"<<endl;
549       sdt->SetInput(GetCasted(IFSelect_Selection,ItemValue(3)));
550     }
551     DeclareAndCast(IFSelect_SelectControl,sct,sel);
552     if (!sct.IsNull()) {
553       if (nbs != 2)
554         sout<<"Lineno."<<thenl<<" : SelectControl, not two sources, followings ignored"<<endl;
555       sct->SetMainInput   (GetCasted(IFSelect_Selection,ItemValue(3)));
556       sct->SetSecondInput (GetCasted(IFSelect_Selection,ItemValue(4)));
557     }
558     DeclareAndCast(IFSelect_SelectCombine,sco,sel);
559     if (!sco.IsNull()) {
560       for (Standard_Integer j = 1; j <= nbs; j ++)
561         sco->Add(GetCasted(IFSelect_Selection,ItemValue(j+2)));
562     }
563   }
564
565 //  ... Modifiers en tout genre
566   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!MODIFIERS"));
567   while (rubr) {
568     if (!ReadLine()) return 1;
569     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
570     if (theline.Length() < 2)
571       { sout<<"Lineno."<<thenl<<" : A Modifier is badly defined"<<endl; continue; }
572     Handle(Standard_Transient) item;   // a fournir ...
573     ReadOwn(item);
574     if (item.IsNull()) continue;
575     DeclareAndCast(IFSelect_GeneralModifier,modif,item);
576     if (modif.IsNull())
577       { sout<<"Lineno."<<thenl<<" : A Modifier has not been Recognized"<<endl; continue; }
578     AddItem(modif,Standard_False);  // active plus tard
579   }
580
581 //  ... Transformers
582   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!TRANSFORMERS"));
583   while (rubr) {
584     if (!ReadLine()) return 1;
585     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
586     if (theline.Length() < 2)
587       { sout<<"Lineno."<<thenl<<" : A Transformer is badly defined"<<endl; continue; }
588     Handle(Standard_Transient) item;   // a fournir ...
589     ReadOwn(item);
590     if (item.IsNull()) continue;
591     DeclareAndCast(IFSelect_Transformer,trf,item);
592     if (trf.IsNull())
593       { sout<<"Lineno."<<thenl<<" : A Transformer has not been Recognized"<<endl; continue; }
594     AddItem(trf,Standard_False);  // active plus tard
595   }
596
597 //  ... Dispatches (ligne de garde deja lue)
598   rubr = (theline.Length() == 1 && theline.Value(1).IsEqual("!DISPATCHES"));
599   while (rubr) {
600     if (!ReadLine()) return 1;
601     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
602     if (theline.Length() < 3)
603       { sout<<"Lineno."<<thenl<<" : A Dispatch is badly defined"<<endl; continue; }
604     DeclareAndCast(IFSelect_Selection,input,ItemValue(3));
605     SetLastGeneral(3);
606     Handle(Standard_Transient) item;   // a fournir ...
607     ReadOwn(item);
608     if (item.IsNull()) continue;
609     DeclareAndCast(IFSelect_Dispatch,disp,item);
610     if (disp.IsNull())
611       { sout<<"Lineno."<<thenl<<" : A Dispatch has not been Recognized"<<endl; continue; }
612     AddItem(disp);
613     thesess->SetItemSelection(disp,input);
614   }
615
616 //  ... FileNaming (ligne de garde deja lue)
617 //  ..  Modifiers deja lus et charges
618   rubr = (theline.Length() == 4 && theline.Value(1).IsEqual("!FILENAMING"));
619   if (rubr) {
620     if (!IsVoid(2)) thesess->SetFilePrefix      (TextValue(2).ToCString());
621     if (!IsVoid(3)) thesess->SetDefaultFileRoot (TextValue(3).ToCString());
622     if (!IsVoid(4)) thesess->SetFileExtension   (TextValue(4).ToCString());
623   }
624   while (rubr) {
625     if (!ReadLine()) return 1;
626     if (theline.Value(1).Value(1) == '!') break;    // liste suivante
627     if (theline.Length() != 2)
628       { sout<<"Lineno."<<thenl<<" : A File Root is badly defined"<<endl; continue; }
629     DeclareAndCast(IFSelect_Dispatch,disp,ItemValue(1));
630     thesess->SetFileRoot (disp,theline.Value(2).ToCString());
631   }
632
633 //  ... Modifiers (ligne de garde deja lue)
634 //  ... Attention, deux listes (MODELMODIFIERS et FILEMODIFIERS)
635   for (Standard_Integer formod = 1; formod >= 0; formod --) {
636     rubr = (theline.Length() == 1 &&
637             ( (formod == 1 && theline.Value(1).IsEqual("!MODELMODIFIERS")) ||
638               (formod == 0 && theline.Value(1).IsEqual("!FILEMODIFIERS"))  ) );
639 //    if ( formod == 1 && ( theline.Length() != 1 ||
640 //                       !theline.Value(1).IsEqual("!MODELMODIFIERS")) )
641 //      { sout<<"Lineno."<<thenl<<" : Model Modifier List Incorrect"<<endl;  return 1; }
642 //    if ( formod == 0 && ( theline.Length() != 1 ||
643 //                       !theline.Value(1).IsEqual("!FILEMODIFIERS")) )
644 //      { sout<<"Lineno."<<thenl<<" : File Modifier List Incorrect"<<endl;  return 1; }
645     while (rubr) {
646       if (!ReadLine()) return 1;
647       if (theline.Value(1).Value(1) == '!') break;    // liste suivante
648       if (theline.Length() < 3)
649         { sout<<"Lineno."<<thenl<<" : A General Modifier is badly defined"<<endl; continue; }
650       DeclareAndCast(IFSelect_GeneralModifier,modif,ItemValue(1));
651       DeclareAndCast(IFSelect_Selection,input,ItemValue(2));
652       DeclareAndCast(IFSelect_Dispatch,disp,ItemValue(3));
653       if (modif.IsNull())
654         { sout<<"Lineno."<<thenl<<" : A General Modifier has not been Recognized"<<endl; continue; }
655       thesess->SetItemSelection   (modif,input);
656       if (!disp.IsNull()) thesess->SetAppliedModifier (modif,disp);
657       else                thesess->SetAppliedModifier (modif,thesess->ShareOut());
658     }
659   }
660
661 //  ...  Conclusion : voir ReadEnd (separe)
662   return 0;
663 }
664
665     Standard_Integer  IFSelect_SessionFile::ReadEnd ()
666 {
667   Handle(Message_Messenger) sout = Message::DefaultMessenger();
668   if ( theline.Length() != 2 ||
669       !theline.Value(1).IsEqual("!XSTEP") ||
670       !theline.Value(2).IsEqual("END"))
671     { sout<<"End of File Incorrect, lineno"<<thenl<<endl;  return 1; }
672   return 0;
673 }
674
675
676     Standard_Boolean  IFSelect_SessionFile::ReadLine ()
677 {
678   if (thenl >= thelist.Length()) return Standard_False;
679   thenl ++;
680   Standard_CString ligne = thelist.Value(thenl).ToCString();
681 //   Lignes vides ?
682   if (ligne[0] == '\0') return ReadLine();
683   SplitLine (ligne);
684   return Standard_True;
685 }
686
687
688     void  IFSelect_SessionFile::SplitLine (const Standard_CString line)
689 {
690   char mot[80];
691   theline.Clear();
692   Standard_Integer nbc  = 0;
693   Standard_Boolean word = (line[0] > ' ');
694   for (Standard_Integer i = 0; line[i] != '\0'; i ++) {
695     if (line[i] > ' ') {
696       if (!word) {  nbc = 0; word = Standard_True;  }
697       mot[nbc] = line[i];  nbc ++;
698     } else {
699       if (word) {
700         word = Standard_False;
701         mot[nbc] = '\0';
702         theline.Append (TCollection_AsciiString(mot));
703       }
704       if (line[i] == '\0' || line[i] == '\n') break;
705     }
706   }
707   thelastgen = 0;
708 }
709
710     Standard_Boolean  IFSelect_SessionFile::ReadOwn
711   (Handle(Standard_Transient)& item)
712 {
713   Handle(Message_Messenger) sout = Message::DefaultMessenger();
714
715   if (theline.Length() < 2) return Standard_False;
716   const TCollection_AsciiString& type = theline.Value(2);
717   if (thelastgen < 2) thelastgen = 2;        // mini : ident+type d abord
718 //  thelastgen = theline.Length();
719 //  for (Standard_Integer i = theline.Length(); i > 0; i --) {
720 //    if (theline.Value(i).Value(1) == ':') thelastgen = i - 1;
721 //  }
722   Handle(IFSelect_SessionDumper) dumper = IFSelect_SessionDumper::First();
723   while (!dumper.IsNull()) {
724     if (dumper->ReadOwn(*this,type,item)) break;
725     dumper = dumper->Next();
726   }
727   if (dumper.IsNull()) sout<<" -- Lineno."<<thenl<<" : an Item could not be read"<<endl;
728   return (!dumper.IsNull());    // IsNull -> echec
729 }
730
731
732     void  IFSelect_SessionFile::AddItem
733   (const Handle(Standard_Transient)& item, const Standard_Boolean active)
734 {
735   Handle(Message_Messenger) sout = Message::DefaultMessenger();
736
737   const TCollection_AsciiString& name = theline.Value(1);
738   Standard_Integer id = 0;
739   if (!item.IsNull()) {
740     if (name.Value(1) == '#') id = thesess->AddItem(item,active);
741     else if (!thesess->NamedItem(name.ToCString()).IsNull()) id =
742       thesess->AddItem(item,active);
743     else id = thesess->AddNamedItem(name.ToCString(),item,active);
744   }
745   else sout<<"Lineno."<<thenl<<" -- Name : "<<name
746     <<" : Item could not be defined" << endl;
747   thenames->SetItem(name.ToCString(),id);
748 }
749
750     Standard_Boolean  IFSelect_SessionFile::IsDone () const
751       {  return thedone;  }
752
753     Handle(IFSelect_WorkSession)  IFSelect_SessionFile::WorkSession () const
754       {  return thesess;  }
755
756 //  ########                Actions Unitaires d ECRITURE               ########
757
758     void  IFSelect_SessionFile::NewItem
759   (const Standard_Integer ident, const Handle(Standard_Transient)& par)
760 {
761   char laligne[100];
762   if (!thesess->HasName(par)) {
763     thenewnum ++;  thenums->SetValue(ident,thenewnum);
764     sprintf(laligne," #%d %s",thenewnum,par->DynamicType()->Name());
765   }
766   else  sprintf(laligne," %s %s",thesess->Name(par)->ToCString(),
767                 par->DynamicType()->Name());
768   WriteLine(laligne);
769 }
770
771     void  IFSelect_SessionFile::SetOwn (const Standard_Boolean mode)
772       {  theownflag = mode;  }
773
774     void  IFSelect_SessionFile::SendVoid ()
775 {
776 ////  if (theownflag) WriteLine(" :$");
777   WriteLine(" $");
778 }
779
780     void  IFSelect_SessionFile::SendItem (const Handle(Standard_Transient)& par)
781 {
782   Handle(Message_Messenger) sout = Message::DefaultMessenger();
783
784   char laligne[100];
785   Standard_Integer filenum = 0;
786   Standard_Integer id = thesess->ItemIdent(par);
787   if (id != 0) filenum = thenums->Value(id);
788   if (filenum == 0) {
789     if (!par.IsNull()) sout << "Lineno " << thenl << " --  Unknown Item : "
790        << " Type:" << par->DynamicType()->Name() << endl;  //sout<<Handle par
791     SendVoid();
792     thedone = Standard_False;
793     return;
794   }
795 ////  if (theownflag) WriteLine(" :");
796 ////  else            WriteLine(" ");
797   if (filenum < 0) sprintf(laligne," :%s",thesess->Name(par)->ToCString());
798   else sprintf(laligne," #%d",filenum);
799   WriteLine(laligne);
800 }
801
802     void  IFSelect_SessionFile::SendText (const Standard_CString text)
803 {
804   char laligne[100];
805 ////  if (theownflag) sprintf(laligne," :%s",text);
806   sprintf(laligne," %s",text);
807   WriteLine(laligne);
808 }
809
810
811 //  ########                Actions Unitaires de LECTURE               ########
812
813     void  IFSelect_SessionFile::SetLastGeneral (const Standard_Integer lastgen)
814       {  thelastgen = lastgen;  }
815
816     Standard_Integer  IFSelect_SessionFile::NbParams () const
817       {  return theline.Length() - thelastgen;  }
818
819
820     Standard_Boolean  IFSelect_SessionFile::IsVoid
821   (const Standard_Integer num) const
822 {
823   Standard_Integer nm = num + thelastgen;
824   if (nm <= 0 || nm > theline.Length()) return Standard_True;
825   const TCollection_AsciiString& term = theline.Value(nm);
826   return (term.IsEqual ("$") || term.IsEqual (":$") );
827 }
828
829     Standard_Boolean  IFSelect_SessionFile::IsText
830   (const Standard_Integer num) const
831 {
832   Standard_Integer nm = num + thelastgen;
833   if (nm <= 0 || nm > theline.Length()) return Standard_False;
834   const TCollection_AsciiString& term = theline.Value(nm);
835   if (term.Value(1) == ':') return Standard_False;
836   if (term.Value(1) == '#') return Standard_False;
837   if (term.IsEqual("$"))    return Standard_False;
838   return Standard_True;
839 }
840
841     const TCollection_AsciiString&  IFSelect_SessionFile::ParamValue
842   (const Standard_Integer num) const
843       {  return theline.Value(num+thelastgen);  }
844
845
846     TCollection_AsciiString  IFSelect_SessionFile::TextValue
847   (const Standard_Integer num) const
848 {
849   Standard_Integer nm = num + thelastgen;
850   TCollection_AsciiString res;
851   if (nm <= 0 || nm > theline.Length()) return res;
852   res = theline.Value(nm);
853   if (res.Value( res.Length() ) == '"') res.Remove(res.Length());
854   if (res.Value(1) == ':') res.Remove(1);
855   if (res.Value(1) == '"') res.Remove(1);
856   return res;
857 }
858
859     Handle(Standard_Transient)  IFSelect_SessionFile::ItemValue
860   (const Standard_Integer num) const
861 {
862   Handle(Message_Messenger) sout = Message::DefaultMessenger();
863
864   Handle(Standard_Transient) res;
865   Standard_Integer nm = num + thelastgen;
866   if (nm <= 0 || nm > theline.Length()) return res;
867   Standard_Integer id;
868   TCollection_AsciiString name = theline.Value(nm);
869   if (name.Value(1) == ':') name.Remove(1);
870   if (name.IsEqual("$")) return res;    // item non-defini justement
871   if (!thenames->GetItem(name.ToCString(),id)) {
872     sout << " -- Item Unknown in File : " << name
873       << " lineno " << thenl << " param." << nm << endl;
874     id = 0;
875   }
876   return thesess->Item(id);
877 }
878
879
880     void  IFSelect_SessionFile::Destroy ()
881 {   }  // agit si File non ferme, sinon ne fait rien