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