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