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