0023151: Add command line option to DRAWEXE to execute specified command
[occt.git] / src / Draw / Draw.cxx
1 // Created on: 1993-08-13
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25
26 #include <Draw.ixx>
27
28 #if defined(HAVE_TIME_H) || defined(WNT)
29 # include <time.h>
30 #endif
31
32 #include <Draw_Appli.hxx>
33 #include <OSD.hxx>
34 #include <OSD_Timer.hxx>
35
36 #ifdef HAVE_SYS_TIME_H
37 # include <sys/time.h>
38 #endif
39
40 #ifdef HAVE_SYS_TYPES_H
41 # include <sys/types.h>
42 #endif
43
44 #ifdef HAVE_UNISTD_H
45 # include <unistd.h>
46 #endif
47
48 #ifdef HAVE_STRINGS_H
49 # include <strings.h>
50 #endif
51
52
53 #include <Draw_Window.hxx>
54 #include <gp_Pnt2d.hxx>
55
56 #include <Standard_Stream.hxx>
57 #include <Standard_Version.hxx>
58
59 #include <Draw_Drawable3D.hxx>
60 #include <Draw_Interpretor.hxx>
61 #include <Draw_ProgressIndicator.hxx>
62 #include <tcl.h>
63
64 #include <Draw_MapOfFunctions.hxx>
65 #include <OSD_SharedLibrary.hxx>
66 #include <Resource_Manager.hxx>
67 #include <Draw_Failure.hxx>
68 #include <TCollection_AsciiString.hxx>
69 #include <Standard_ErrorHandler.hxx>
70 extern Standard_Boolean Draw_ParseFailed;
71
72 Standard_EXPORT Draw_Viewer dout;
73 Standard_EXPORT Draw_Interpretor theCommands;
74 Standard_EXPORT Standard_Boolean Draw_Batch;
75 Standard_EXPORT Standard_Boolean Draw_Spying = Standard_False;
76 Standard_EXPORT Standard_Boolean Draw_Chrono = Standard_False;
77 Standard_EXPORT Standard_Boolean Draw_VirtualWindows = Standard_False;
78 Standard_EXPORT Standard_Boolean ErrorMessages = Standard_True;
79
80 static const char* ColorNames[MAXCOLOR] = {
81   "White","Red","Green","Blue","Cyan","Gold","Magenta",
82   "Maroon","Orange","Pink","Salmon","Violet","Yellow","Khaki","Coral"
83   };
84
85 filebuf Draw_Spyfile;
86
87 static ostream spystream(&Draw_Spyfile);
88
89 static   Standard_Boolean XLoop;
90
91 static Handle(Draw_ProgressIndicator) PInd = NULL;
92
93 Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
94 // true if complete command
95
96 // *******************************************************************
97 // read an init file
98 // *******************************************************************
99 #ifdef WNT
100 extern console_semaphore_value volatile console_semaphore;
101 extern char console_command[1000];
102 #endif
103
104 static void ReadInitFile (const TCollection_AsciiString& theFileName)
105 {
106   TCollection_AsciiString aPath = theFileName;
107 #ifdef WNT
108   if (!Draw_Batch) {
109     try {
110       aPath.ChangeAll ('\\', '/');
111
112       sprintf(console_command, "source \"%.980s\"", aPath.ToCString());
113       console_semaphore = HAS_CONSOLE_COMMAND;
114       while (console_semaphore == HAS_CONSOLE_COMMAND)
115         Sleep(10);
116     }
117     catch(...) {
118       cout << "Error while reading a script file." << endl;
119       ExitProcess(0);
120     }
121   } else {
122 #endif
123     char* com = new char [aPath.Length() + strlen ("source ") + 2];
124     sprintf (com, "source %s", aPath.ToCString());
125     Draw_Interprete (com);
126     delete [] com;
127 #ifdef WNT
128   }
129 #endif
130 }
131
132 //=======================================================================
133 //function :
134 //purpose  : Set/Get Progress Indicator
135 //=======================================================================
136 void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& thePI)
137 {
138   PInd = thePI;
139 }
140
141 Handle(Draw_ProgressIndicator) Draw::GetProgressBar()
142 {
143   return PInd;
144 }
145
146 #ifndef WNT
147 /*--------------------------------------------------------*\
148 |  exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
149 \*--------------------------------------------------------*/
150 void exitProc(ClientData /*dc*/)
151 {
152   if (!Draw_Batch) {
153     for (Standard_Integer id = 0; id < MAXVIEW; id++)
154       dout.DeleteView(id);
155   }
156 }
157 #endif
158
159 // *******************************************************************
160 // main
161 // *******************************************************************
162 #ifdef WNT
163 //Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lps
164 Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszLine, int nShow,const FDraw_InitAppli Draw_InitAppli)
165 #else
166 void Draw_Appli(Standard_Integer argc, char** argv,const FDraw_InitAppli Draw_InitAppli)
167 #endif
168 {
169   // *****************************************************************
170   // analyze arguments
171   // *****************************************************************
172   Draw_Batch = Standard_False;
173   TCollection_AsciiString aRunFile, aCommand;
174   Standard_Integer i;
175   Standard_Boolean isInteractiveForced = Standard_False;
176
177 #ifdef WNT
178   // On NT command line arguments are in the lpzline and not in argv
179   int argc = 0;
180   const int MAXARGS = 1024;
181   const char* argv[MAXARGS];
182   for (const char* p = strtok(lpszLine, " \t"); p != NULL; p = strtok(NULL, " \t")) {
183     argv[argc++] = p;
184   }
185 #endif
186
187   // parse command line
188   for (i = 1; i < argc; i++) {
189     if (strcasecmp (argv[i], "-h") == 0 || strcasecmp (argv[i], "--help") == 0)
190     {
191       cout << "Open CASCADE " << OCC_VERSION_STRING_EXT << " DRAW Test Harness" << endl << endl;
192       cout << "Options: " << endl;
193       cout << "  -b: batch mode (no GUI, no viewers)" << endl;
194       cout << "  -v: no GUI, use virtual (off-screen) windows for viewers" << endl;
195       cout << "  -i: interactive mode" << endl;
196       cout << "  -f file: execute script from file" << endl;
197       cout << "  -c command args...: execute command (with optional arguments)" << endl << endl;
198       cout << "Options -b, -v, and -i are mutually exclusive." << endl;
199       cout << "If -c or -f are given, -v is default; otherwise default is -i." << endl;
200       cout << "Options -c and -f are alternatives and should be at the end " << endl;
201       cout << "of the command line. " << endl;
202       cout << "Option -c can accept set of commands separated by ';'." << endl;
203       return;
204     }
205     else if (strcasecmp (argv[i], "-b") == 0)
206       Draw_Batch = Standard_True;
207     else if (strcasecmp (argv[i], "-v") == 0) {
208       // force virtual windows
209       Draw_VirtualWindows = Standard_True;
210     } else if (strcasecmp (argv[i], "-i") == 0) {
211       // force interactive
212       Draw_VirtualWindows = Standard_False;
213       isInteractiveForced = Standard_True;
214     } else if (strcasecmp (argv[i], "-f") == 0) { // -f option should be LAST!
215       Draw_VirtualWindows = !isInteractiveForced;
216       if (++i < argc) {
217         aRunFile = TCollection_AsciiString (argv[i]);
218       }
219       break;
220     } else if (strcasecmp (argv[i], "-c") == 0) { // -c option should be LAST!
221       Draw_VirtualWindows = !isInteractiveForced;
222       if (++i < argc) {
223         aCommand = TCollection_AsciiString (argv[i]);
224       }
225       while (++i < argc) {
226         aCommand.AssignCat (" ");
227         aCommand.AssignCat (argv[i]);
228       }
229       break;
230     } else {
231       cout << "Error: unsupported option " << argv[i] << endl;
232     }
233   }
234
235   // *****************************************************************
236   // set signals
237   // *****************************************************************
238   OSD::SetSignal();
239
240 #ifdef _WIN32
241   // in interactive mode, force Windows to report dll loading problems interactively
242   if ( ! Draw_VirtualWindows && ! Draw_Batch )
243     ::SetErrorMode (0);
244 #endif
245
246   // *****************************************************************
247   // init X window and create display
248   // *****************************************************************
249 #ifdef WNT
250   HWND hWnd;
251 #endif
252
253   if (!Draw_Batch)
254 #ifdef WNT
255     Draw_Batch=!Init_Appli(hInst, hPrevInst, nShow, hWnd);
256 #else
257     Draw_Batch=!Init_Appli();
258 #endif
259   else
260     cout << "DRAW is running in batch mode" << endl;
261
262   XLoop = !Draw_Batch;
263   if (XLoop) {
264     // Default colors
265     for (i=0;i<MAXCOLOR;i++) {
266       if (!dout.DefineColor(i,ColorNames[i]))
267         cout <<"Could not allocate default color "<<ColorNames[i]<<endl;
268     }
269   }
270
271   // *****************************************************************
272   // set maximum precision for cout
273   // *****************************************************************
274   cout.precision(15);
275
276   // *****************************************************************
277   // standard commands
278   // *****************************************************************
279   Draw::BasicCommands(theCommands);
280   Draw::VariableCommands(theCommands);
281   Draw::UnitCommands(theCommands);
282   if (!Draw_Batch) Draw::GraphicCommands(theCommands);
283
284   // *****************************************************************
285   // user commands
286   // *****************************************************************
287   Draw_InitAppli(theCommands);
288
289 #ifndef WNT
290   Tcl_CreateExitHandler(exitProc, 0);
291 #endif
292
293   // *****************************************************************
294   // read init files
295   // *****************************************************************
296   // default
297
298   if (getenv ("DRAWDEFAULT") == NULL)
299   {
300     if (getenv ("CASROOT") == NULL)
301     {
302 #ifdef WNT
303       ReadInitFile ("ddefault");
304 #else
305       cout << " the CASROOT variable is mandatory to Run OpenCascade "<< endl;
306       cout << "No default file" << endl;
307 #endif
308     }
309     else
310     {
311       TCollection_AsciiString aDefStr (getenv ("CASROOT"));
312       aDefStr += "/src/DrawResources/DrawDefault";
313       ReadInitFile (aDefStr);
314     }
315   }
316   else
317   {
318     ReadInitFile (getenv ("DRAWDEFAULT"));
319   }
320
321   // read commands from file
322   if (!aRunFile.IsEmpty()) {
323     ReadInitFile (aRunFile);
324     // provide a clean exit, this is useful for some analysis tools
325     if ( ! isInteractiveForced )
326 #ifndef WNT
327       return;
328 #else
329       ExitProcess(0);
330 #endif
331   }
332
333   // execute command from command line
334   if (!aCommand.IsEmpty()) {
335     Draw_Interprete (aCommand.ToCString());
336     // provide a clean exit, this is useful for some analysis tools
337     if ( ! isInteractiveForced )
338 #ifndef WNT
339       return;
340 #else
341       ExitProcess(0);
342 #endif
343   }
344
345   // *****************************************************************
346   // X loop
347   // *****************************************************************
348   if (XLoop) {
349 #ifdef WNT
350     Run_Appli(hWnd);
351 #else
352     Run_Appli(Draw_Interprete);
353 #endif
354   }
355   else
356   {
357     char cmd[255];
358     do {
359       cout << "Viewer>";
360       i = -1;
361       do {
362         cin.get(cmd[++i]);
363       } while ((cmd[i] != '\n') && (!cin.fail()));
364       cmd[i] = '\0';
365     } while (Draw_Interprete(cmd) != (unsigned int ) -2);
366   }
367 #ifdef WNT
368   // Destruction de l'application
369   Destroy_Appli(hInst);
370 #endif
371 }
372 //#endif
373
374 // User functions called before and after each command
375 void (*Draw_BeforeCommand)() = NULL;
376 void (*Draw_AfterCommand)(Standard_Integer) = NULL;
377
378 Standard_Boolean Draw_Interprete(const char* com)
379 {
380
381   static Standard_Boolean first = Standard_True;
382   static Tcl_DString command;
383
384   if (first) {
385     first = Standard_False;
386     Tcl_DStringInit(&command);
387   }
388
389 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)))
390   // OCC63: Since Tcl 8.1 it uses UTF-8 encoding for internal representation of strings
391   Tcl_ExternalToUtfDString ( NULL, com, -1, &command );
392 #else
393   Tcl_DStringAppend(&command,com,-1);
394 #endif
395
396   if (!theCommands.Complete(Tcl_DStringValue(&command)))
397     return Standard_False;
398
399   // *******************************************************************
400   // Command interpreter
401   // *******************************************************************
402
403 //  Standard_Integer i = 0;
404 //  Standard_Integer j = 0;
405
406   Standard_Boolean wasspying = Draw_Spying;
407
408   OSD_Timer tictac;
409   Standard_Boolean hadchrono = Draw_Chrono;
410   if (hadchrono) tictac.Start();
411
412   if (Draw_BeforeCommand) (*Draw_BeforeCommand) ();
413
414   Standard_Integer c;
415
416   c = theCommands.RecordAndEval(Tcl_DStringValue(&command));
417
418   if (Draw_AfterCommand) (*Draw_AfterCommand)(c);
419
420   if (wasspying && Draw_Spying) {
421     if (c > 0) spystream << "# ";
422     spystream << Tcl_DStringValue(&command) << "\n";
423   }
424
425   dout.Flush();
426
427   if (*theCommands.Result())
428     cout << theCommands.Result() << endl;
429
430   if (Draw_Chrono && hadchrono) {
431     tictac.Stop();
432     tictac.Show();
433   }
434
435   Tcl_DStringFree(&command);
436
437   return Standard_True;
438 }
439
440 //
441 // for TCl
442 //
443
444 Standard_Integer Tcl_AppInit (Tcl_Interp *)
445 {
446   return 0;
447 }
448
449 //
450 // for debug call
451 //
452
453
454
455 Standard_Integer  Draw_Call (char *c)
456 {
457    Standard_Integer r = theCommands.Eval(c);
458    cout << theCommands.Result() << endl;
459    return r;
460 }
461
462
463 //=================================================================================
464 //
465 //=================================================================================
466 void Draw::Load(Draw_Interpretor& theDI, const TCollection_AsciiString& theKey,
467                  const TCollection_AsciiString& theResourceFileName) {
468
469   static Draw_MapOfFunctions theMapOfFunctions;
470   OSD_Function f;
471
472   if(!theMapOfFunctions.IsBound(theKey)) {
473
474     Handle(Resource_Manager) aPluginResource = new Resource_Manager(theResourceFileName.ToCString());
475     if(!aPluginResource->Find(theKey.ToCString())) {
476       Standard_SStream aMsg; aMsg << "Could not find the resource:";
477       aMsg << theKey.ToCString()<< endl;
478       cout << "could not find the resource:"<<theKey.ToCString()<< endl;
479       Draw_Failure::Raise(aMsg);
480     }
481
482     TCollection_AsciiString aPluginLibrary("");
483 #ifndef WNT
484     aPluginLibrary += "lib";
485 #endif
486     aPluginLibrary +=  aPluginResource->Value(theKey.ToCString());
487 #ifdef WNT
488     aPluginLibrary += ".dll";
489 #elif __APPLE__
490     aPluginLibrary += ".dylib";
491 #elif defined (HPUX) || defined(_hpux)
492     aPluginLibrary += ".sl";
493 #else
494     aPluginLibrary += ".so";
495 #endif
496     OSD_SharedLibrary aSharedLibrary(aPluginLibrary.ToCString());
497     if(!aSharedLibrary.DlOpen(OSD_RTLD_LAZY)) {
498       TCollection_AsciiString error(aSharedLibrary.DlError());
499       Standard_SStream aMsg; aMsg << "Could not open: ";
500       aMsg << aPluginResource->Value(theKey.ToCString());
501       aMsg << "; reason: ";
502       aMsg << error.ToCString();
503 #ifdef DEB
504       cout << "could not open: "  << aPluginResource->Value(theKey.ToCString())<< " ; reason: "<< error.ToCString() << endl;
505 #endif
506       Draw_Failure::Raise(aMsg);
507     }
508     f = aSharedLibrary.DlSymb("PLUGINFACTORY");
509     if( f == NULL ) {
510       TCollection_AsciiString error(aSharedLibrary.DlError());
511       Standard_SStream aMsg; aMsg << "Could not find the factory in: ";
512       aMsg << aPluginResource->Value(theKey.ToCString());
513       aMsg << error.ToCString();
514       Draw_Failure::Raise(aMsg);
515     }
516     theMapOfFunctions.Bind(theKey, f);
517   }
518   else
519     f = theMapOfFunctions(theKey);
520
521 //   void (*fp) (Draw_Interpretor&, const TCollection_AsciiString&) = NULL;
522 //   fp = (void (*)(Draw_Interpretor&, const TCollection_AsciiString&)) f;
523 //   (*fp) (theDI, theKey);
524
525   void (*fp) (Draw_Interpretor&) = NULL;
526   fp = (void (*)(Draw_Interpretor&)) f;
527   (*fp) (theDI);
528
529 }
530
531
532 //=================================================================================
533 //
534 //=================================================================================
535 void Draw::Load(Draw_Interpretor& theDI, const TCollection_AsciiString& theKey,
536                 const TCollection_AsciiString& theResourceFileName,
537                 TCollection_AsciiString& theDefaultsDirectory,
538                 TCollection_AsciiString& theUserDefaultsDirectory,
539                 const Standard_Boolean Verbose ) {
540
541   static Draw_MapOfFunctions theMapOfFunctions;
542   OSD_Function f;
543
544   if(!theMapOfFunctions.IsBound(theKey)) {
545
546     Handle(Resource_Manager) aPluginResource = new Resource_Manager(theResourceFileName.ToCString(), theDefaultsDirectory, theUserDefaultsDirectory, Verbose);
547
548     if(!aPluginResource->Find(theKey.ToCString())) {
549       Standard_SStream aMsg; aMsg << "Could not find the resource:";
550       aMsg << theKey.ToCString()<< endl;
551       cout << "could not find the resource:"<<theKey.ToCString()<< endl;
552       Draw_Failure::Raise(aMsg);
553     }
554
555     TCollection_AsciiString aPluginLibrary("");
556 #ifndef WNT
557     aPluginLibrary += "lib";
558 #endif
559     aPluginLibrary +=  aPluginResource->Value(theKey.ToCString());
560 #ifdef WNT
561     aPluginLibrary += ".dll";
562 #elif __APPLE__
563     aPluginLibrary += ".dylib";
564 #elif defined (HPUX) || defined(_hpux)
565     aPluginLibrary += ".sl";
566 #else
567     aPluginLibrary += ".so";
568 #endif
569     OSD_SharedLibrary aSharedLibrary(aPluginLibrary.ToCString());
570     if(!aSharedLibrary.DlOpen(OSD_RTLD_LAZY)) {
571       TCollection_AsciiString error(aSharedLibrary.DlError());
572       Standard_SStream aMsg; aMsg << "Could not open: ";
573       aMsg << aPluginResource->Value(theKey.ToCString());
574       aMsg << "; reason: ";
575       aMsg << error.ToCString();
576 #ifdef DEB
577       cout << "could not open: "  << aPluginResource->Value(theKey.ToCString())<< " ; reason: "<< error.ToCString() << endl;
578 #endif
579       Draw_Failure::Raise(aMsg);
580     }
581     f = aSharedLibrary.DlSymb("PLUGINFACTORY");
582     if( f == NULL ) {
583       TCollection_AsciiString error(aSharedLibrary.DlError());
584       Standard_SStream aMsg; aMsg << "Could not find the factory in: ";
585       aMsg << aPluginResource->Value(theKey.ToCString());
586       aMsg << error.ToCString();
587       Draw_Failure::Raise(aMsg);
588     }
589     theMapOfFunctions.Bind(theKey, f);
590   }
591   else
592     f = theMapOfFunctions(theKey);
593
594 //   void (*fp) (Draw_Interpretor&, const TCollection_AsciiString&) = NULL;
595 //   fp = (void (*)(Draw_Interpretor&, const TCollection_AsciiString&)) f;
596 //   (*fp) (theDI, theKey);
597
598   void (*fp) (Draw_Interpretor&) = NULL;
599   fp = (void (*)(Draw_Interpretor&)) f;
600   (*fp) (theDI);
601
602 }