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