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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <Draw_Appli.hxx>
20 #include <Draw_Drawable3D.hxx>
21 #include <Draw_Failure.hxx>
22 #include <Draw_Interpretor.hxx>
23 #include <Draw_ProgressIndicator.hxx>
24 #include <Draw_Window.hxx>
25 #include <gp_Pnt2d.hxx>
27 #include <OSD_Environment.hxx>
28 #include <OSD_SharedLibrary.hxx>
29 #include <OSD_Timer.hxx>
30 #include <Plugin_MapOfFunctions.hxx>
31 #include <Resource_Manager.hxx>
32 #include <Standard_ErrorHandler.hxx>
33 #include <Standard_Stream.hxx>
34 #include <Standard_Version.hxx>
35 #include <TCollection_AsciiString.hxx>
38 // on MSVC, use #pragma to define name of the Tcl library to link with,
39 // depending on Tcl version number
41 // two helper macros are needed to convert version number macro to string literal
42 #define STRINGIZE1(a) #a
43 #define STRINGIZE2(a) STRINGIZE1(a)
44 #pragma comment (lib, "tcl" STRINGIZE2(TCL_MAJOR_VERSION) STRINGIZE2(TCL_MINOR_VERSION) ".lib")
45 #pragma comment (lib, "tk" STRINGIZE2(TCL_MAJOR_VERSION) STRINGIZE2(TCL_MINOR_VERSION) ".lib")
50 extern Standard_Boolean Draw_ParseFailed;
52 Standard_EXPORT Draw_Viewer dout;
53 Standard_EXPORT Draw_Interpretor theCommands;
54 Standard_EXPORT Standard_Boolean Draw_Batch;
55 Standard_EXPORT Standard_Boolean Draw_Spying = Standard_False;
56 Standard_EXPORT Standard_Boolean Draw_Chrono = Standard_False;
57 Standard_EXPORT Standard_Boolean Draw_VirtualWindows = Standard_False;
58 Standard_EXPORT Standard_Boolean ErrorMessages = Standard_True;
60 static const char* ColorNames[MAXCOLOR] = {
61 "White","Red","Green","Blue","Cyan","Gold","Magenta",
62 "Maroon","Orange","Pink","Salmon","Violet","Yellow","Khaki","Coral"
67 static ostream spystream(&Draw_Spyfile);
69 static Standard_Boolean XLoop;
71 static Handle(Draw_ProgressIndicator) PInd = NULL;
73 Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
74 // true if complete command
76 // *******************************************************************
78 // *******************************************************************
80 extern console_semaphore_value volatile console_semaphore;
81 extern wchar_t console_command[1000];
84 static void ReadInitFile (const TCollection_AsciiString& theFileName)
86 TCollection_AsciiString aPath = theFileName;
92 aPath.ChangeAll ('\\', '/');
94 const TCollection_ExtendedString aCmdWide = TCollection_ExtendedString ("source -encoding utf-8 \"") + TCollection_ExtendedString (aPath) + "\"";
95 memcpy (console_command, aCmdWide.ToWideString(), Min (aCmdWide.Length() + 1, 980) * sizeof(wchar_t));
97 console_semaphore = HAS_CONSOLE_COMMAND;
98 while (console_semaphore == HAS_CONSOLE_COMMAND)
104 cout << "Error while reading a script file." << endl;
109 char* com = new char [aPath.Length() + strlen ("source -encoding utf-8 ") + 2];
110 Sprintf (com, "source -encoding utf-8 %s", aPath.ToCString());
111 Draw_Interprete (com);
118 //=======================================================================
120 //purpose : Set/Get Progress Indicator
121 //=======================================================================
122 void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& thePI)
127 Handle(Draw_ProgressIndicator) Draw::GetProgressBar()
133 /*--------------------------------------------------------*\
134 | exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
135 \*--------------------------------------------------------*/
136 void exitProc(ClientData /*dc*/)
139 for (Standard_Integer id = 0; id < MAXVIEW; id++)
145 // *******************************************************************
147 // *******************************************************************
149 Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, int nShow, int argc, wchar_t** argv, const FDraw_InitAppli Draw_InitAppli)
151 void Draw_Appli(int argc, char** argv, const FDraw_InitAppli Draw_InitAppli)
155 // prepend extra DLL search path to override system libraries like opengl32.dll
157 OSD_Environment aUserDllEnv ("CSF_UserDllPath");
158 const TCollection_ExtendedString aUserDllPath (aUserDllEnv.Value());
159 if (!aUserDllPath.IsEmpty())
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 *SetDllDirectoryW_t)(const wchar_t* thePathName);
164 HMODULE aKern32Module = GetModuleHandleW (L"kernel32");
165 SetDllDirectoryW_t aFunc = (aKern32Module != NULL)
166 ? (SetDllDirectoryW_t )GetProcAddress (aKern32Module, "SetDllDirectoryW") : NULL;
169 aFunc (aUserDllPath.ToWideString());
173 //std::cerr << "SetDllDirectoryW() is not available on this system!\n";
175 if (aKern32Module != NULL)
177 FreeLibrary (aKern32Module);
182 // *****************************************************************
184 // *****************************************************************
185 Draw_Batch = Standard_False;
186 TCollection_AsciiString aRunFile, aCommand;
187 Standard_Boolean isInteractiveForced = Standard_False;
189 // parse command line
190 for (int anArgIter = 1; anArgIter < argc; ++anArgIter)
192 TCollection_AsciiString anArg (argv[anArgIter]);
195 || anArg == "--help")
197 std::cout << "Open CASCADE " << OCC_VERSION_STRING_EXT << " DRAW Test Harness\n\n";
198 std::cout << "Options:\n";
199 std::cout << " -b: batch mode (no GUI, no viewers)\n";
200 std::cout << " -v: no GUI, use virtual (off-screen) windows for viewers\n";
201 std::cout << " -i: interactive mode\n";
202 std::cout << " -f file: execute script from file\n";
203 std::cout << " -c command args...: execute command (with optional arguments)\n\n";
204 std::cout << "Options -b, -v, and -i are mutually exclusive.\n";
205 std::cout << "If -c or -f are given, -v is default; otherwise default is -i.\n";
206 std::cout << "Options -c and -f are alternatives and should be at the end \n";
207 std::cout << "of the command line.\n";
208 std::cout << "Option -c can accept set of commands separated by ';'.\n";
211 else if (anArg == "-b")
213 Draw_Batch = Standard_True;
215 else if (anArg == "-v")
217 // force virtual windows
218 Draw_VirtualWindows = Standard_True;
220 else if (anArg == "-i")
223 Draw_VirtualWindows = Standard_False;
224 isInteractiveForced = Standard_True;
226 else if (anArg == "-f") // -f option should be LAST!
228 Draw_VirtualWindows = !isInteractiveForced;
229 if (++anArgIter < argc)
231 aRunFile = TCollection_AsciiString (argv[anArgIter]);
235 else if (anArg == "-c") // -c option should be LAST!
237 Draw_VirtualWindows = !isInteractiveForced;
238 if (++anArgIter < argc)
240 aCommand = TCollection_AsciiString (argv[anArgIter]);
242 while (++anArgIter < argc)
244 aCommand.AssignCat (" ");
245 aCommand.AssignCat (argv[anArgIter]);
251 std::cout << "Error: unsupported option " << TCollection_AsciiString (argv[anArgIter]) << "\n";
255 // *****************************************************************
257 // *****************************************************************
258 OSD::SetSignal(Standard_False);
261 // in interactive mode, force Windows to report dll loading problems interactively
262 if ( ! Draw_VirtualWindows && ! Draw_Batch )
266 // *****************************************************************
267 // init X window and create display
268 // *****************************************************************
275 Draw_Batch=!Init_Appli(hInst, hPrevInst, nShow, hWnd);
277 Draw_Batch=!Init_Appli();
280 cout << "DRAW is running in batch mode" << endl;
286 for (int i = 0; i < MAXCOLOR; ++i)
288 if (!dout.DefineColor (i, ColorNames[i]))
290 std::cout <<"Could not allocate default color " << ColorNames[i] << std::endl;
295 // *****************************************************************
296 // set maximum precision for cout
297 // *****************************************************************
300 // *****************************************************************
302 // *****************************************************************
303 Draw::BasicCommands(theCommands);
304 Draw::VariableCommands(theCommands);
305 Draw::UnitCommands(theCommands);
306 if (!Draw_Batch) Draw::GraphicCommands(theCommands);
308 // *****************************************************************
310 // *****************************************************************
311 Draw_InitAppli(theCommands);
314 Tcl_CreateExitHandler(exitProc, 0);
317 // *****************************************************************
319 // *****************************************************************
322 if (getenv ("DRAWDEFAULT") == NULL)
324 if (getenv ("CASROOT") == NULL)
327 ReadInitFile ("ddefault");
329 cout << " the CASROOT variable is mandatory to Run OpenCascade "<< endl;
330 cout << "No default file" << endl;
335 TCollection_AsciiString aDefStr (getenv ("CASROOT"));
336 aDefStr += "/src/DrawResources/DrawDefault";
337 ReadInitFile (aDefStr);
342 ReadInitFile (getenv ("DRAWDEFAULT"));
345 // read commands from file
346 if (!aRunFile.IsEmpty()) {
347 ReadInitFile (aRunFile);
348 // provide a clean exit, this is useful for some analysis tools
349 if ( ! isInteractiveForced )
357 // execute command from command line
358 if (!aCommand.IsEmpty()) {
359 Draw_Interprete (aCommand.ToCString());
360 // provide a clean exit, this is useful for some analysis tools
361 if ( ! isInteractiveForced )
369 // *****************************************************************
371 // *****************************************************************
376 Run_Appli(Draw_Interprete);
388 } while ((cmd[i] != '\n') && (!cin.fail()));
390 Draw_Interprete(cmd);
394 // Destruction de l'application
395 Destroy_Appli(hInst);
400 // User functions called before and after each command
401 void (*Draw_BeforeCommand)() = NULL;
402 void (*Draw_AfterCommand)(Standard_Integer) = NULL;
404 Standard_Boolean Draw_Interprete(const char* com)
407 static Standard_Boolean first = Standard_True;
408 static Tcl_DString command;
411 first = Standard_False;
412 Tcl_DStringInit(&command);
416 // string is already converted into UTF-8
417 Tcl_DStringAppend(&command, com, -1);
418 #elif ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)))
419 // OCC63: Since Tcl 8.1 it uses UTF-8 encoding for internal representation of strings
420 Tcl_ExternalToUtfDString ( NULL, com, -1, &command );
422 Tcl_DStringAppend(&command,com,-1);
425 if (!theCommands.Complete(Tcl_DStringValue(&command)))
426 return Standard_False;
428 // *******************************************************************
429 // Command interpreter
430 // *******************************************************************
432 // Standard_Integer i = 0;
433 // Standard_Integer j = 0;
435 Standard_Boolean wasspying = Draw_Spying;
438 Standard_Boolean hadchrono = Draw_Chrono;
439 if (hadchrono) tictac.Start();
441 if (Draw_BeforeCommand) (*Draw_BeforeCommand) ();
445 c = theCommands.RecordAndEval(Tcl_DStringValue(&command));
447 if (Draw_AfterCommand) (*Draw_AfterCommand)(c);
449 if (wasspying && Draw_Spying) {
450 if (c > 0) spystream << "# ";
451 spystream << Tcl_DStringValue(&command) << "\n";
456 if (*theCommands.Result())
459 const TCollection_ExtendedString aResWide (theCommands.Result());
460 std::wcout << aResWide.ToWideString() << std::endl;
462 std::cout << theCommands.Result() << std::endl;
466 if (Draw_Chrono && hadchrono) {
471 Tcl_DStringFree(&command);
473 return Standard_True;
480 Standard_Integer Tcl_AppInit (Tcl_Interp *)
491 Standard_Integer Draw_Call (char *c)
493 Standard_Integer r = theCommands.Eval(c);
494 cout << theCommands.Result() << endl;
498 //=================================================================================
500 //=================================================================================
501 void Draw::Load(Draw_Interpretor& theDI, const TCollection_AsciiString& theKey,
502 const TCollection_AsciiString& theResourceFileName,
503 TCollection_AsciiString& theDefaultsDirectory,
504 TCollection_AsciiString& theUserDefaultsDirectory,
505 const Standard_Boolean Verbose ) {
507 static Plugin_MapOfFunctions theMapOfFunctions;
510 if(!theMapOfFunctions.IsBound(theKey)) {
512 Handle(Resource_Manager) aPluginResource = new Resource_Manager(theResourceFileName.ToCString(), theDefaultsDirectory, theUserDefaultsDirectory, Verbose);
514 if(!aPluginResource->Find(theKey.ToCString())) {
515 Standard_SStream aMsg; aMsg << "Could not find the resource:";
516 aMsg << theKey.ToCString()<< endl;
517 cout << "could not find the resource:"<<theKey.ToCString()<< endl;
518 throw Draw_Failure(aMsg.str().c_str());
521 TCollection_AsciiString aPluginLibrary("");
522 #if !defined(_WIN32) || defined(__MINGW32__)
523 aPluginLibrary += "lib";
525 aPluginLibrary += aPluginResource->Value(theKey.ToCString());
527 aPluginLibrary += ".dll";
529 aPluginLibrary += ".dylib";
530 #elif defined (HPUX) || defined(_hpux)
531 aPluginLibrary += ".sl";
533 aPluginLibrary += ".so";
535 OSD_SharedLibrary aSharedLibrary(aPluginLibrary.ToCString());
536 if(!aSharedLibrary.DlOpen(OSD_RTLD_LAZY)) {
537 TCollection_AsciiString error(aSharedLibrary.DlError());
538 Standard_SStream aMsg; aMsg << "Could not open: ";
539 aMsg << aPluginResource->Value(theKey.ToCString());
540 aMsg << "; reason: ";
541 aMsg << error.ToCString();
543 cout << "could not open: " << aPluginResource->Value(theKey.ToCString())<< " ; reason: "<< error.ToCString() << endl;
545 throw Draw_Failure(aMsg.str().c_str());
547 f = aSharedLibrary.DlSymb("PLUGINFACTORY");
549 TCollection_AsciiString error(aSharedLibrary.DlError());
550 Standard_SStream aMsg; aMsg << "Could not find the factory in: ";
551 aMsg << aPluginResource->Value(theKey.ToCString());
552 aMsg << error.ToCString();
553 throw Draw_Failure(aMsg.str().c_str());
555 theMapOfFunctions.Bind(theKey, f);
558 f = theMapOfFunctions(theKey);
560 // void (*fp) (Draw_Interpretor&, const TCollection_AsciiString&) = NULL;
561 // fp = (void (*)(Draw_Interpretor&, const TCollection_AsciiString&)) f;
562 // (*fp) (theDI, theKey);
564 void (*fp) (Draw_Interpretor&) = NULL;
565 fp = (void (*)(Draw_Interpretor&)) f;