0031171: Draw - support Unicode input / output in console on Windows
[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
18 #include <Draw.hxx>
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>
26 #include <OSD.hxx>
27 #include <OSD_Environment.hxx>
28 #include <OSD_File.hxx>
29 #include <OSD_Process.hxx>
30 #include <OSD_SharedLibrary.hxx>
31 #include <OSD_Timer.hxx>
32 #include <Plugin_MapOfFunctions.hxx>
33 #include <Resource_Manager.hxx>
34 #include <Standard_ErrorHandler.hxx>
35 #include <Standard_Stream.hxx>
36 #include <Standard_Version.hxx>
37 #include <TCollection_AsciiString.hxx>
38
39 #include <tcl.h>
40
41 #include <Standard_WarningDisableFunctionCast.hxx>
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 std::filebuf Draw_Spyfile;
71
72 static std::ostream spystream(&Draw_Spyfile);
73
74 static Handle(Draw_ProgressIndicator) PInd = NULL;
75
76 Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
77 // true if complete command
78
79 // *******************************************************************
80 // read an init file
81 // *******************************************************************
82
83 static void interpreteTclCommand (const TCollection_AsciiString& theCmd)
84 {
85 #ifdef _WIN32
86   if (!Draw_Batch)
87   {
88     try
89     {
90       while (console_semaphore == HAS_CONSOLE_COMMAND)
91       {
92         Sleep(10);
93       }
94       {
95         TCollection_ExtendedString aCmdWide (theCmd);
96         wcscpy_s (console_command, aCmdWide.ToWideString());
97       }
98       console_semaphore = HAS_CONSOLE_COMMAND;
99       while (console_semaphore == HAS_CONSOLE_COMMAND)
100       {
101         Sleep(10);
102       }
103     }
104     catch (...)
105     {
106       std::cout << "Error while reading a script file.\n";
107       ExitProcess(0);
108     }
109   }
110   else
111 #endif
112   {
113     Draw_Interprete (theCmd.ToCString());
114   }
115 }
116
117 static void ReadInitFile (const TCollection_AsciiString& theFileName)
118 {
119   TCollection_AsciiString aCmd = theFileName;
120 #ifdef _WIN32
121   aCmd.ChangeAll ('\\', '/');
122 #endif
123   aCmd = TCollection_AsciiString ("source -encoding utf-8 \"") + aCmd + "\"";
124   interpreteTclCommand (aCmd);
125 }
126
127 //! Define environment variable available from Tcl and OCCT.
128 static void setOcctTclEnv (const TCollection_AsciiString& theName,
129                            TCollection_AsciiString& thePath)
130 {
131   if (thePath.IsEmpty())
132   {
133     return;
134   }
135
136   thePath.ChangeAll ('\\', '/');
137   OSD_Environment aRedPathEnv (theName);
138   aRedPathEnv.SetValue (thePath);
139   aRedPathEnv.Build();
140
141   const TCollection_AsciiString aPutEnv = theName + "=" + thePath;
142   Tcl_PutEnv (aPutEnv.ToCString());
143 }
144
145 //! Look for resource within standard installation layouts relative to executable location.
146 //!
147 //! Bin (INSTALL_DIR_BIN):
148 //!  - Windows: <prefix>/win64/vc10/bin(d)
149 //!  - Unix:    <prefix>/bin
150 //! Resources (INSTALL_DIR_RESOURCE):
151 //!  - Windows: <prefix>/src
152 //!  - Unix:    <prefix>/share/opencascade-7.0.0/resources
153 //! Samples (INSTALL_DIR_SAMPLES):
154 //!  - Windows: <prefix>/samples
155 //!  - Unix:    <prefix>/share/opencascade-7.0.0/samples
156 //! Tests (INSTALL_DIR_TESTS):
157 //!  - Windows: <prefix>/tests
158 //!  - Unix:    <prefix>/share/opencascade-7.0.0/tests
159 //!
160 //! @param theCasRoot  [out] found CASROOT location (e.g. installation folder)
161 //! @param theResRoot  [out] found resources root location
162 //! @param theResName   [in] resource to find ("resources", "samples", etc.)
163 //! @param theProbeFile [in] file to probe within resources location (e.g. "DrawResources/DrawDefault" within "resources")
164 static bool searchResources (TCollection_AsciiString& theCasRoot,
165                              TCollection_AsciiString& theResRoot,
166                              const TCollection_AsciiString& theResName,
167                              const TCollection_AsciiString& theProbeFile)
168 {
169   const TCollection_AsciiString aResLayouts[] =
170   {
171     TCollection_AsciiString("/share/opencascade-" OCC_VERSION_STRING_EXT "/") + theResName,
172     TCollection_AsciiString("/share/opencascade-" OCC_VERSION_COMPLETE "/") + theResName,
173     TCollection_AsciiString("/share/opencascade-" OCC_VERSION_STRING "/") + theResName,
174     TCollection_AsciiString("/share/opencascade/") + theResName,
175     TCollection_AsciiString("/share/occt-" OCC_VERSION_STRING_EXT "/") + theResName,
176     TCollection_AsciiString("/share/occt-" OCC_VERSION_COMPLETE "/") + theResName,
177     TCollection_AsciiString("/share/occt-" OCC_VERSION_STRING "/") + theResName,
178     TCollection_AsciiString("/share/occt/") + theResName,
179     TCollection_AsciiString("/") + theResName,
180     TCollection_AsciiString("/share/opencascade"),
181     TCollection_AsciiString("/share/occt"),
182     TCollection_AsciiString("/share"),
183     TCollection_AsciiString("/src"),
184     TCollection_AsciiString("")
185   };
186
187   const TCollection_AsciiString anExeDir (OSD_Process::ExecutableFolder());
188   for (Standard_Integer aLayIter = 0;; ++aLayIter)
189   {
190     const TCollection_AsciiString& aResLayout = aResLayouts[aLayIter];
191     const TCollection_AsciiString  aProbeFile = aResLayout + "/" + theProbeFile;
192     if (OSD_File (anExeDir + aProbeFile).Exists())
193     {
194       theCasRoot = anExeDir;
195       theResRoot = theCasRoot + aResLayout;
196       return true;
197     }
198     // <prefix>/bin(d)
199     else if (OSD_File (anExeDir + "../" + aProbeFile).Exists())
200     {
201       theCasRoot = anExeDir + "..";
202       theResRoot = theCasRoot + aResLayout;
203       return true;
204     }
205     // <prefix>/gcc/bin(d)
206     else if (OSD_File (anExeDir + "../../" + aProbeFile).Exists())
207     {
208       theCasRoot = anExeDir + "../..";
209       theResRoot = theCasRoot + aResLayout;
210       return true;
211     }
212     // <prefix>/win64/vc10/bin(d)
213     else if (OSD_File (anExeDir + "../../../" + aProbeFile).Exists())
214     {
215       theCasRoot = anExeDir + "../../..";
216       theResRoot = theCasRoot + aResLayout;
217       return true;
218     }
219
220     if (aResLayout.IsEmpty())
221     {
222       return false;
223     }
224   }
225 }
226
227 //=======================================================================
228 //function : GetInterpretor
229 //purpose  :
230 //=======================================================================
231 Draw_Interpretor& Draw::GetInterpretor()
232 {
233   return theCommands;
234 }
235
236 //=======================================================================
237 //function :
238 //purpose  : Set/Get Progress Indicator
239 //=======================================================================
240 void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& thePI)
241 {
242   PInd = thePI;
243 }
244
245 Handle(Draw_ProgressIndicator) Draw::GetProgressBar()
246 {
247   return PInd;
248 }
249
250 #ifndef _WIN32
251 /*--------------------------------------------------------*\
252 |  exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
253 \*--------------------------------------------------------*/
254 void exitProc(ClientData /*dc*/)
255 {
256   if (!Draw_Batch) {
257     for (Standard_Integer id = 0; id < MAXVIEW; id++)
258       dout.DeleteView(id);
259   }
260 }
261 #endif
262
263 // *******************************************************************
264 // main
265 // *******************************************************************
266 #ifdef _WIN32
267 Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, int nShow, int argc, wchar_t** argv, const FDraw_InitAppli Draw_InitAppli)
268 #else
269 void Draw_Appli(int argc, char** argv, const FDraw_InitAppli Draw_InitAppli)
270 #endif
271 {
272
273 // prepend extra DLL search path to override system libraries like opengl32.dll
274 #ifdef _WIN32
275   OSD_Environment aUserDllEnv ("CSF_UserDllPath");
276   const TCollection_ExtendedString aUserDllPath (aUserDllEnv.Value());
277   if (!aUserDllPath.IsEmpty())
278   {
279     // This function available since Win XP SP1 #if (_WIN32_WINNT >= 0x0502).
280     // We retrieve dynamically here (kernel32 should be always preloaded).
281     typedef BOOL (WINAPI *SetDllDirectoryW_t)(const wchar_t* thePathName);
282     HMODULE aKern32Module = GetModuleHandleW (L"kernel32");
283     SetDllDirectoryW_t aFunc = (aKern32Module != NULL)
284                              ? (SetDllDirectoryW_t )GetProcAddress (aKern32Module, "SetDllDirectoryW") : NULL;
285     if (aFunc != NULL)
286     {
287       aFunc (aUserDllPath.ToWideString());
288     }
289     else
290     {
291       //std::cerr << "SetDllDirectoryW() is not available on this system!\n";
292     }
293     if (aKern32Module != NULL)
294     {
295       FreeLibrary (aKern32Module);
296     }
297   }
298 #endif
299
300   // *****************************************************************
301   // analyze arguments
302   // *****************************************************************
303   Draw_Batch = Standard_False;
304   TCollection_AsciiString aRunFile, aCommand;
305   Standard_Boolean isInteractiveForced = Standard_False;
306
307   // parse command line
308   for (int anArgIter = 1; anArgIter < argc; ++anArgIter)
309   {
310     TCollection_AsciiString anArg (argv[anArgIter]);
311     anArg.LowerCase();
312     if (anArg == "-h"
313      || anArg == "--help")
314     {
315       std::cout << "Open CASCADE " << OCC_VERSION_STRING_EXT << " DRAW Test Harness\n\n";
316       std::cout << "Options:\n";
317       std::cout << "  -b: batch mode (no GUI, no viewers)\n";
318       std::cout << "  -v: no GUI, use virtual (off-screen) windows for viewers\n";
319       std::cout << "  -i: interactive mode\n";
320       std::cout << "  -f file: execute script from file\n";
321       std::cout << "  -c command args...: execute command (with optional arguments)\n\n";
322       std::cout << "Options -b, -v, and -i are mutually exclusive.\n";
323       std::cout << "If -c or -f are given, -v is default; otherwise default is -i.\n";
324       std::cout << "Options -c and -f are alternatives and should be at the end \n";
325       std::cout << "of the command line.\n";
326       std::cout << "Option -c can accept set of commands separated by ';'.\n";
327       return;
328     }
329     else if (anArg == "-b")
330     {
331       Draw_Batch = Standard_True;
332     }
333     else if (anArg == "-v")
334     {
335       // force virtual windows
336       Draw_VirtualWindows = Standard_True;
337     }
338     else if (anArg == "-i")
339     {
340       // force interactive
341       Draw_VirtualWindows = Standard_False;
342       isInteractiveForced = Standard_True;
343     }
344     else if (anArg == "-f") // -f option should be LAST!
345     {
346       Draw_VirtualWindows = !isInteractiveForced;
347       if (++anArgIter < argc)
348       {
349         aRunFile = TCollection_AsciiString (argv[anArgIter]);
350       }
351       break;
352     }
353     else if (anArg == "-c") // -c option should be LAST!
354     {
355       Draw_VirtualWindows = !isInteractiveForced;
356       if (++anArgIter < argc)
357       {
358         aCommand = TCollection_AsciiString (argv[anArgIter]);
359       }
360       while (++anArgIter < argc)
361       {
362         aCommand.AssignCat (" ");
363         aCommand.AssignCat (argv[anArgIter]);
364       }
365       break;
366     }
367     else
368     {
369       std::cout << "Error: unsupported option " << TCollection_AsciiString (argv[anArgIter]) << "\n";
370     }
371   }
372
373   // *****************************************************************
374   // set signals
375   // *****************************************************************
376   OSD::SetSignal(Standard_False);
377
378 #ifdef _WIN32
379   // in interactive mode, force Windows to report dll loading problems interactively
380   if ( ! Draw_VirtualWindows && ! Draw_Batch )
381     ::SetErrorMode (0);
382 #endif
383
384   // *****************************************************************
385   // init X window and create display
386   // *****************************************************************
387 #ifdef _WIN32
388   HWND hWnd = NULL;
389 #endif
390
391   if (!Draw_Batch)
392 #ifdef _WIN32
393     Draw_Batch=!Init_Appli(hInst, hPrevInst, nShow, hWnd);
394 #else
395     Draw_Batch=!Init_Appli();
396 #endif
397   else
398   {
399     std::cout << "DRAW is running in batch mode" << std::endl;
400     theCommands.Init();
401     Tcl_Init(theCommands.Interp());
402   }
403
404   if (! Draw_Batch)
405   {
406     // Default colors
407     for (int i = 0; i < MAXCOLOR; ++i)
408     {
409       if (!dout.DefineColor (i, ColorNames[i]))
410       {
411         std::cout <<"Could not allocate default color " << ColorNames[i] << std::endl;
412       }
413     }
414   }
415
416   // *****************************************************************
417   // set maximum precision for cout
418   // *****************************************************************
419   std::cout.precision(15);
420
421   // *****************************************************************
422   // standard commands
423   // *****************************************************************
424   Draw::BasicCommands(theCommands);
425   Draw::VariableCommands(theCommands);
426   Draw::UnitCommands(theCommands);
427   if (!Draw_Batch) Draw::GraphicCommands(theCommands);
428
429   // *****************************************************************
430   // user commands
431   // *****************************************************************
432   Draw_InitAppli(theCommands);
433
434 #ifndef _WIN32
435   Tcl_CreateExitHandler(exitProc, 0);
436 #endif
437
438   // *****************************************************************
439   // read init files
440   // *****************************************************************
441   // default
442   const TCollection_AsciiString aDrawDef (OSD_Environment ("DRAWDEFAULT").Value());
443   if (!aDrawDef.IsEmpty())
444   {
445     ReadInitFile (aDrawDef);
446   }
447   else
448   {
449     TCollection_AsciiString aDrawHome;
450     TCollection_AsciiString aCasRoot (OSD_Environment ("CASROOT").Value());
451     if (!aCasRoot.IsEmpty())
452     {
453       aDrawHome = aCasRoot + "/src/DrawResources";
454     }
455     else
456     {
457       // search for relative locations within standard development environment
458       TCollection_AsciiString aResPath;
459       if (searchResources (aCasRoot, aResPath, "resources", "DrawResources/DrawDefault"))
460       {
461         aDrawHome = aResPath + "/DrawResources";
462         setOcctTclEnv ("CASROOT",  aCasRoot);
463         setOcctTclEnv ("DRAWHOME", aDrawHome);
464         setOcctTclEnv ("CSF_OCCTResourcePath", aResPath);
465       }
466
467       TCollection_AsciiString aSamplesPath;
468       if (OSD_Environment ("CSF_OCCTSamplesPath").Value().IsEmpty()
469        && searchResources (aCasRoot, aSamplesPath, "samples", "tcl/Readme.txt"))
470       {
471         setOcctTclEnv ("CSF_OCCTSamplesPath", aSamplesPath);
472       }
473
474       TCollection_AsciiString aTestsPath;
475       if (OSD_Environment ("CSF_TestScriptsPath").Value().IsEmpty()
476        && searchResources (aCasRoot, aTestsPath, "tests", "parse.rules"))
477       {
478         setOcctTclEnv ("CSF_TestScriptsPath", aTestsPath);
479       }
480     }
481
482     if (!aDrawHome.IsEmpty())
483     {
484       const TCollection_AsciiString aDefStr = aDrawHome + "/DrawDefault";
485       ReadInitFile (aDefStr);
486     }
487     else
488     {
489 #ifdef _WIN32
490       ReadInitFile ("ddefault");
491 #else
492       std::cout << " the CASROOT variable is mandatory to Run OpenCascade "<< std::endl;
493       std::cout << "No default file" << std::endl;
494 #endif
495     }
496   }
497
498   // read commands from file
499   if (!aRunFile.IsEmpty()) {
500     ReadInitFile (aRunFile);
501     // provide a clean exit, this is useful for some analysis tools
502     if ( ! isInteractiveForced )
503 #ifndef _WIN32
504       return;
505 #else
506       ExitProcess(0);
507 #endif
508   }
509
510   // execute command from command line
511   if (!aCommand.IsEmpty())
512   {
513 #ifdef _WIN32
514     if (!Draw_Batch)
515     {
516       // on Windows except batch mode, commands are executed in separate thread
517       while (console_semaphore == HAS_CONSOLE_COMMAND) Sleep(10);
518       TCollection_ExtendedString aCmdWide(aCommand);
519       wcscpy_s(console_command, aCmdWide.ToWideString());
520       console_semaphore = HAS_CONSOLE_COMMAND;
521       while (console_semaphore == HAS_CONSOLE_COMMAND) Sleep(10);
522     }
523     else
524 #endif
525     Draw_Interprete (aCommand.ToCString()); // Linux and Windows batch mode
526     // provide a clean exit, this is useful for some analysis tools
527     if ( ! isInteractiveForced )
528 #ifndef _WIN32
529       return;
530 #else
531       ExitProcess(0);
532 #endif
533   }
534
535   // *****************************************************************
536   // X loop
537   // *****************************************************************
538   if (! Draw_Batch) {
539 #ifdef _WIN32
540     Run_Appli(hWnd);
541 #else
542     Run_Appli(Draw_Interprete);
543 #endif
544   }
545   else
546   {
547     const int MAXCMD = 2048;
548     char cmd[MAXCMD];
549     for (int ncmd = 1;; ++ncmd)
550     {
551       std::cout << "Draw[" << ncmd << "]> ";
552       if (std::cin.getline (cmd, MAXCMD).fail())
553       {
554         break;
555       }
556       Draw_Interprete(cmd);
557     }
558   }
559 #ifdef _WIN32
560   // Destruction de l'application
561   Destroy_Appli(hInst);
562 #endif
563 }
564 //#endif
565
566 // User functions called before and after each command
567 void (*Draw_BeforeCommand)() = NULL;
568 void (*Draw_AfterCommand)(Standard_Integer) = NULL;
569
570 Standard_Boolean Draw_Interprete(const char* com)
571 {
572
573   static Standard_Boolean first = Standard_True;
574   static Tcl_DString command;
575
576   if (first) {
577     first = Standard_False;
578     Tcl_DStringInit(&command);
579   }
580
581 #ifdef _WIN32
582   // string is already converted into UTF-8
583   Tcl_DStringAppend(&command, com, -1);
584 #elif ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)))
585   // OCC63: Since Tcl 8.1 it uses UTF-8 encoding for internal representation of strings
586   Tcl_ExternalToUtfDString ( NULL, com, -1, &command );
587 #else
588   Tcl_DStringAppend(&command,com,-1);
589 #endif
590
591   if (!theCommands.Complete(Tcl_DStringValue(&command)))
592     return Standard_False;
593
594   // *******************************************************************
595   // Command interpreter
596   // *******************************************************************
597
598 //  Standard_Integer i = 0;
599 //  Standard_Integer j = 0;
600
601   Standard_Boolean wasspying = Draw_Spying;
602
603   OSD_Timer tictac;
604   Standard_Boolean hadchrono = Draw_Chrono;
605   if (hadchrono) tictac.Start();
606
607   if (Draw_BeforeCommand) (*Draw_BeforeCommand) ();
608
609   Standard_Integer c;
610
611   c = theCommands.RecordAndEval(Tcl_DStringValue(&command));
612
613   if (Draw_AfterCommand) (*Draw_AfterCommand)(c);
614
615   if (wasspying && Draw_Spying) {
616     if (c > 0) spystream << "# ";
617     spystream << Tcl_DStringValue(&command) << "\n";
618   }
619
620   dout.Flush();
621
622   if (*theCommands.Result())
623   {
624     std::cout << theCommands.Result() << std::endl;
625   }
626
627   if (Draw_Chrono && hadchrono) {
628     tictac.Stop();
629     tictac.Show();
630   }
631
632   Tcl_DStringFree(&command);
633
634   return Standard_True;
635 }
636
637 //
638 // for TCl
639 //
640
641 Standard_Integer Tcl_AppInit (Tcl_Interp *)
642 {
643   return 0;
644 }
645
646 //
647 // for debug call
648 //
649
650
651
652 Standard_Integer  Draw_Call (char *c)
653 {
654    Standard_Integer r = theCommands.Eval(c);
655    std::cout << theCommands.Result() << std::endl;
656    return r;
657 }
658
659 //=================================================================================
660 //
661 //=================================================================================
662 void Draw::Load(Draw_Interpretor& theDI, const TCollection_AsciiString& theKey,
663                 const TCollection_AsciiString& theResourceFileName,
664                 TCollection_AsciiString& theDefaultsDirectory,
665                 TCollection_AsciiString& theUserDefaultsDirectory,
666                 const Standard_Boolean Verbose ) {
667
668   static Plugin_MapOfFunctions theMapOfFunctions;
669   OSD_Function f;
670
671   if(!theMapOfFunctions.IsBound(theKey)) {
672
673     Handle(Resource_Manager) aPluginResource = new Resource_Manager(theResourceFileName.ToCString(), theDefaultsDirectory, theUserDefaultsDirectory, Verbose);
674
675     if(!aPluginResource->Find(theKey.ToCString())) {
676       Standard_SStream aMsg; aMsg << "Could not find the resource:";
677       aMsg << theKey.ToCString()<< std::endl;
678       std::cout << "could not find the resource:"<<theKey.ToCString()<< std::endl;
679       throw Draw_Failure(aMsg.str().c_str());
680     }
681
682     TCollection_AsciiString aPluginLibrary("");
683 #if !defined(_WIN32) || defined(__MINGW32__)
684     aPluginLibrary += "lib";
685 #endif
686     aPluginLibrary +=  aPluginResource->Value(theKey.ToCString());
687 #ifdef _WIN32
688     aPluginLibrary += ".dll";
689 #elif __APPLE__
690     aPluginLibrary += ".dylib";
691 #elif defined (HPUX) || defined(_hpux)
692     aPluginLibrary += ".sl";
693 #else
694     aPluginLibrary += ".so";
695 #endif
696     OSD_SharedLibrary aSharedLibrary(aPluginLibrary.ToCString());
697     if(!aSharedLibrary.DlOpen(OSD_RTLD_LAZY)) {
698       TCollection_AsciiString error(aSharedLibrary.DlError());
699       Standard_SStream aMsg; aMsg << "Could not open: ";
700       aMsg << aPluginResource->Value(theKey.ToCString());
701       aMsg << "; reason: ";
702       aMsg << error.ToCString();
703 #ifdef OCCT_DEBUG
704       std::cout << "could not open: "  << aPluginResource->Value(theKey.ToCString())<< " ; reason: "<< error.ToCString() << std::endl;
705 #endif
706       throw Draw_Failure(aMsg.str().c_str());
707     }
708     f = aSharedLibrary.DlSymb("PLUGINFACTORY");
709     if( f == NULL ) {
710       TCollection_AsciiString error(aSharedLibrary.DlError());
711       Standard_SStream aMsg; aMsg << "Could not find the factory in: ";
712       aMsg << aPluginResource->Value(theKey.ToCString());
713       aMsg << error.ToCString();
714       throw Draw_Failure(aMsg.str().c_str());
715     }
716     theMapOfFunctions.Bind(theKey, f);
717   }
718   else
719     f = theMapOfFunctions(theKey);
720
721 //   void (*fp) (Draw_Interpretor&, const TCollection_AsciiString&) = NULL;
722 //   fp = (void (*)(Draw_Interpretor&, const TCollection_AsciiString&)) f;
723 //   (*fp) (theDI, theKey);
724
725   void (*fp) (Draw_Interpretor&) = NULL;
726   fp = (void (*)(Draw_Interpretor&)) f;
727   (*fp) (theDI);
728
729 }