0025307: Problems resulted from re-triangulation
[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
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17#include <Draw.ixx>
18
7fd59977 19#include <Draw_Appli.hxx>
20#include <OSD.hxx>
dac04bfa 21#include <OSD_Environment.hxx>
7fd59977 22#include <OSD_Timer.hxx>
23
7fd59977 24#include <Draw_Window.hxx>
25#include <gp_Pnt2d.hxx>
26
27#include <Standard_Stream.hxx>
bf03eb83 28#include <Standard_Version.hxx>
7fd59977 29
30#include <Draw_Drawable3D.hxx>
31#include <Draw_Interpretor.hxx>
32#include <Draw_ProgressIndicator.hxx>
7fd59977 33
97385d61 34#include <Plugin_MapOfFunctions.hxx>
7fd59977 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>
6a0964c2 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
7fd59977 55extern Standard_Boolean Draw_ParseFailed;
7fd59977 56
57Standard_EXPORT Draw_Viewer dout;
58Standard_EXPORT Draw_Interpretor theCommands;
59Standard_EXPORT Standard_Boolean Draw_Batch;
60Standard_EXPORT Standard_Boolean Draw_Spying = Standard_False;
61Standard_EXPORT Standard_Boolean Draw_Chrono = Standard_False;
62Standard_EXPORT Standard_Boolean Draw_VirtualWindows = Standard_False;
63Standard_EXPORT Standard_Boolean ErrorMessages = Standard_True;
64
65static const char* ColorNames[MAXCOLOR] = {
66 "White","Red","Green","Blue","Cyan","Gold","Magenta",
67 "Maroon","Orange","Pink","Salmon","Violet","Yellow","Khaki","Coral"
68 };
69
70filebuf Draw_Spyfile;
71
72static ostream spystream(&Draw_Spyfile);
73
74static Standard_Boolean XLoop;
75
76static Handle(Draw_ProgressIndicator) PInd = NULL;
77
bf03eb83 78Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
7fd59977 79// true if complete command
80
7fd59977 81// *******************************************************************
82// read an init file
83// *******************************************************************
84#ifdef WNT
85extern console_semaphore_value volatile console_semaphore;
86extern char console_command[1000];
87#endif
88
86be4295 89static void ReadInitFile (const TCollection_AsciiString& theFileName)
7fd59977 90{
86be4295 91 TCollection_AsciiString aPath = theFileName;
7fd59977 92#ifdef WNT
93 if (!Draw_Batch) {
94 try {
86be4295
A
95 aPath.ChangeAll ('\\', '/');
96
91322f44 97 Sprintf(console_command, "source \"%.980s\"", aPath.ToCString());
7fd59977 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
86be4295 108 char* com = new char [aPath.Length() + strlen ("source ") + 2];
91322f44 109 Sprintf (com, "source %s", aPath.ToCString());
86be4295 110 Draw_Interprete (com);
7fd59977 111 delete [] com;
112#ifdef WNT
113 }
114#endif
115}
7fd59977 116
117//=======================================================================
118//function :
119//purpose : Set/Get Progress Indicator
120//=======================================================================
121void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& thePI)
122{
123 PInd = thePI;
124}
125
126Handle(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\*--------------------------------------------------------*/
135void 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// *******************************************************************
dac04bfa 147#ifdef _WIN32
7fd59977 148//Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lps
149Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpszLine, int nShow,const FDraw_InitAppli Draw_InitAppli)
150#else
151void Draw_Appli(Standard_Integer argc, char** argv,const FDraw_InitAppli Draw_InitAppli)
152#endif
153{
dac04bfa 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
7fd59977 182 // *****************************************************************
183 // analyze arguments
184 // *****************************************************************
185 Draw_Batch = Standard_False;
bf03eb83 186 TCollection_AsciiString aRunFile, aCommand;
7fd59977 187 Standard_Integer i;
188 Standard_Boolean isInteractiveForced = Standard_False;
bf03eb83 189
dac04bfa 190#ifdef _WIN32
bf03eb83 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;
7fd59977 217 }
bf03eb83 218 else if (strcasecmp (argv[i], "-b") == 0)
219 Draw_Batch = Standard_True;
220 else if (strcasecmp (argv[i], "-v") == 0) {
7fd59977 221 // force virtual windows
222 Draw_VirtualWindows = Standard_True;
bf03eb83 223 } else if (strcasecmp (argv[i], "-i") == 0) {
7fd59977 224 // force interactive
225 Draw_VirtualWindows = Standard_False;
226 isInteractiveForced = Standard_True;
bf03eb83 227 } else if (strcasecmp (argv[i], "-f") == 0) { // -f option should be LAST!
7fd59977 228 Draw_VirtualWindows = !isInteractiveForced;
229 if (++i < argc) {
86be4295 230 aRunFile = TCollection_AsciiString (argv[i]);
7fd59977 231 }
232 break;
bf03eb83 233 } else if (strcasecmp (argv[i], "-c") == 0) { // -c option should be LAST!
7fd59977 234 Draw_VirtualWindows = !isInteractiveForced;
bf03eb83 235 if (++i < argc) {
236 aCommand = TCollection_AsciiString (argv[i]);
237 }
238 while (++i < argc) {
239 aCommand.AssignCat (" ");
240 aCommand.AssignCat (argv[i]);
7fd59977 241 }
242 break;
bf03eb83 243 } else {
244 cout << "Error: unsupported option " << argv[i] << endl;
7fd59977 245 }
246 }
bf03eb83 247
7fd59977 248 // *****************************************************************
249 // set signals
250 // *****************************************************************
d538d7a2 251 OSD::SetSignal(Standard_False);
7fd59977 252
bf03eb83 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
7fd59977 259 // *****************************************************************
260 // init X window and create display
261 // *****************************************************************
262#ifdef WNT
1d47d8d0 263 HWND hWnd = NULL;
7fd59977 264#endif
265
266 if (!Draw_Batch)
267#ifdef WNT
bf03eb83 268 Draw_Batch=!Init_Appli(hInst, hPrevInst, nShow, hWnd);
7fd59977 269#else
270 Draw_Batch=!Init_Appli();
271#endif
272 else
bf03eb83 273 cout << "DRAW is running in batch mode" << endl;
7fd59977 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
86be4295
A
310
311 if (getenv ("DRAWDEFAULT") == NULL)
7fd59977 312 {
86be4295 313 if (getenv ("CASROOT") == NULL)
7fd59977 314 {
315#ifdef WNT
86be4295 316 ReadInitFile ("ddefault");
7fd59977 317#else
86be4295
A
318 cout << " the CASROOT variable is mandatory to Run OpenCascade "<< endl;
319 cout << "No default file" << endl;
7fd59977 320#endif
321 }
322 else
323 {
86be4295
A
324 TCollection_AsciiString aDefStr (getenv ("CASROOT"));
325 aDefStr += "/src/DrawResources/DrawDefault";
326 ReadInitFile (aDefStr);
7fd59977 327 }
328 }
329 else
330 {
86be4295 331 ReadInitFile (getenv ("DRAWDEFAULT"));
7fd59977 332 }
333
bf03eb83 334 // read commands from file
86be4295 335 if (!aRunFile.IsEmpty()) {
bf03eb83 336 ReadInitFile (aRunFile);
337 // provide a clean exit, this is useful for some analysis tools
338 if ( ! isInteractiveForced )
7fd59977 339#ifndef WNT
bf03eb83 340 return;
341#else
342 ExitProcess(0);
7fd59977 343#endif
bf03eb83 344 }
7fd59977 345
bf03eb83 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 )
7fd59977 351#ifndef WNT
bf03eb83 352 return;
7fd59977 353#else
bf03eb83 354 ExitProcess(0);
7fd59977 355#endif
356 }
357
358 // *****************************************************************
359 // X loop
360 // *****************************************************************
361 if (XLoop) {
362#ifdef WNT
bf03eb83 363 Run_Appli(hWnd);
7fd59977 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
388void (*Draw_BeforeCommand)() = NULL;
389void (*Draw_AfterCommand)(Standard_Integer) = NULL;
390
bf03eb83 391Standard_Boolean Draw_Interprete(const char* com)
7fd59977 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
457Standard_Integer Tcl_AppInit (Tcl_Interp *)
458{
459 return 0;
460}
461
462//
463// for debug call
464//
465
466
467
468Standard_Integer Draw_Call (char *c)
469{
470 Standard_Integer r = theCommands.Eval(c);
471 cout << theCommands.Result() << endl;
472 return r;
473}
474
7fd59977 475//=================================================================================
476//
477//=================================================================================
478void 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
97385d61 484 static Plugin_MapOfFunctions theMapOfFunctions;
7fd59977 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();
63c629aa 519#ifdef DRAW_DEB
7fd59977 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}