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