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