0024947: Redesign OCCT legacy type system -- final corrections
[occt.git] / src / IFSelect / IFSelect_SessionPilot.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 <Standard_Stream.hxx>
15
16 #include <IFSelect_SessionPilot.ixx>
17 #include <IFSelect_Activator.hxx>
18 #include <IFSelect_Selection.hxx>
19 #include <Interface_EntityIterator.hxx>
20 #include <Interface_InterfaceModel.hxx>
21 #include <TColStd_HSequenceOfAsciiString.hxx>
22
23 #include <Interface_Macros.hxx>
24 #include <Message_Messenger.hxx>
25 #include <Message.hxx>
26 #include <OSD_OpenFile.hxx>
27
28 #include <stdio.h>
29
30 #define MAXWORDS 200
31 #define MAXCARS 1000
32
33 static int initactor = 0;
34 static char* trace;
35
36 static TCollection_AsciiString nulword;
37
38 // Nb Maxi de words : cf thewords et method SetCommandLine
39
40     IFSelect_SessionPilot::IFSelect_SessionPilot (const Standard_CString prompt)
41     : theprompt (prompt) , thewords (0,MAXWORDS-1) , thewordeb (0,MAXWORDS-1)
42 {
43   if (theprompt.Length() == 0) theprompt.AssignCat ("Test-XSTEP>");
44   therecord = Standard_False;  thenbwords = 0;
45   if (initactor) return;  initactor = 1;
46   Add (1,"x");
47   Add (1,"exit");
48   Add (2,"?");
49   Add (2,"xhelp");
50   Add (3,"xcommand");
51   Add (4,"xsource");
52   Add (5,"xstep");
53   Add (6,"xnew");
54   trace = getenv("DEBUGMODE");
55 }
56
57
58     Handle(IFSelect_WorkSession)  IFSelect_SessionPilot::Session () const 
59       {  return thesession;  }
60
61     Handle(IFSelect_WorkLibrary)  IFSelect_SessionPilot::Library () const 
62       {  return thesession->WorkLibrary();  }
63
64     Standard_Boolean  IFSelect_SessionPilot::RecordMode () const 
65       {  return therecord;  }
66
67     void  IFSelect_SessionPilot::SetSession
68   (const Handle(IFSelect_WorkSession)& WS)
69       {  thesession = WS;  }
70
71     void  IFSelect_SessionPilot::SetLibrary
72   (const Handle(IFSelect_WorkLibrary)& WL)
73       {  if (!thesession.IsNull()) thesession->SetLibrary(WL);  }
74
75     void  IFSelect_SessionPilot::SetRecordMode (const Standard_Boolean mode)
76       {  therecord = mode;  }
77
78
79     void  IFSelect_SessionPilot::SetCommandLine
80   (const TCollection_AsciiString& command)
81 {
82   Standard_Integer lc = command.Length();
83   if (lc > 200) cout<<" Commande TRES LONGUE : "<<lc<<" caracteres :"<<endl
84     <<command.ToCString()<<endl;
85   thecommand = command;
86   if (thecommand.Value(lc) <= ' ')  {  thecommand.Remove(lc);  lc --;  }
87   thenbwords = 0;
88   Standard_Integer i, nc = 0;
89   char unarg[MAXCARS];
90   for (i = 1; i <= lc; i ++) {
91     char val = command.Value(i);
92     if (val <= ' ') {
93       if (nc == 0) continue;
94       if (thenbwords >= MAXWORDS) {  unarg[nc] = val;  nc ++;  continue;  }
95       unarg[nc] = '\0';
96       thewords(thenbwords).Clear();  thewords(thenbwords).AssignCat(unarg);
97       if (trace) cout<<"thewords("<<thenbwords<<") ="<<unarg<<endl;
98       thenbwords ++; nc = 0;
99       continue;
100     }
101     if (nc == 0) thewordeb.SetValue (thenbwords,i);
102     if (nc > MAXCARS) {  cout<<"Arg."<<thenbwords<<" > "<<MAXCARS<<" car.s, tronque"<<endl; continue;  }
103     unarg[nc] = val;  nc ++;
104   }
105   if (nc > 0) {
106     unarg[nc] = '\0'; thewords(thenbwords).Clear();
107     thewords(thenbwords).AssignCat(unarg);
108     if (trace) cout<<"thewords("<<thenbwords<<")="<<unarg<<endl<<" .. Fin avec thenbwords="<<thenbwords+1<<endl;
109     thenbwords ++;
110   }
111 /*
112     aligner sur MAXWORDS
113   char l0[80],l1[80],l2[80],l3[80],l4[80],l5[80],l6[80],l7[80],l8[80],l9[80];
114   char m0[80],m1[80],m2[80],m3[80],m4[80],m5[80],m6[80],m7[80],m8[80],m9[80];
115   thenbwords = sscanf
116     (thecommand.ToCString(),"%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
117      l0,l1,l2,l3,l4,l5,l6,l7,l8,l9,m0,m1,m2,m3,m4,m5,m6,m7,m8,m9);
118   if (thenbwords <  0) thenbwords = 0;
119   if (thenbwords > MAXWORDS) thenbwords = MAXWORDS;
120   Standard_Integer nb = thewords.Upper();
121   for (i = 0; i <= nb; i ++) thewords(i).Clear();
122   switch (thenbwords) {
123     case 20 : thewords(19).AssignCat(m9);
124     case 19 : thewords(18).AssignCat(m8);
125     case 18 : thewords(17).AssignCat(m7);
126     case 17 : thewords(16).AssignCat(m6);
127     case 16 : thewords(15).AssignCat(m5);
128     case 15 : thewords(14).AssignCat(m4);
129     case 14 : thewords(13).AssignCat(m3);
130     case 13 : thewords(12).AssignCat(m2);
131     case 12 : thewords(11).AssignCat(m1);
132     case 11 : thewords(10).AssignCat(m0);
133     case 10 : thewords(9).AssignCat(l9);
134     case  9 : thewords(8).AssignCat(l8);
135     case  8 : thewords(7).AssignCat(l7);
136     case  7 : thewords(6).AssignCat(l6);
137     case  6 : thewords(5).AssignCat(l5);
138     case  5 : thewords(4).AssignCat(l4);
139     case  4 : thewords(3).AssignCat(l3);
140     case  3 : thewords(2).AssignCat(l2);
141     case  2 : thewords(1).AssignCat(l1);
142     case  1 : thewords(0).AssignCat(l0);
143     default : break;
144   }
145 */
146   thenumrec = 0;
147   theobjrec.Nullify();
148 }
149
150     const TCollection_AsciiString&  IFSelect_SessionPilot::CommandLine () const
151       {  return thecommand;  }
152
153     Standard_CString  IFSelect_SessionPilot::CommandPart
154   (const Standard_Integer numarg) const
155 {
156   if (numarg <= 0) return thecommand.ToCString();
157   if (numarg >= thenbwords) return "";
158   return &(thecommand.ToCString())[thewordeb(numarg)-1];
159 }
160
161     Standard_Integer  IFSelect_SessionPilot::NbWords () const 
162       {  return thenbwords;  }
163
164     const TCollection_AsciiString&  IFSelect_SessionPilot::Word
165   (const Standard_Integer num) const 
166       {  if (num < thenbwords) return thewords(num);  return nulword;  }
167
168     Standard_CString  IFSelect_SessionPilot::Arg
169   (const Standard_Integer num) const 
170       {  return Word(num).ToCString();  }
171
172     Standard_Boolean  IFSelect_SessionPilot::RemoveWord
173   (const Standard_Integer num)
174 {
175   if (num < 0 || num > thenbwords) return Standard_False;
176   Standard_Integer i; // svv Jan11 2000 : porting on DEC
177   for (i = num; i < thenbwords; i ++) {
178     thewords(i).Clear();
179     thewords(i).AssignCat(thewords(i+1).ToCString());
180   }
181   thewords(thenbwords).Clear();
182   thenbwords --;
183 //  Et refaire thecommand. Si num = 0, on supprime le debut (facile)
184   if (num == 0) {
185     thecommand.Remove(1,thewordeb(1));
186   } else {
187 //   Sinon, reconstituer, a partir des words
188     thecommand.Clear();
189     for (i = 0; i < thenbwords; i ++) {
190       if (i > 0) thecommand.AssignCat(" ");
191       thecommand.AssignCat(thewords(i));
192     }
193   }
194
195   return Standard_True;
196 }
197
198     Standard_Integer  IFSelect_SessionPilot::NbCommands () const 
199       {  return thecomlist.Length();  }
200
201     const TCollection_AsciiString&  IFSelect_SessionPilot::Command
202   (const Standard_Integer num) const 
203       {  return thecomlist(num);  }
204
205
206     IFSelect_ReturnStatus  IFSelect_SessionPilot::RecordItem
207   (const Handle(Standard_Transient)& item)
208 {
209   theobjrec = item;
210   return (item.IsNull() ? IFSelect_RetFail : IFSelect_RetDone);
211 }
212
213     Handle(Standard_Transient)  IFSelect_SessionPilot::RecordedItem () const
214       {  return theobjrec;  }
215
216     void  IFSelect_SessionPilot::Clear ()
217       { thecomlist.Clear(); }
218
219
220 //  #######################################################################
221 //  ########        CONTROLE D EXECUTION
222
223
224     IFSelect_ReturnStatus  IFSelect_SessionPilot::ReadScript
225   (const Standard_CString file)
226 {
227   FILE* fic; int lefic = 0;
228   if (file != NULL && file[0] != '\0') {
229     fic = OSD_OpenFile (file,"r");
230     if (fic) lefic = 1;
231     else { cout<<" ...   Script File "<<file<<" not found"<<endl; return IFSelect_RetFail; }
232     cout << " ...   Reading Script File " << file << endl;
233   }
234   else fic = stdin;
235   IFSelect_ReturnStatus stat = IFSelect_RetVoid;
236
237   for (;;) {
238     char ligne[100];
239     if (!lefic) std::cout << theprompt.ToCString();
240     ligne[0] = '\0';
241     fgets(ligne,100,fic);
242     if (feof(fic)) break;
243     if (ligne[0] == '\0') continue;
244 //    On interprete cette commande
245     TCollection_AsciiString command(ligne);
246     if (lefic) cout<<file<<":"<<command;  // le return est dans la ligne ... !
247     stat = Execute(command);
248     if (stat == IFSelect_RetStop) break;
249     if ((stat == IFSelect_RetError || stat == IFSelect_RetFail) && lefic)
250       { cout << " ...   Error in Script File, abandon"<<endl;  break; }
251   }
252   if (!lefic) return IFSelect_RetStop;
253   fclose(fic);
254   cout<<"End of Reading Script File " << file << endl;
255   if (stat == IFSelect_RetError || stat == IFSelect_RetFail) return stat;
256   return IFSelect_RetVoid;        // fin fichier : depiler
257 }
258
259
260 //  On boucle sur la lecture jusqu a une commande de fin ou un EOF
261
262     IFSelect_ReturnStatus  IFSelect_SessionPilot::Perform ()
263 {
264   IFSelect_ReturnStatus stat = IFSelect_RetVoid;
265   if (thenbwords == 0) return stat;
266   if (thewords(0).Value(1) == '#') return stat;  // commentaire
267
268   theobjrec.Nullify();
269 //  Est-ce un nom ?
270
271 //  Commande pour un Acteur
272   Handle(IFSelect_Activator) actor;  Standard_Integer num;
273   if (IFSelect_Activator::Select(thewords(0).ToCString(),num,actor)) {
274     stat = actor->Do(num,this);
275 //  Prise en compte des commandes a resultat
276 //  Ici, resultat non nomme;  Resultat nomme par commande x (plus loin)
277     if (!theobjrec.IsNull()) {
278       thesession->RemoveItem(theobjrec);  //// depannage ?
279       Standard_Boolean addws = thesession->AddItem(theobjrec);
280       if (!addws) { cout<<"Could not add item to session, sorry"<<endl; return IFSelect_RetFail; }
281     }
282
283     if (stat == IFSelect_RetVoid || stat == IFSelect_RetDone) {
284       if (therecord) thecomlist.Append(thecommand);
285     }
286     else if (stat == IFSelect_RetError) cout<<"Error in Command : "<<thecommand<<endl;
287     else if (stat == IFSelect_RetFail) cout << "Execution Failure for : " <<thecommand<<endl;
288     return stat;
289   }
290   cout << " Command : " << thewords(0) << " unknown" << endl;
291   return IFSelect_RetError;    // pas reconnu donc incorrect
292 }
293
294     IFSelect_ReturnStatus  IFSelect_SessionPilot::ExecuteAlias
295   (const TCollection_AsciiString& alias)
296 {
297   if (alias.Length() > 0) thewords(0) = alias;
298   return Perform();
299 }
300
301     IFSelect_ReturnStatus  IFSelect_SessionPilot::Execute
302   (const TCollection_AsciiString& command)
303 {
304   SetCommandLine(command);
305   return Perform();
306 }
307
308     IFSelect_ReturnStatus  IFSelect_SessionPilot::ExecuteCounter
309   (const Handle(IFSelect_SignCounter)& counter, const Standard_Integer numword,
310    const IFSelect_PrintCount mode)
311 {
312   if (counter.IsNull()) return IFSelect_RetError;
313   counter->Clear();
314   if (NbWords() <= numword) counter->AddModel (thesession->Model());
315   else {
316 //   on demande un givelist
317     Handle(TColStd_HSequenceOfTransient) list = thesession->GiveList (CommandPart(numword));
318     if (list.IsNull()) {
319       cout<<"Nothing selected from : "<<CommandPart(numword)<<endl;
320       return IFSelect_RetError;
321     }
322     counter->AddWithGraph (list,thesession->Graph());
323   }
324   counter->PrintList(Message::DefaultMessenger(),thesession->Model(),mode);
325   return IFSelect_RetVoid;
326 }
327
328     Standard_Integer  IFSelect_SessionPilot::Number
329   (const Standard_CString val) const
330 {
331   Standard_Integer num = thesession->NumberFromLabel (val);
332   if (num < 0)  cout<<" Label:"<<val<<" ->"<<-num<<" ent.s, refus"<<endl;
333   return num;
334 }
335
336
337 //  #########################################################################
338 //  ########        ACTIONS SPECIFIQUES DU PILOTE
339
340 #define MAXCOMPERLINE  5
341 #define LENGTHFORCOM  15
342
343     IFSelect_ReturnStatus  IFSelect_SessionPilot::Do
344   (const Standard_Integer number,
345    const Handle(IFSelect_SessionPilot)& session)
346 {
347 //                  Commandes Propres : x, exit, undo, redo, ?, help
348   IFSelect_ReturnStatus  stat = IFSelect_RetVoid;
349   Standard_Integer       argc = NbWords();
350   const Standard_CString arg1 = Word(1).ToCString();
351   Standard_Integer       modhelp = -1;
352   switch (number) {
353     case -1 :                                 //        ****     HELP-XSNEW
354       modhelp = 1;
355       cout<<"  --  Commands candidate for  xsnew  --"<<endl;
356 //  HELP : soit complet (par defaut)  soit limite a xsnew
357     case  0 : {                               //        ****     HELP
358       Handle(TColStd_HSequenceOfAsciiString) list;
359 //    Help complet : on donne la liste des commandes, sans plus (deja pas mal)
360       if (thenbwords <= 1) {
361         list = IFSelect_Activator::Commands(modhelp);
362         Standard_Integer nbcom = 0;
363         Standard_Integer nb = list->Length();
364         cout << " -- Liste des Commands Disponibles --"<<endl;
365         for (Standard_Integer i = 1; i <= nb; i ++) {
366           const TCollection_AsciiString& uncom = list->Value(i);
367           Standard_Integer loncom = uncom.Length();
368           nbcom ++;
369           if (nbcom > MAXCOMPERLINE) { cout<<endl; nbcom = 1; }
370           cout<<" "<<uncom;
371           if (nbcom == MAXCOMPERLINE) continue;
372           for (Standard_Integer j = loncom; j < LENGTHFORCOM; j ++) cout<<" ";
373         }
374         if (nbcom > 0) cout<<endl;
375         cout<<"\nhelp *  liste toutes les commandes avec un help sur chacune\n"
376           <<"help <com> liste la ou les commande debutant par <com>"
377           <<" avec un help sur chacune"<<endl;
378
379 //    Un Help particulier
380       } else {
381         if (thewords(1).IsEqual("*")) list = IFSelect_Activator::Commands(modhelp);
382
383         else list = IFSelect_Activator::Commands(modhelp,thewords(1).ToCString());
384
385         Standard_Integer nb = list->Length();
386         for (Standard_Integer i = 1; i <= nb; i ++) {
387           Handle(IFSelect_Activator) actor;  Standard_Integer num;
388           if (IFSelect_Activator::Select
389               (list->Value(i).ToCString(),num,actor)) {
390             if (IFSelect_Activator::Mode (list->Value(i).ToCString()) == 1)
391               cout<<"[xsnew name] ";
392             cout << list->Value(i) << " : " << actor->Help(num) << endl;
393           }
394         }
395         if (nb == 0 && thenbwords > 1) cout<<" Command "<<Word(1)<<" unknown. "
396           << " help (without command) lists all the commands" << endl;
397       }
398       return IFSelect_RetVoid;
399     }
400     case  1 : return IFSelect_RetStop;        //        ****     Fin de session
401     case  2 : {                               //        ****     HELP
402       return Do(0,this);
403     }
404     case  3 : {                               //        ****     COMMAND
405       if (argc < 2) { cout << "Donner une option :\n"
406          <<"a : analyse une ligne  r : toggle record mode\n"
407          <<"l : list recorded  c : clear  f nom : sauver dans fichier de nom"
408          << endl; return IFSelect_RetVoid; }
409       switch (arg1[0]) {
410         case 'a' : {                          //        ****    command analyse
411           cout<<"Command n0 " << number <<" : "<< session->CommandLine()<<endl;
412           cout<<"Nb Words : " << argc-2 << " :\n";
413           for (Standard_Integer i = 2; i < argc; i ++) {
414             cout << " Word." << i-1 << " : " << session->Word(i) <<endl;
415           }
416           break;
417         }
418         case 'c' : session->Clear();  break;  //        ****    command clear
419         case 'f' : {
420           if (argc < 3) { cout<<"Donner nom de fichier"<<endl; return IFSelect_RetError; }
421           Standard_Integer nb = session->NbCommands();
422           if (nb == 0) { cout<<"Aucune commande enregistree"<<endl; break; }
423           cout << "Nb Commandes enregistrees : " << nb <<endl;
424           ofstream fout(Word(2).ToCString(),ios::out);
425           for (Standard_Integer i = 1; i <= nb; i ++)
426             fout<<session->Command(i)<<endl;
427           break;
428         }
429         case 'l' : {                          //        ****    command list
430           if (session->RecordMode()) cout<<"  -- Record Mode Actif"<<endl;
431           else                       cout<<"  -- Record Mode Inactif"<<endl;
432           Standard_Integer nb = session->NbCommands();
433           cout << "Nb Commandes enregistrees : " << nb << " :"<<endl;
434           for (Standard_Integer i = 1; i <= nb; i ++) {
435             cout<<"  "<<i<<"    "<<session->Command(i)<<endl;
436           }
437           break;
438         }
439         case 'r' : {                          //        ****    command record
440           Standard_Boolean mode = session->RecordMode();
441           if (mode) cout << " -- Record Mode a present Inactif" <<endl;
442           else      cout << " -- Record Mode a present Actif"   <<endl;
443           session->SetRecordMode(!mode);
444           break;
445         }
446         default  : cout << "Option de controle de commande non comprise"<<endl;
447       }
448       return IFSelect_RetVoid;
449     }
450
451     case  4 : {                               //        ****     FILE
452       if (argc < 2) { cout<<"Donner nom de fichier"<<endl; return IFSelect_RetError; }
453       return session->ReadScript
454         (TCollection_AsciiString(session->Word(1)).ToCString());
455 //          On recopie la string parce que Word(1) change tout le temps !
456     }
457
458     case  5 : {                               //        ****     XSTEP
459       if (argc < 2) {
460         cout<<"xstep : prefixe neutre pour toute commande xstep-draw"<<endl
461           <<"xstep command args  equivaut a  command args"<<endl;
462         return Do(2,this);
463       } else {
464         RemoveWord(0);
465         return Perform();
466       }
467     }
468     case  6 : {                               //        ****    XSNEW(variable)
469       if (argc < 3) {
470         cout<<"xsnew nomvar command [args]   creates an item"<<endl
471           <<"  nomvar : name of item (must be a new name) in the session"<<endl;
472         return Do (-1,this);
473       } else {
474
475         theobjrec.Nullify();
476         TCollection_AsciiString name = Word(1);
477 //  Le nom ne doit pas etre deja pris !
478           if (thesession.IsNull()) { cout<<"Command with a Name and no Session defined !"<<endl; return IFSelect_RetFail; }
479 //////    if (thesession->NameIdent(thewords(0).ToCString()) > 0)
480 //////      { cout<<"Command with name:"<<thewords(0)<<", already taken"<<endl; return IFSelect_RetFail; }
481         RemoveWord(0);  RemoveWord(0);
482
483 //  Commande pour un Acteur
484         Handle(IFSelect_Activator) actor;  Standard_Integer num;
485         if (IFSelect_Activator::Select(thewords(0).ToCString(),num,actor)) {
486           theobjrec.Nullify();
487           stat = actor->Do(num,this);
488 //  Prise en compte des commandes a resultat
489           if (!theobjrec.IsNull()) {
490             thesession->RemoveItem(theobjrec);  //// depannage ?
491             Standard_Boolean addws =
492               thesession->AddNamedItem(name.ToCString(),theobjrec);
493             theobjrec.Nullify();
494             if (!addws) { cout<<"Could not add named item:"<<name<<", sorry"<<endl; return IFSelect_RetFail; }
495           }
496           else cout<<"Remark : xsnew with name:"<<name<<" and no result"<<endl;
497
498           return stat;
499         }
500         cout << " Command : " << thewords(0) << " unknown" << endl;
501         return IFSelect_RetError;    // pas reconnu donc incorrect
502       }
503     }
504     default : return IFSelect_RetError;
505   }
506 }
507
508
509
510     Standard_CString  IFSelect_SessionPilot::Help
511   (const Standard_Integer number) const
512 {
513   switch (number) {
514     case  1 : return "exit ou x : Fin de session";
515     case  2 : return "Liste les commandes. ? <titre> : commandes debutant par <titre>";
516     case  3 : return "controle de commande. command tout court pour help complet";
517     case  4 : return "lit les commandes depuis un fichier";
518     case  5 : return "prefixe neutre pour xstep-draw";
519     case  6 : return "creation item : donner nom_item puis commande args";
520     default : return "";
521   }
522 }