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