0020716: Eliminate usage of "config.h" header file
[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-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Draw.ixx>
18
19 #include <Draw_Appli.hxx>
20 #include <OSD.hxx>
21 #include <OSD_Environment.hxx>
22 #include <OSD_Timer.hxx>
23
24 #include <Draw_Window.hxx>
25 #include <gp_Pnt2d.hxx>
26
27 #include <Standard_Stream.hxx>
28 #include <Standard_Version.hxx>
29
30 #include <Draw_Drawable3D.hxx>
31 #include <Draw_Interpretor.hxx>
32 #include <Draw_ProgressIndicator.hxx>
33
34 #include <Plugin_MapOfFunctions.hxx>
35 #include <OSD_SharedLibrary.hxx>
36 #include <Resource_Manager.hxx>
37 #include <Draw_Failure.hxx>
38 #include <TCollection_AsciiString.hxx>
39 #include <Standard_ErrorHandler.hxx>
40
41 #include <tcl.h>
42
43 // on MSVC, use #pragma to define name of the Tcl library to link with,
44 // depending on Tcl version number
45 #ifdef _MSC_VER
46 // two helper macros are needed to convert version number macro to string literal
47 #define STRINGIZE1(a) #a
48 #define STRINGIZE2(a) STRINGIZE1(a)
49 #pragma comment (lib, "tcl" STRINGIZE2(TCL_MAJOR_VERSION) STRINGIZE2(TCL_MINOR_VERSION) ".lib")
50 #pragma comment (lib, "tk"  STRINGIZE2(TCL_MAJOR_VERSION) STRINGIZE2(TCL_MINOR_VERSION) ".lib")
51 #undef STRINGIZE2
52 #undef STRINGIZE1
53 #endif
54
55 extern Standard_Boolean Draw_ParseFailed;
56
57 Standard_EXPORT Draw_Viewer dout;
58 Standard_EXPORT Draw_Interpretor theCommands;
59 Standard_EXPORT Standard_Boolean Draw_Batch;
60 Standard_EXPORT Standard_Boolean Draw_Spying = Standard_False;
61 Standard_EXPORT Standard_Boolean Draw_Chrono = Standard_False;
62 Standard_EXPORT Standard_Boolean Draw_VirtualWindows = Standard_False;
63 Standard_EXPORT Standard_Boolean ErrorMessages = Standard_True;
64
65 static const char* ColorNames[MAXCOLOR] = {
66   "White","Red","Green","Blue","Cyan","Gold","Magenta",
67   "Maroon","Orange","Pink","Salmon","Violet","Yellow","Khaki","Coral"
68   };
69
70 filebuf Draw_Spyfile;
71
72 static ostream spystream(&Draw_Spyfile);
73
74 static   Standard_Boolean XLoop;
75
76 static Handle(Draw_ProgressIndicator) PInd = NULL;
77
78 Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
79 // true if complete command
80
81 // *******************************************************************
82 // read an init file
83 // *******************************************************************
84 #ifdef WNT
85 extern console_semaphore_value volatile console_semaphore;
86 extern char console_command[1000];
87 #endif
88
89 static void ReadInitFile (const TCollection_AsciiString& theFileName)
90 {
91   TCollection_AsciiString aPath = theFileName;
92 #ifdef WNT
93   if (!Draw_Batch) {
94     try {
95       aPath.ChangeAll ('\\', '/');
96
97       Sprintf(console_command, "source \"%.980s\"", aPath.ToCString());
98       console_semaphore = HAS_CONSOLE_COMMAND;
99       while (console_semaphore == HAS_CONSOLE_COMMAND)
100         Sleep(10);
101     }
102     catch(...) {
103       cout << "Error while reading a script file." << endl;
104       ExitProcess(0);
105     }
106   } else {
107 #endif
108     char* com = new char [aPath.Length() + strlen ("source ") + 2];
109     Sprintf (com, "source %s", aPath.ToCString());
110     Draw_Interprete (com);
111     delete [] com;
112 #ifdef WNT
113   }
114 #endif
115 }
116
117 //=======================================================================
118 //function :
119 //purpose  : Set/Get Progress Indicator
120 //=======================================================================
121 void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& thePI)
122 {
123   PInd = thePI;
124 }
125
126 Handle(Draw_ProgressIndicator) Draw::GetProgressBar()
127 {
128   return PInd;
129 }
130
131 #ifndef WNT
132 /*--------------------------------------------------------*\
133 |  exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
134 \*--------------------------------------------------------*/
135 void exitProc(ClientData /*dc*/)
136 {
137   if (!Draw_Batch) {
138     for (Standard_Integer id = 0; id < MAXVIEW; id++)
139       dout.DeleteView(id);
140   }
141 }
142 #endif
143
144 // *******************************************************************
145 // main
146 // *******************************************************************
147 #ifdef _WIN32
148 //Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lps
149 Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszLine, int nShow,const FDraw_InitAppli Draw_InitAppli)
150 #else
151 void Draw_Appli(Standard_Integer argc, char** argv,const FDraw_InitAppli Draw_InitAppli)
152 #endif
153 {
154
155 // prepend extra DLL search path to override system libraries like opengl32.dll
156 #ifdef _WIN32
157   OSD_Environment aUserDllEnv ("CSF_UserDllPath");
158   TCollection_AsciiString aUserDllPath = aUserDllEnv.Value();
159   if (!aUserDllPath.IsEmpty())
160   {
161     // This function available since Win XP SP1 #if (_WIN32_WINNT >= 0x0502).
162     // We retrieve dynamically here (kernel32 should be always preloaded).
163     typedef BOOL (WINAPI *SetDllDirectoryA_t)(const char* thePathName);
164     HMODULE aKern32Module = GetModuleHandleA ("kernel32");
165     SetDllDirectoryA_t aFunc = (aKern32Module != NULL)
166                              ? (SetDllDirectoryA_t )GetProcAddress (aKern32Module, "SetDllDirectoryA") : NULL;
167     if (aFunc != NULL)
168     {
169       aFunc (aUserDllPath.ToCString());
170     }
171     else
172     {
173       //std::cerr << "SetDllDirectoryA() is not available on this system!\n";
174     }
175     if (aKern32Module != NULL)
176     {
177       FreeLibrary (aKern32Module);
178     }
179   }
180 #endif
181
182   // *****************************************************************
183   // analyze arguments
184   // *****************************************************************
185   Draw_Batch = Standard_False;
186   TCollection_AsciiString aRunFile, aCommand;
187   Standard_Integer i;
188   Standard_Boolean isInteractiveForced = Standard_False;
189
190 #ifdef _WIN32
191   // On NT command line arguments are in the lpzline and not in argv
192   int argc = 0;
193   const int MAXARGS = 1024;
194   const char* argv[MAXARGS];
195   for (const char* p = strtok(lpszLine, " \t"); p != NULL; p = strtok(NULL, " \t")) {
196     argv[argc++] = p;
197   }
198 #endif
199
200   // parse command line
201   for (i = 1; i < argc; i++) {
202     if (strcasecmp (argv[i], "-h") == 0 || strcasecmp (argv[i], "--help") == 0)
203     {
204       cout << "Open CASCADE " << OCC_VERSION_STRING_EXT << " DRAW Test Harness" << endl << endl;
205       cout << "Options: " << endl;
206       cout << "  -b: batch mode (no GUI, no viewers)" << endl;
207       cout << "  -v: no GUI, use virtual (off-screen) windows for viewers" << endl;
208       cout << "  -i: interactive mode" << endl;
209       cout << "  -f file: execute script from file" << endl;
210       cout << "  -c command args...: execute command (with optional arguments)" << endl << endl;
211       cout << "Options -b, -v, and -i are mutually exclusive." << endl;
212       cout << "If -c or -f are given, -v is default; otherwise default is -i." << endl;
213       cout << "Options -c and -f are alternatives and should be at the end " << endl;
214       cout << "of the command line. " << endl;
215       cout << "Option -c can accept set of commands separated by ';'." << endl;
216       return;
217     }
218     else if (strcasecmp (argv[i], "-b") == 0)
219       Draw_Batch = Standard_True;
220     else if (strcasecmp (argv[i], "-v") == 0) {
221       // force virtual windows
222       Draw_VirtualWindows = Standard_True;
223     } else if (strcasecmp (argv[i], "-i") == 0) {
224       // force interactive
225       Draw_VirtualWindows = Standard_False;
226       isInteractiveForced = Standard_True;
227     } else if (strcasecmp (argv[i], "-f") == 0) { // -f option should be LAST!
228       Draw_VirtualWindows = !isInteractiveForced;
229       if (++i < argc) {
230         aRunFile = TCollection_AsciiString (argv[i]);
231       }
232       break;
233     } else if (strcasecmp (argv[i], "-c") == 0) { // -c option should be LAST!
234       Draw_VirtualWindows = !isInteractiveForced;
235       if (++i < argc) {
236         aCommand = TCollection_AsciiString (argv[i]);
237       }
238       while (++i < argc) {
239         aCommand.AssignCat (" ");
240         aCommand.AssignCat (argv[i]);
241       }
242       break;
243     } else {
244       cout << "Error: unsupported option " << argv[i] << endl;
245     }
246   }
247
248   // *****************************************************************
249   // set signals
250   // *****************************************************************
251   OSD::SetSignal();
252
253 #ifdef _WIN32
254   // in interactive mode, force Windows to report dll loading problems interactively
255   if ( ! Draw_VirtualWindows && ! Draw_Batch )
256     ::SetErrorMode (0);
257 #endif
258
259   // *****************************************************************
260   // init X window and create display
261   // *****************************************************************
262 #ifdef WNT
263   HWND hWnd = NULL;
264 #endif
265
266   if (!Draw_Batch)
267 #ifdef WNT
268     Draw_Batch=!Init_Appli(hInst, hPrevInst, nShow, hWnd);
269 #else
270     Draw_Batch=!Init_Appli();
271 #endif
272   else
273     cout << "DRAW is running in batch mode" << endl;
274
275   XLoop = !Draw_Batch;
276   if (XLoop) {
277     // Default colors
278     for (i=0;i<MAXCOLOR;i++) {
279       if (!dout.DefineColor(i,ColorNames[i]))
280         cout <<"Could not allocate default color "<<ColorNames[i]<<endl;
281     }
282   }
283
284   // *****************************************************************
285   // set maximum precision for cout
286   // *****************************************************************
287   cout.precision(15);
288
289   // *****************************************************************
290   // standard commands
291   // *****************************************************************
292   Draw::BasicCommands(theCommands);
293   Draw::VariableCommands(theCommands);
294   Draw::UnitCommands(theCommands);
295   if (!Draw_Batch) Draw::GraphicCommands(theCommands);
296
297   // *****************************************************************
298   // user commands
299   // *****************************************************************
300   Draw_InitAppli(theCommands);
301
302 #ifndef WNT
303   Tcl_CreateExitHandler(exitProc, 0);
304 #endif
305
306   // *****************************************************************
307   // read init files
308   // *****************************************************************
309   // default
310
311   if (getenv ("DRAWDEFAULT") == NULL)
312   {
313     if (getenv ("CASROOT") == NULL)
314     {
315 #ifdef WNT
316       ReadInitFile ("ddefault");
317 #else
318       cout << " the CASROOT variable is mandatory to Run OpenCascade "<< endl;
319       cout << "No default file" << endl;
320 #endif
321     }
322     else
323     {
324       TCollection_AsciiString aDefStr (getenv ("CASROOT"));
325       aDefStr += "/src/DrawResources/DrawDefault";
326       ReadInitFile (aDefStr);
327     }
328   }
329   else
330   {
331     ReadInitFile (getenv ("DRAWDEFAULT"));
332   }
333
334   // read commands from file
335   if (!aRunFile.IsEmpty()) {
336     ReadInitFile (aRunFile);
337     // provide a clean exit, this is useful for some analysis tools
338     if ( ! isInteractiveForced )
339 #ifndef WNT
340       return;
341 #else
342       ExitProcess(0);
343 #endif
344   }
345
346   // execute command from command line
347   if (!aCommand.IsEmpty()) {
348     Draw_Interprete (aCommand.ToCString());
349     // provide a clean exit, this is useful for some analysis tools
350     if ( ! isInteractiveForced )
351 #ifndef WNT
352       return;
353 #else
354       ExitProcess(0);
355 #endif
356   }
357
358   // *****************************************************************
359   // X loop
360   // *****************************************************************
361   if (XLoop) {
362 #ifdef WNT
363     Run_Appli(hWnd);
364 #else
365     Run_Appli(Draw_Interprete);
366 #endif
367   }
368   else
369   {
370     char cmd[255];
371     do {
372       cout << "Viewer>";
373       i = -1;
374       do {
375         cin.get(cmd[++i]);
376       } while ((cmd[i] != '\n') && (!cin.fail()));
377       cmd[i] = '\0';
378     } while (Draw_Interprete(cmd) != (unsigned int ) -2);
379   }
380 #ifdef WNT
381   // Destruction de l'application
382   Destroy_Appli(hInst);
383 #endif
384 }
385 //#endif
386
387 // User functions called before and after each command
388 void (*Draw_BeforeCommand)() = NULL;
389 void (*Draw_AfterCommand)(Standard_Integer) = NULL;
390
391 Standard_Boolean Draw_Interprete(const char* com)
392 {
393
394   static Standard_Boolean first = Standard_True;
395   static Tcl_DString command;
396
397   if (first) {
398     first = Standard_False;
399     Tcl_DStringInit(&command);
400   }
401
402 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)))
403   // OCC63: Since Tcl 8.1 it uses UTF-8 encoding for internal representation of strings
404   Tcl_ExternalToUtfDString ( NULL, com, -1, &command );
405 #else
406   Tcl_DStringAppend(&command,com,-1);
407 #endif
408
409   if (!theCommands.Complete(Tcl_DStringValue(&command)))
410     return Standard_False;
411
412   // *******************************************************************
413   // Command interpreter
414   // *******************************************************************
415
416 //  Standard_Integer i = 0;
417 //  Standard_Integer j = 0;
418
419   Standard_Boolean wasspying = Draw_Spying;
420
421   OSD_Timer tictac;
422   Standard_Boolean hadchrono = Draw_Chrono;
423   if (hadchrono) tictac.Start();
424
425   if (Draw_BeforeCommand) (*Draw_BeforeCommand) ();
426
427   Standard_Integer c;
428
429   c = theCommands.RecordAndEval(Tcl_DStringValue(&command));
430
431   if (Draw_AfterCommand) (*Draw_AfterCommand)(c);
432
433   if (wasspying && Draw_Spying) {
434     if (c > 0) spystream << "# ";
435     spystream << Tcl_DStringValue(&command) << "\n";
436   }
437
438   dout.Flush();
439
440   if (*theCommands.Result())
441     cout << theCommands.Result() << endl;
442
443   if (Draw_Chrono && hadchrono) {
444     tictac.Stop();
445     tictac.Show();
446   }
447
448   Tcl_DStringFree(&command);
449
450   return Standard_True;
451 }
452
453 //
454 // for TCl
455 //
456
457 Standard_Integer Tcl_AppInit (Tcl_Interp *)
458 {
459   return 0;
460 }
461
462 //
463 // for debug call
464 //
465
466
467
468 Standard_Integer  Draw_Call (char *c)
469 {
470    Standard_Integer r = theCommands.Eval(c);
471    cout << theCommands.Result() << endl;
472    return r;
473 }
474
475 //=================================================================================
476 //
477 //=================================================================================
478 void Draw::Load(Draw_Interpretor& theDI, const TCollection_AsciiString& theKey,
479                 const TCollection_AsciiString& theResourceFileName,
480                 TCollection_AsciiString& theDefaultsDirectory,
481                 TCollection_AsciiString& theUserDefaultsDirectory,
482                 const Standard_Boolean Verbose ) {
483
484   static Plugin_MapOfFunctions theMapOfFunctions;
485   OSD_Function f;
486
487   if(!theMapOfFunctions.IsBound(theKey)) {
488
489     Handle(Resource_Manager) aPluginResource = new Resource_Manager(theResourceFileName.ToCString(), theDefaultsDirectory, theUserDefaultsDirectory, Verbose);
490
491     if(!aPluginResource->Find(theKey.ToCString())) {
492       Standard_SStream aMsg; aMsg << "Could not find the resource:";
493       aMsg << theKey.ToCString()<< endl;
494       cout << "could not find the resource:"<<theKey.ToCString()<< endl;
495       Draw_Failure::Raise(aMsg);
496     }
497
498     TCollection_AsciiString aPluginLibrary("");
499 #ifndef WNT
500     aPluginLibrary += "lib";
501 #endif
502     aPluginLibrary +=  aPluginResource->Value(theKey.ToCString());
503 #ifdef WNT
504     aPluginLibrary += ".dll";
505 #elif __APPLE__
506     aPluginLibrary += ".dylib";
507 #elif defined (HPUX) || defined(_hpux)
508     aPluginLibrary += ".sl";
509 #else
510     aPluginLibrary += ".so";
511 #endif
512     OSD_SharedLibrary aSharedLibrary(aPluginLibrary.ToCString());
513     if(!aSharedLibrary.DlOpen(OSD_RTLD_LAZY)) {
514       TCollection_AsciiString error(aSharedLibrary.DlError());
515       Standard_SStream aMsg; aMsg << "Could not open: ";
516       aMsg << aPluginResource->Value(theKey.ToCString());
517       aMsg << "; reason: ";
518       aMsg << error.ToCString();
519 #ifdef DEB
520       cout << "could not open: "  << aPluginResource->Value(theKey.ToCString())<< " ; reason: "<< error.ToCString() << endl;
521 #endif
522       Draw_Failure::Raise(aMsg);
523     }
524     f = aSharedLibrary.DlSymb("PLUGINFACTORY");
525     if( f == NULL ) {
526       TCollection_AsciiString error(aSharedLibrary.DlError());
527       Standard_SStream aMsg; aMsg << "Could not find the factory in: ";
528       aMsg << aPluginResource->Value(theKey.ToCString());
529       aMsg << error.ToCString();
530       Draw_Failure::Raise(aMsg);
531     }
532     theMapOfFunctions.Bind(theKey, f);
533   }
534   else
535     f = theMapOfFunctions(theKey);
536
537 //   void (*fp) (Draw_Interpretor&, const TCollection_AsciiString&) = NULL;
538 //   fp = (void (*)(Draw_Interpretor&, const TCollection_AsciiString&)) f;
539 //   (*fp) (theDI, theKey);
540
541   void (*fp) (Draw_Interpretor&) = NULL;
542   fp = (void (*)(Draw_Interpretor&)) f;
543   (*fp) (theDI);
544
545 }