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