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