0027691: Remove dchrono from all test cases and move its to perf group
[occt.git] / src / Draw / Draw_VariableCommands.cxx
1 // Created on: 1995-02-23
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Draw.hxx>
19 #include <Draw_Appli.hxx>
20 #include <Draw_Axis2D.hxx>
21 #include <Draw_Axis3D.hxx>
22 #include <Draw_Display.hxx>
23 #include <Draw_Drawable3D.hxx>
24 #include <Draw_Grid.hxx>
25 #include <Draw_Number.hxx>
26 #include <Draw_ProgressIndicator.hxx>
27 #include <Draw_SequenceOfDrawable3D.hxx>
28 #include <NCollection_Map.hxx>
29 #include <Standard_SStream.hxx>
30 #include <Standard_Stream.hxx>
31 #include <TCollection_AsciiString.hxx>
32
33 #include <ios>
34 #ifdef _WIN32
35 extern Draw_Viewer dout;
36 #endif
37
38 #include <tcl.h>
39 #include <errno.h>
40
41 #include <OSD_Environment.hxx>
42 #include <OSD_OpenFile.hxx>
43
44 Standard_Boolean Draw_ParseFailed;
45
46 static Standard_Boolean autodisp = Standard_True;
47 static Standard_Boolean repaint2d,repaint3d;
48
49 extern Draw_Interpretor theCommands;
50
51 //===============================================
52 // dictionnary of variables
53 // Variables are stored in a map Integer, Transient
54 // The Integer Value is the content of the TCl variable 
55 //===============================================
56
57 static NCollection_Map<Handle(Draw_Drawable3D)> theVariables;
58
59 //=======================================================================
60 //function : FindVariable
61 //purpose  : 
62 //=======================================================================
63
64 static Standard_Integer p_id;
65 static Standard_Integer p_X;
66 static Standard_Integer p_Y;
67 static Standard_Integer p_b;
68 static const char* p_Name = "";
69
70
71 static Draw_SaveAndRestore* Draw_First = NULL;
72
73 //=======================================================================
74 //function : Draw_SaveAndRestore
75 //purpose  : 
76 //=======================================================================
77
78 Draw_SaveAndRestore::Draw_SaveAndRestore
79   (const char* name,
80    Standard_Boolean (*test)(const Handle(Draw_Drawable3D)&),
81   void (*save)(const Handle(Draw_Drawable3D)&, ostream&),
82   Handle(Draw_Drawable3D) (*restore) (istream&),
83   Standard_Boolean display) :
84   myName(name),
85   myTest(test),
86   mySave(save), 
87   myRestore(restore),
88   myDisplay(display),
89   myNext(Draw_First)
90 {
91   Draw_First = this;
92 }
93
94 Standard_Boolean Draw_SaveAndRestore::Test(const Handle(Draw_Drawable3D)&d)
95 {return (*myTest) (d);}
96
97 void Draw_SaveAndRestore::Save(const Handle(Draw_Drawable3D)& d, 
98                                ostream& os) const
99 { (*mySave) (d,os);}
100
101 Handle(Draw_Drawable3D) Draw_SaveAndRestore::Restore(istream& is) const
102 {return (*myRestore) (is);}
103
104 //=======================================================================
105 // numeric save and restore
106 //=======================================================================
107
108 static Standard_Boolean numtest(const Handle(Draw_Drawable3D)& d) 
109 {
110   return d->IsInstance(STANDARD_TYPE(Draw_Number));
111 }
112
113 static void numsave (const Handle(Draw_Drawable3D)& theDrawable,
114                      ostream&                       theStream)
115 {
116   Handle(Draw_Number) aNum = Handle(Draw_Number)::DownCast (theDrawable);
117   ios::fmtflags aFlags = theStream.flags();
118   theStream.setf      (ios::scientific);
119   theStream.precision (15);
120   theStream.width     (30);
121   theStream << aNum->Value() << "\n";
122   theStream.setf      (aFlags);
123 }
124
125 static Handle(Draw_Drawable3D) numrestore (istream& is)
126 {
127   Standard_Real val;
128   is >> val;
129   Handle(Draw_Number) N = new Draw_Number(val);
130   return N;
131 }
132
133
134 static Draw_SaveAndRestore numsr("Draw_Number",
135                                  numtest,numsave,numrestore,
136                                  Standard_False);
137
138 //=======================================================================
139 // save
140 //=======================================================================
141
142 static Standard_Integer save(Draw_Interpretor& di, Standard_Integer n, const char** a)
143 {
144   if (n <= 2) return 1;
145
146
147   const char* name = a[2];
148   ofstream os;
149   os.precision(15);
150   OSD_OpenStream(os, name, ios::out);
151   if (!os.rdbuf()->is_open()) {
152     di << "Cannot open file for writing "<<name;
153     return 1;
154   }
155
156   Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
157   if (!D.IsNull()) {
158     // find a tool
159     Draw_SaveAndRestore* tool = Draw_First;
160     Handle(Draw_ProgressIndicator) progress = new Draw_ProgressIndicator ( di, 1 );
161     progress->SetScale ( 0, 100, 1 );
162     progress->NewScope(100,"Writing");
163     progress->Show();
164
165     while (tool) {
166       if (tool->Test(D)) break;
167       tool = tool->Next();
168     }
169     if (tool) {
170       os << tool->Name() << "\n";
171       Draw::SetProgressBar(progress);
172       tool->Save(D,os);
173       os << "\n";
174     }
175     else {
176       di << "No method for saving " << a[1];
177       return 1;
178     }
179     Draw::SetProgressBar( 0 );
180     progress->EndScope();
181     progress->Show();
182   }
183   
184   os << "0\n\n";
185
186   Standard_Boolean res = Standard_False;
187
188   errno = 0;
189
190   res = os.good() && !errno;
191   if( !res )
192   {
193     di<<"File has not been written";
194     return 1;
195   }
196
197   di << a[1];
198   return 0;
199 }
200
201 //=======================================================================
202 // read
203 //=======================================================================
204
205 static Standard_Integer restore(Draw_Interpretor& di, Standard_Integer n, const char** a)
206 {
207
208   if (n <= 2) return 1;
209
210   const char* fname = a[1];
211   const char* name  = a[2];
212   
213   filebuf fic;
214   istream in(&fic);
215   OSD_OpenStream (fic, fname, ios::in);
216   if (!fic.is_open()) {
217     di << "Cannot open file for reading : "<<fname;
218     return 1;
219   }
220   
221   char typ[255];
222   in >> typ;
223   if (!in.fail()) {
224     // search a tool
225     Handle(Draw_ProgressIndicator) progress = new Draw_ProgressIndicator ( di, 1 );
226     progress->NewScope(100,"Reading");
227     progress->Show();
228
229     Draw_SaveAndRestore* tool = Draw_First;
230     Draw_SaveAndRestore* aDBRepTool = NULL;
231     while (tool) {
232       const char* toolName = tool->Name();
233       if (!strcmp(typ,toolName)) break;
234       if (!strcmp("DBRep_DrawableShape",toolName))
235         aDBRepTool = tool;
236       Draw::SetProgressBar(progress);
237       tool = tool->Next();
238     }
239
240     if (!tool)
241     {
242       //assume that this file stores a DBRep_DrawableShape variable
243       tool = aDBRepTool;
244       in.seekg(0, ios::beg);
245     }
246
247     if (tool)
248     {
249       Handle(Draw_Drawable3D) D = tool->Restore(in);
250       Draw::Set(name,D,tool->Disp() && autodisp);
251     }
252
253     else {
254       di << "Cannot restore a  " << typ;
255       return 1;
256     }
257     Draw::SetProgressBar( 0 );
258     progress->EndScope();
259     progress->Show();
260   }
261   
262   di << name;
263   return 0;
264 }
265
266 //=======================================================================
267 // display
268 //=======================================================================
269
270 static Standard_Integer display(Draw_Interpretor& di, Standard_Integer n, const char** a)
271 {
272   if (n <= 1) return 1;
273   else {
274     for (Standard_Integer i = 1; i < n; i++) {
275       Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
276       if (!D.IsNull()) {
277         if (!D->Visible()) {
278           dout << D;
279           di << a[i] << " ";
280         }
281       }
282     }
283   }
284   return 0;
285 }
286
287 //=======================================================================
288 // erase, clear, donly
289 //=======================================================================
290
291 static Standard_Integer erase(Draw_Interpretor& di, Standard_Integer n, const char** a)
292 {
293   static Standard_Boolean draw_erase_mute = Standard_False;
294   if (n == 2) {
295     if (!strcasecmp(a[1],"-mute")) {
296       draw_erase_mute = Standard_True;
297       return 0;
298     }
299   }
300
301   Standard_Boolean donly = !strcasecmp(a[0],"donly");
302   
303   if (n <= 1 || donly) {
304     // clear, 2dclear, donly, erase (without arguments)
305     Standard_Integer i;
306     
307     // solve the names for "." before erasing
308     if (donly) {
309       for (i = 1; i < n; i++) {
310         Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
311         if (D.IsNull()) {
312           if ((a[i][0] == '.') && (a[i][1] == '\0'))
313             cout << "Missed !!!" << endl;
314           return 0;
315         }
316       }
317     }
318     
319     // sauvegarde des proteges visibles
320     Draw_SequenceOfDrawable3D prot;
321     NCollection_Map<Handle(Draw_Drawable3D)>::Iterator aMapIt (theVariables);
322     for (; aMapIt.More(); aMapIt.Next()) {
323       const Handle(Draw_Drawable3D)& D = aMapIt.Key();
324       if (!D.IsNull()) {
325         if (D->Protected() && D->Visible())
326           prot.Append(D);
327       }
328     }
329   
330     // effacement de toutes les variables
331     Standard_Integer erasemode = 1;
332     if (a[0][0] == '2') erasemode = 2;
333     if (a[0][0] == 'c') erasemode = 3;
334     
335     // effacement des graphiques non variables
336     if (erasemode == 2) 
337       dout.Clear2D();
338     else if (erasemode == 3)
339       dout.Clear3D();
340     else
341       dout.Clear();
342     
343     // affichage pour donly
344     if (donly) {
345       for (i = 1; i < n; i++) {
346         Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
347         if (!D.IsNull()) {
348           if (!D->Visible()) {
349             dout << D;
350             if (!draw_erase_mute) di << a[i] << " ";
351           }
352         }
353       }
354     }
355     
356   // afficahge des proteges
357     for (i = 1; i <= prot.Length(); i++)
358       dout << prot(i);
359     
360     
361   }
362   else {
363     for (Standard_Integer i = 1; i < n; i++) {
364       Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
365       if (!D.IsNull()) {
366         if (D->Visible()) {
367             dout.RemoveDrawable(D);
368             if (!draw_erase_mute) di << D->Name() << " ";
369           }
370       }
371     }
372     dout.Repaint2D();
373     dout.Repaint3D();
374   }
375   draw_erase_mute = Standard_False;
376   repaint2d = Standard_False;
377   repaint3d = Standard_False;
378   dout.Flush();
379   return 0;
380 }
381
382
383
384 //=======================================================================
385 // draw
386 //=======================================================================
387
388 static Standard_Integer draw(Draw_Interpretor& , Standard_Integer n, const char** a)
389 {
390   if (n < 3) return 1;
391   Standard_Integer id = Draw::Atoi(a[1]);
392   if (!dout.HasView(id)) {
393     cout << "bad view number in draw"<<endl;
394     return 1;
395   }
396   Standard_Integer mo = Draw::Atoi(a[2]);
397   Draw_Display d = dout.MakeDisplay(id);
398   d.SetMode(mo);
399   Standard_Integer i;
400   for (i = 3; i < n; i++) {
401     Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
402     if (!D.IsNull()) D->DrawOn(d);
403   }
404   d.Flush();
405   return 0;
406 }
407
408 //=======================================================================
409 // protect, unprotect
410 //=======================================================================
411
412 static Standard_Integer protect(Draw_Interpretor& di, Standard_Integer n, const char** a)
413 {
414   if (n <= 1) return 1;
415   Standard_Boolean prot = *a[0] != 'u';
416   for (Standard_Integer i = 1; i < n; i++) {
417     Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
418     if (!D.IsNull()) {
419       D->Protected(prot);
420       di << a[i] << " ";
421     }
422   }
423   return 0;
424 }
425
426 //=======================================================================
427 // autodisplay
428 //=======================================================================
429
430 static Standard_Integer autodisplay(Draw_Interpretor& di, Standard_Integer n, const char** a)
431 {
432   if (n <= 1)
433     autodisp = !autodisp;
434   else 
435     autodisp = !(!strcasecmp(a[1],"0"));
436
437   if (autodisp)
438     di << "1";
439   else
440     di << "0";
441
442   return 0;
443 }
444
445
446 //=======================================================================
447 // whatis
448 //=======================================================================
449
450 static Standard_Integer whatis(Draw_Interpretor& di, Standard_Integer n, const char** a)
451 {
452   if (n <= 1) return 1;
453   for (Standard_Integer i = 1; i < n; i++) {
454     Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
455     if (!D.IsNull()) {
456       D->Whatis(di);
457     }
458   }
459   return 0;
460 }
461
462
463 //=======================================================================
464 // value
465 //=======================================================================
466
467 static Standard_Integer value(Draw_Interpretor& di, Standard_Integer n, const char** a)
468 {
469   if (n != 2) return 1;
470   di << Draw::Atof(a[1]);
471
472   return 0;
473 }
474
475 //=======================================================================
476 //function : dname
477 //purpose  : 
478 //=======================================================================
479 static Standard_Integer dname(Draw_Interpretor& di, Standard_Integer n, const char** a)
480 {
481   if (n <= 1) {
482     return 1;
483   }
484   //
485   Standard_PCharacter pC;
486   Standard_Integer i;
487   Handle(Draw_Drawable3D) aD;
488   //
489   for (i = 1; i < n; ++i) {
490     aD = Draw::Get(a[i]);
491     if (!aD.IsNull()) {
492       //modified by NIZNHY-PKV Tue Jun 10 10:18:13 2008f
493       //di << a[i];
494       pC=(Standard_PCharacter)aD->Name();
495       di << pC;
496       //modified by NIZNHY-PKV Tue Jun 10 10:18:18 2008t
497     }
498   }
499   return 0;
500 }
501
502 //=======================================================================
503 // dump
504 //=======================================================================
505
506
507 static Standard_Integer dump(Draw_Interpretor& DI, Standard_Integer n, const char** a)
508 {
509   if(n < 2) return 1;
510   Standard_Integer i;
511   for (i = 1; i < n; i++) {
512     Handle(Draw_Drawable3D) D = Draw::Get(a[i]);
513     if (!D.IsNull()) {
514       Standard_SStream sss;
515       sss.precision(15);
516       sss << "\n\n*********** Dump of " << a[i] << " *************\n";
517       D->Dump(sss);
518       DI << sss;
519     }
520   }
521   return 0;
522 }
523
524 //=======================================================================
525 // copy
526 //=======================================================================
527
528 static Standard_Integer copy(Draw_Interpretor& , Standard_Integer n, const char** a)
529 {
530   if (n < 3) return 1;
531   Standard_Boolean cop = !strcasecmp(a[0],"copy");
532
533   Handle(Draw_Drawable3D) D;
534   for (Standard_Integer i = 1; i < n; i += 2) {
535     if (i+1 >= n) return 0;
536     D = Draw::Get(a[i]);
537     if (!D.IsNull()) {
538       if (cop) 
539         D = D->Copy();
540       else 
541         // clear old name
542         Draw::Set(a[i],Handle(Draw_Drawable3D)());
543
544       Draw::Set(a[i+1],D);
545     }
546   }
547   return 0;
548 }
549
550 //=======================================================================
551 //function : repaint
552 //purpose  : 
553 //=======================================================================
554
555 static Standard_Integer repaintall(Draw_Interpretor& , Standard_Integer , const char** )
556 {
557   if (repaint2d) dout.Repaint2D();
558   repaint2d = Standard_False;
559   if (repaint3d) dout.Repaint3D();
560   repaint3d = Standard_False;
561   dout.Flush();
562   return 0;
563 }
564
565 //=======================================================================
566 //function : set
567 //purpose  : 
568 //=======================================================================
569
570 static Standard_Integer set(Draw_Interpretor& di, Standard_Integer n, const char** a)
571 {
572   if (n < 2) return 1;
573   Standard_Integer i = 1;
574   Standard_Real val=0;
575   for (i = 1; i < n; i += 2) {
576     val = 0;
577     if (i+1 < n) val = Draw::Atof(a[i+1]);
578     Draw::Set(a[i],val);
579   }
580   di << val;
581   return 0;
582 }
583
584 //=======================================================================
585 //function : dsetenv
586 //purpose  : 
587 //=======================================================================
588
589 static Standard_Integer dsetenv(Draw_Interpretor& /*di*/, Standard_Integer argc, const char** argv)
590 {
591   if (argc < 2) {
592     cout << "Use: " << argv[0] << " {varname} [value]" << endl;
593     return 1;
594   }
595
596   OSD_Environment env (argv[1]);
597   if (argc > 2 && argv[2][0] != '\0')
598   {
599     env.SetValue (argv[2]);
600     env.Build();
601   }
602   else
603     env.Remove();
604   return env.Failed();
605 }
606
607 //=======================================================================
608 //function : dgetenv
609 //purpose  : 
610 //=======================================================================
611
612 static Standard_Integer dgetenv(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
613 {
614   if (argc < 2) {
615     cout << "Use: " << argv[0] << " {varname}" << endl;
616     return 1;
617   }
618
619   const char* val = getenv (argv[1]);
620   di << ( val ? val : "" );
621   return 0;
622 }
623
624 //=======================================================================
625 //function : isdraw
626 //purpose  : 
627 //=======================================================================
628
629 static Standard_Integer isdraw(Draw_Interpretor& di, Standard_Integer n, const char** a)
630 {
631   if (n != 2) return 1;
632   Handle(Draw_Drawable3D) D = Draw::Get(a[1],Standard_False);
633   if (D.IsNull())
634     di << "0";
635   else
636     di << "1";
637   return 0;
638 }
639
640 //=======================================================================
641 //function : isprot
642 //purpose  : 
643 //=======================================================================
644
645 Standard_Integer isprot(Draw_Interpretor& di, Standard_Integer n, const char** a)
646 {
647   if (n != 2) return 1;
648   Handle(Draw_Drawable3D) D = Draw::Get(a[1],Standard_False);
649   if (D.IsNull())
650     di << "0";
651   else {
652     if (D->Protected())
653       di << "1";
654     else
655       di << "0";
656   }
657   return 0;
658 }
659
660
661 //=======================================================================
662 //function : pick
663 //purpose  : 
664 //=======================================================================
665
666 static Standard_Integer pick(Draw_Interpretor& , Standard_Integer n, const char** a)
667 {
668   if (n < 6) return 1;
669   Standard_Integer id;
670   Standard_Integer X,Y,b;
671   Standard_Boolean wait = (n == 6);
672   if (!wait) id = Draw::Atoi(a[1]);
673   dout.Select(id,X,Y,b,wait);
674   Standard_Real z = dout.Zoom(id);
675   gp_Pnt P((Standard_Real)X /z,(Standard_Real)Y /z,0);
676   gp_Trsf T;
677   dout.GetTrsf(id,T);
678   T.Invert();
679   P.Transform(T);
680   Draw::Set(a[1],id);
681   Draw::Set(a[2],P.X());
682   Draw::Set(a[3],P.Y());
683   Draw::Set(a[4],P.Z());
684   Draw::Set(a[5],b);
685   return 0;
686 }
687
688
689 //=======================================================================
690 //function : lastrep
691 //purpose  : 
692 //=======================================================================
693
694 static Standard_Integer lastrep(Draw_Interpretor& di, Standard_Integer n, const char** a)
695 {
696   if (n < 5) return 1;
697
698   Draw::Set(a[1],p_id);
699   if (n == 5) {
700     Draw::Set(a[2],p_X);
701     Draw::Set(a[3],p_Y);
702   }
703   else if (n == 6) {
704     Standard_Real z = dout.Zoom(p_id);
705     gp_Pnt P((Standard_Real)p_X /z,(Standard_Real)p_Y /z,0);
706     gp_Trsf T;
707     dout.GetTrsf(p_id,T);
708     T.Invert();
709     P.Transform(T);
710     Draw::Set(a[2],P.X());
711     Draw::Set(a[3],P.Y());
712     Draw::Set(a[4],P.Z());
713   }
714   else {
715     di << "Too many args";
716     return 1;
717   }
718   Draw::Set(a[n-1],p_b);
719   di << p_Name;
720   return 0;
721 }
722
723
724 //=======================================================================
725 //function : Set
726 //purpose  : 
727 //=======================================================================
728 void Draw::Set(const Standard_CString name, 
729                const Handle(Draw_Drawable3D)& D)
730 {
731  Draw::Set(name,D,autodisp);
732 }
733
734 // MKV 29.03.05
735 static char* tracevar(ClientData CD, Tcl_Interp*,const char* name,const char*, int)
736 {
737   // protect if the map was destroyed before the interpretor
738   if (theVariables.IsEmpty()) return NULL;
739
740   // MSV 9.10.14 CR25344
741   Handle(Draw_Drawable3D) D(reinterpret_cast<Draw_Drawable3D*>(CD));
742   if (D.IsNull()) {
743     Tcl_UntraceVar(theCommands.Interp(),name,TCL_TRACE_UNSETS | TCL_TRACE_WRITES,
744                    tracevar,CD);
745     return NULL;
746   }
747   if (D->Protected()) {
748     D->Name(Tcl_SetVar(theCommands.Interp(),name,name,0));
749     return (char*) "variable is protected";
750   } else {
751     if (D->Visible()) {
752       dout.RemoveDrawable(D);
753       if (D->Is3D()) 
754           repaint3d = Standard_True;
755       else
756           repaint2d = Standard_True;
757     }
758     Tcl_UntraceVar(theCommands.Interp(),name,TCL_TRACE_UNSETS | TCL_TRACE_WRITES,
759                    tracevar,CD);
760     theVariables.Remove(D);
761     return NULL;
762   }
763 }
764
765 //=======================================================================
766 //function : Set
767 //purpose  : 
768 //=======================================================================
769 void Draw::Set(const Standard_CString name, 
770                const Handle(Draw_Drawable3D)& D,
771                const Standard_Boolean displ)
772 {
773   if ((name[0] == '.') && (name[1] == '\0')) {
774     if (!D.IsNull()) {
775       dout.RemoveDrawable(D);
776       if (displ) dout << D;
777     }
778   }
779   else {
780     // Check if the variable with the same name exists
781     ClientData aCD =
782       Tcl_VarTraceInfo(theCommands.Interp(),name,TCL_TRACE_UNSETS | TCL_TRACE_WRITES,
783                        tracevar, NULL);
784     Handle(Draw_Drawable3D) anOldD(reinterpret_cast<Draw_Drawable3D*>(aCD));
785     if (!anOldD.IsNull()) {
786       if (theVariables.Contains(anOldD) && anOldD->Protected()) {
787         cout << "variable is protected" << endl;
788         return;
789       }
790       anOldD.Nullify();
791     }
792
793     Tcl_UnsetVar(theCommands.Interp(),name,0);
794
795     if (!D.IsNull()) {
796       theVariables.Add(D);
797       D->Name(Tcl_SetVar(theCommands.Interp(),name,name,0));
798     
799       // set the trace function
800       Tcl_TraceVar(theCommands.Interp(),name,TCL_TRACE_UNSETS | TCL_TRACE_WRITES,
801                    tracevar,reinterpret_cast<ClientData>(D.operator->()));
802       if (displ) {
803         if (!D->Visible())
804           dout << D;
805       }
806       else if (D->Visible())
807         dout.RemoveDrawable(D);
808     }
809   }
810 }
811 //=======================================================================
812 //function : Set
813 //purpose  : 
814 //=======================================================================
815 void Draw::Set(const Standard_CString Name, const Standard_Real val)
816 {
817   if ((Name[0] == '.') && (Name[1] == '\0')) return;
818   Standard_CString aName = Name;
819   Handle(Draw_Drawable3D) D = Draw::Get(aName,Standard_False);
820   Handle(Draw_Number) N;
821   if (!D.IsNull()) {
822     N = Handle(Draw_Number)::DownCast(D);
823   }
824   if (N.IsNull()) {
825     N = new Draw_Number(val);
826     Draw::Set(aName,N,Standard_False);
827   }
828   else
829     N->Value(val);
830 }
831 //=======================================================================
832 //function : Get
833 //purpose  : 
834 //=======================================================================
835 Handle(Draw_Drawable3D) Draw::Get(Standard_CString& name, 
836                                   const Standard_Boolean )
837 {
838   Standard_Boolean pick = ((name[0] == '.') && (name[1] == '\0'));
839   Handle(Draw_Drawable3D) D;
840   if (pick) {
841     cout << "Pick an object" << endl;
842     dout.Select(p_id,p_X,p_Y,p_b);
843     dout.Pick(p_id,p_X,p_Y,5,D,0);
844     if (!D.IsNull()) {
845       if (D->Name()) {
846         name = p_Name = D->Name();
847         //p_Name = (char *)D->Name();
848       }
849     }
850   }
851   else {
852     ClientData aCD =
853       Tcl_VarTraceInfo(theCommands.Interp(),name,TCL_TRACE_UNSETS | TCL_TRACE_WRITES,
854                        tracevar, NULL);
855     D = reinterpret_cast<Draw_Drawable3D*>(aCD);
856     if (!theVariables.Contains(D))
857       D.Nullify();
858 #if 0
859     if (D.IsNull() && complain)
860       cout <<name<<" does not exist"<<endl;
861 #endif
862   }
863   return D;
864 }
865
866 //=======================================================================
867 //function : Get
868 //purpose  : 
869 //=======================================================================
870 Standard_Boolean Draw::Get(const Standard_CString name, 
871                            Standard_Real& val)
872 {
873   if ((name[0] == '.') && (name[1] == '\0')) {
874     return Standard_False;
875   }
876   Standard_CString aName = name;
877   Handle(Draw_Drawable3D) D = Draw::Get(aName,Standard_False);
878   if (!D.IsNull()) {
879     Handle(Draw_Number) N = Handle(Draw_Number)::DownCast(D);
880     if (!N.IsNull()) {
881       val = N->Value();
882       return Standard_True;
883     }
884   }
885   return Standard_False;
886 }
887
888 //=======================================================================
889 //function : LastPick
890 //purpose  : 
891 //=======================================================================
892 void  Draw::LastPick(Standard_Integer& view, 
893                      Standard_Integer& X, 
894                      Standard_Integer& Y, 
895                      Standard_Integer& button)
896 {
897   view = p_id;
898   X = p_X;
899   Y = p_Y;
900   button = p_b;
901 }
902 //=======================================================================
903 //function : Repaint
904 //purpose  : 
905 //=======================================================================
906 void  Draw::Repaint()
907 {
908   repaint2d = Standard_True;
909   repaint3d = Standard_True;
910 }
911
912 //=======================================================================
913 //function : trigonometric functions
914 //purpose  : 
915 //=======================================================================
916
917 //static Standard_Integer trigo (Draw_Interpretor& di, Standard_Integer n, const char** a)
918 static Standard_Integer trigo (Draw_Interpretor& di, Standard_Integer , const char** a)
919 {
920
921   Standard_Real x = Draw::Atof(a[1]);
922
923   if (!strcasecmp(a[0],"cos"))
924     di << Cos(x);
925   else if (!strcasecmp(a[0],"sin"))
926     di << Sin(x);
927   else if (!strcasecmp(a[0],"tan"))
928     di << Tan(x);
929   else if (!strcasecmp(a[0],"sqrt"))
930     di << Sqrt(x);
931   else if (!strcasecmp(a[0],"acos"))
932     di << ACos(x);
933   else if (!strcasecmp(a[0],"asin"))
934     di << ASin(x);
935   else if (!strcasecmp(a[0],"atan2"))
936     di << ATan2(x,Draw::Atof(a[2]));
937
938   return 0;
939 }
940
941
942 //=======================================================================
943 // Atof and Atoi
944 //=======================================================================
945
946 static Standard_Boolean Numeric(char c)
947 {
948   return (c == '.' || (c >= '0' && c <= '9'));
949 }
950
951 static Standard_Boolean Alphabetic(char c)
952 {
953   return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c == '_'));
954 }
955
956 static Standard_Real Parse(char*&);
957
958 static Standard_Real ParseValue(char*& name)
959 {
960   while (*name == ' ' || *name == '\t') name++;
961   Standard_Real x = 0;
962   switch (*name) {
963
964   case '\0' :
965     break;
966
967   case '(' :
968     name++;
969     x = Parse(name);
970     if (*name != ')') 
971       cout << "Mismatched parenthesis" << endl;
972     name++;
973     break;
974
975   case '+' :
976     name++;
977     x = ParseValue(name);
978     break;
979
980   case '-' :
981     name++;
982     x = - ParseValue(name);
983     break;
984
985     default :
986       {
987         // process a string
988         
989         char* p = name;
990         while (Numeric(*p)) p++;
991         // process scientific notation
992         if ((*p == 'e') || (*p == 'E')) {
993           if (Numeric(*(p+1)) || *(p+1) == '+' || *(p+1) == '-')
994             p+= 2;
995         }
996         while (Numeric(*p) || Alphabetic(*p)) p++;
997         char c = *p;
998         *p = '\0';
999         
1000         if (Numeric(*name))   // numeric litteral
1001           x = Atof(name);
1002         else if (!Draw::Get((Standard_CString) name,x)) {  // variable
1003           
1004           // search for a function ...
1005           *p = c;
1006           // count arguments
1007           Standard_Integer argc = 1;
1008           char* q = p;
1009           while ((*q == ' ') || (*q == '\t')) q++;
1010           if (*q == '(') {
1011             Standard_Integer pc = 1;
1012             argc = 2;
1013             q++;
1014             while ((pc > 0) && *q) {
1015               if (*q == '(') pc++;
1016               if (*q == ')') pc--;
1017               if ((pc == 1) && (*q == ',')) argc++;
1018               q++;
1019             }
1020             if (pc > 0) {
1021               cout << "Unclosed parenthesis"<< endl;
1022               x = 0;
1023             }
1024             else {
1025               // build function call 
1026               // replace , and first and last () by space
1027               if (argc > 1) {
1028                 Standard_Integer i = 2;
1029                 while (*p != '(') p++;
1030                 *p = ' ';
1031                 p++;
1032                 pc = 1;
1033                 while (pc > 0) {
1034                   if (*p == '(') pc++;
1035                   if (*p == ')') pc--;
1036                   if ((pc == 1) && (*p == ',')) {
1037                     *p = ' ';
1038                     p++;
1039                     i++;
1040                   }
1041                   else
1042                     p++;
1043                 }
1044                 *(p-1) = '\0';
1045                 c = *p;
1046
1047                 // call the function, save the current result
1048                 char* sv = 0;
1049                 if (*theCommands.Result()) {
1050                   sv = new char [strlen(theCommands.Result())];
1051                   strcpy(sv,theCommands.Result());
1052                   theCommands.Reset();
1053                 }
1054                 if (theCommands.Eval(name) != 0) {
1055                   cout << "Call of function " << name << " failed" << endl;
1056                   x = 0;
1057                 }
1058                 else
1059                   x = Atof(theCommands.Result());
1060                 theCommands.Reset();
1061                 if (sv) {
1062                   theCommands << sv;
1063                   delete [] sv;
1064                 }
1065               }
1066             }
1067           }
1068           else
1069             Draw_ParseFailed = Standard_True;
1070         }
1071         *p = c;
1072         name = p;
1073       }
1074     break;
1075     
1076   }
1077   while (*name == ' ' || *name == '\t') name++;
1078   return x;
1079 }
1080
1081
1082 static Standard_Real ParseFactor(char*& name)
1083 {
1084   Standard_Real x = ParseValue(name);
1085
1086   for(;;) {
1087     char c = *name;
1088     if (c == '\0') return x;
1089     name++;
1090     switch (c) {
1091
1092     case '*' :
1093       x *= ParseValue(name);
1094       break;
1095
1096     case '/' :
1097       x /= ParseValue(name);
1098       break;
1099
1100       default :
1101         name--;
1102         return x;
1103       
1104     }
1105   }
1106 }
1107
1108 static Standard_Real Parse(char*& name)
1109 {
1110   Standard_Real x = ParseFactor(name);
1111
1112   for(;;) {
1113     char c = *name;
1114     if (c == '\0') return x;
1115     name++;
1116     switch (c) {
1117
1118     case '+' :
1119       x += ParseFactor(name);
1120       break;
1121
1122     case '-' :
1123       x -= ParseFactor(name);
1124       break;
1125
1126       default :
1127         name--;
1128         return x;
1129       
1130     }
1131   }
1132 }
1133 //=======================================================================
1134 //function : Atof
1135 //purpose  : 
1136 //=======================================================================
1137 Standard_Real Draw::Atof(const Standard_CString name)
1138 {
1139   // copy the string
1140   char* n = new char[1+strlen(name)];
1141   char* b = n;
1142   strcpy(n,name);
1143   Standard_Real x = Parse(n);
1144   while ((*n == ' ') || (*n == '\t')) n++;
1145   if (*n) Draw_ParseFailed = Standard_True;
1146   delete [] b;
1147   return x;
1148 }
1149
1150 Standard_Integer Draw::Atoi(const Standard_CString name)
1151 {
1152   return (Standard_Integer ) Draw::Atof(name);
1153 }
1154 //=======================================================================
1155 //function : Set
1156 //purpose  : set a TCL var
1157 //=======================================================================
1158 void Draw::Set(const Standard_CString Name, const Standard_CString val)
1159 {
1160   Standard_PCharacter pName, pVal;
1161   //
1162   pName=(Standard_PCharacter)Name;
1163   pVal=(Standard_PCharacter)val;
1164   //
1165   Tcl_SetVar(theCommands.Interp(), pName, pVal, 0);
1166 }
1167 //=======================================================================
1168 // Command management
1169 // refresh the screen
1170 //=======================================================================
1171
1172 static void before()
1173 {
1174   repaint2d = Standard_False;
1175   repaint3d = Standard_False;
1176 }
1177
1178 void Draw_RepaintNowIfNecessary()
1179 {
1180   if (repaint2d) dout.Repaint2D();
1181   if (repaint3d) dout.Repaint3D();
1182   repaint2d = Standard_False;
1183   repaint3d = Standard_False;
1184 }
1185
1186 static void  after(Standard_Integer)
1187 {
1188   Draw_RepaintNowIfNecessary();
1189 }
1190
1191 extern void (*Draw_BeforeCommand)();
1192 extern void (*Draw_AfterCommand)(Standard_Integer);
1193
1194
1195 //=======================================================================
1196 //function : Commands
1197 //purpose  : 
1198 //=======================================================================
1199 void  Draw::VariableCommands(Draw_Interpretor& theCommandsArg)
1200 {
1201   static Standard_Boolean Done = Standard_False;
1202   if (Done) return;
1203   Done = Standard_True;
1204
1205   // set up start and stop command
1206   Draw_BeforeCommand = &before;
1207   Draw_AfterCommand  = &after;
1208
1209   //  set up some variables
1210
1211   const char* n;
1212   Handle(Draw_Axis3D) theAxes3d = new Draw_Axis3D(gp_Pnt(0,0,0),Draw_bleu,20);
1213   n = "axes";
1214   Draw::Set(n,theAxes3d);
1215   theAxes3d->Protected(Standard_True);
1216
1217   Handle(Draw_Axis2D) theAxes2d = new Draw_Axis2D(gp_Pnt2d(0,0),Draw_bleu,20);
1218   n = "axes2d";
1219   Draw::Set(n,theAxes2d);
1220   theAxes2d->Protected(Standard_True);
1221
1222   n = "pi";
1223   Draw::Set(n,M_PI);
1224   Draw::Get(n)->Protected(Standard_True);
1225
1226   n = "pinf";
1227   Draw::Set(n,RealLast());
1228   Draw::Get(n)->Protected(Standard_True);
1229
1230   n = "minf";
1231   Draw::Set(n,RealFirst());
1232   Draw::Get(n)->Protected(Standard_True);
1233
1234   n = "grid";
1235   Handle(Draw_Grid) theGrid = new Draw_Grid();
1236   Draw::Set(n, theGrid);
1237   theGrid->Protected(Standard_True);
1238   
1239
1240   const char* g;
1241
1242   g = "DRAW Numeric functions";
1243
1244   theCommandsArg.Add("cos" ,"cos(x)" ,__FILE__,trigo,g);
1245   theCommandsArg.Add("sin" ,"sin(x)" ,__FILE__,trigo,g);
1246   theCommandsArg.Add("tan" ,"tan(x)" ,__FILE__,trigo,g);
1247   theCommandsArg.Add("acos" ,"acos(x)" ,__FILE__,trigo,g);
1248   theCommandsArg.Add("asin" ,"asin(x)" ,__FILE__,trigo,g);
1249   theCommandsArg.Add("atan2" ,"atan2(x,y)" ,__FILE__,trigo,g);
1250   theCommandsArg.Add("sqrt","sqrt(x)",__FILE__,trigo,g);
1251
1252   g = "DRAW Variables management";
1253
1254   theCommandsArg.Add("protect","protect name ...",__FILE__,protect,g);
1255   theCommandsArg.Add("unprotect","unprotect name ...",__FILE__,protect,g);
1256
1257   theCommandsArg.Add("bsave","bsave name filename",__FILE__,save,g);
1258   theCommandsArg.Add("brestore","brestore filename name",__FILE__,restore,g);
1259
1260   theCommandsArg.Add("isdraw","isdraw var, return 1 if Draw value",__FILE__,isdraw,g);
1261   theCommandsArg.Add("isprot","isprot var, return 1 if Draw var is protected",__FILE__,isprot,g);
1262   
1263   theCommandsArg.Add("autodisplay","toggle autodisplay [0/1]",__FILE__,autodisplay,g);
1264   theCommandsArg.Add("display","display [name1 name2 ...], no names display all",__FILE__,display,g);
1265   theCommandsArg.Add("donly","donly [name1 name2 ...], erase and display",__FILE__,erase,g);
1266   theCommandsArg.Add("erase","erase [name1 name2 ...], no names erase all",__FILE__,erase,g);
1267   theCommandsArg.Add("draw","draw view mode [name1 name2 ...], draw on view with mode",__FILE__,draw,g);
1268   theCommandsArg.Add("clear","clear display",__FILE__,erase,g);
1269   theCommandsArg.Add("2dclear","clear display (2d objects)",__FILE__,erase,g);
1270   theCommandsArg.Add("repaint","repaint, force redraw",__FILE__,repaintall,g);
1271
1272   theCommandsArg.Add("dtyp", "dtyp name1 name2",__FILE__,whatis,g);
1273   theCommandsArg.Add("dval", "dval name, return value",__FILE__,value,g);
1274   theCommandsArg.Add("dname", "dname name, print name",__FILE__,dname,g);
1275   theCommandsArg.Add("dump", "dump name1 name2 ...",__FILE__,dump,g);
1276   theCommandsArg.Add("copy",  "copy name1 toname1 name2 toname2 ...",__FILE__,copy,g);
1277   // san - 02/08/2002 - `rename` command changed to `renamevar` since it conflicts with 
1278   // the built-in Tcl command `rename`
1279   //theCommands.Add("rename","rename name1 toname1 name2 toname2 ...",__FILE__,copy,g);
1280   theCommandsArg.Add("renamevar","renamevar name1 toname1 name2 toname2 ...",__FILE__,copy,g);
1281   theCommandsArg.Add("dset","var1 value1 vr2 value2 ...",__FILE__,set,g);
1282
1283   // commands to access C environment variables; see Mantis issue #23197
1284   theCommandsArg.Add("dgetenv","var : get value of environment variable in C subsystem",__FILE__,dgetenv,g);
1285   theCommandsArg.Add("dsetenv","var [value] : set (unset if value is empty) environment variable in C subsystem",__FILE__,dsetenv,g);
1286
1287   theCommandsArg.Add("pick","pick id X Y Z b [nowait]",__FILE__,pick,g);
1288   theCommandsArg.Add("lastrep","lastrep id X Y [Z] b, return name",__FILE__,lastrep,g);
1289 }