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