0028110: Configuration - specify Unicode charset instead of multibyte in project...
[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
42cf5bc1 18#include <Draw.hxx>
7fd59977 19#include <Draw_Appli.hxx>
7fd59977 20#include <Draw_Drawable3D.hxx>
42cf5bc1 21#include <Draw_Failure.hxx>
7fd59977 22#include <Draw_Interpretor.hxx>
23#include <Draw_ProgressIndicator.hxx>
42cf5bc1 24#include <Draw_Window.hxx>
25#include <gp_Pnt2d.hxx>
26#include <OSD.hxx>
27#include <OSD_Environment.hxx>
7fd59977 28#include <OSD_SharedLibrary.hxx>
42cf5bc1 29#include <OSD_Timer.hxx>
30#include <Plugin_MapOfFunctions.hxx>
7fd59977 31#include <Resource_Manager.hxx>
7fd59977 32#include <Standard_ErrorHandler.hxx>
42cf5bc1 33#include <Standard_Stream.hxx>
34#include <Standard_Version.hxx>
35#include <TCollection_AsciiString.hxx>
6a0964c2 36
37#include <tcl.h>
6a0964c2 38// on MSVC, use #pragma to define name of the Tcl library to link with,
39// depending on Tcl version number
40#ifdef _MSC_VER
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")
46#undef STRINGIZE2
47#undef STRINGIZE1
48#endif
49
7fd59977 50extern Standard_Boolean Draw_ParseFailed;
7fd59977 51
52Standard_EXPORT Draw_Viewer dout;
53Standard_EXPORT Draw_Interpretor theCommands;
54Standard_EXPORT Standard_Boolean Draw_Batch;
55Standard_EXPORT Standard_Boolean Draw_Spying = Standard_False;
56Standard_EXPORT Standard_Boolean Draw_Chrono = Standard_False;
57Standard_EXPORT Standard_Boolean Draw_VirtualWindows = Standard_False;
58Standard_EXPORT Standard_Boolean ErrorMessages = Standard_True;
59
60static const char* ColorNames[MAXCOLOR] = {
61 "White","Red","Green","Blue","Cyan","Gold","Magenta",
62 "Maroon","Orange","Pink","Salmon","Violet","Yellow","Khaki","Coral"
63 };
64
65filebuf Draw_Spyfile;
66
67static ostream spystream(&Draw_Spyfile);
68
69static Standard_Boolean XLoop;
70
71static Handle(Draw_ProgressIndicator) PInd = NULL;
72
bf03eb83 73Standard_EXPORT Standard_Boolean Draw_Interprete(const char* command);
7fd59977 74// true if complete command
75
7fd59977 76// *******************************************************************
77// read an init file
78// *******************************************************************
57c28b61 79#ifdef _WIN32
7fd59977 80extern console_semaphore_value volatile console_semaphore;
ad03c234 81extern wchar_t console_command[1000];
7fd59977 82#endif
83
86be4295 84static void ReadInitFile (const TCollection_AsciiString& theFileName)
7fd59977 85{
86be4295 86 TCollection_AsciiString aPath = theFileName;
57c28b61 87#ifdef _WIN32
ad03c234 88 if (!Draw_Batch)
89 {
90 try
91 {
86be4295 92 aPath.ChangeAll ('\\', '/');
ad03c234 93 {
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));
96 }
7fd59977 97 console_semaphore = HAS_CONSOLE_COMMAND;
98 while (console_semaphore == HAS_CONSOLE_COMMAND)
ad03c234 99 {
7fd59977 100 Sleep(10);
ad03c234 101 }
7fd59977 102 }
103 catch(...) {
104 cout << "Error while reading a script file." << endl;
105 ExitProcess(0);
106 }
107 } else {
108#endif
ad03c234 109 char* com = new char [aPath.Length() + strlen ("source -encoding utf-8 ") + 2];
110 Sprintf (com, "source -encoding utf-8 %s", aPath.ToCString());
86be4295 111 Draw_Interprete (com);
7fd59977 112 delete [] com;
57c28b61 113#ifdef _WIN32
7fd59977 114 }
115#endif
116}
7fd59977 117
118//=======================================================================
119//function :
120//purpose : Set/Get Progress Indicator
121//=======================================================================
122void Draw::SetProgressBar(const Handle(Draw_ProgressIndicator)& thePI)
123{
124 PInd = thePI;
125}
126
127Handle(Draw_ProgressIndicator) Draw::GetProgressBar()
128{
129 return PInd;
130}
131
57c28b61 132#ifndef _WIN32
7fd59977 133/*--------------------------------------------------------*\
134| exitProc: finalization handler for Tcl/Tk thread. Forces parent process to die
135\*--------------------------------------------------------*/
136void exitProc(ClientData /*dc*/)
137{
138 if (!Draw_Batch) {
139 for (Standard_Integer id = 0; id < MAXVIEW; id++)
140 dout.DeleteView(id);
141 }
142}
143#endif
144
145// *******************************************************************
146// main
147// *******************************************************************
dac04bfa 148#ifdef _WIN32
ad03c234 149Standard_EXPORT void Draw_Appli(HINSTANCE hInst, HINSTANCE hPrevInst, int nShow, int argc, wchar_t** argv, const FDraw_InitAppli Draw_InitAppli)
7fd59977 150#else
ad03c234 151void Draw_Appli(int argc, char** argv, const FDraw_InitAppli Draw_InitAppli)
7fd59977 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");
ad03c234 158 const TCollection_ExtendedString aUserDllPath (aUserDllEnv.Value());
dac04bfa 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).
ad03c234 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;
dac04bfa 167 if (aFunc != NULL)
168 {
ad03c234 169 aFunc (aUserDllPath.ToWideString());
dac04bfa 170 }
171 else
172 {
ad03c234 173 //std::cerr << "SetDllDirectoryW() is not available on this system!\n";
dac04bfa 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_Boolean isInteractiveForced = Standard_False;
bf03eb83 188
bf03eb83 189 // parse command line
ad03c234 190 for (int anArgIter = 1; anArgIter < argc; ++anArgIter)
191 {
192 TCollection_AsciiString anArg (argv[anArgIter]);
193 anArg.LowerCase();
194 if (anArg == "-h"
195 || anArg == "--help")
bf03eb83 196 {
ad03c234 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";
bf03eb83 209 return;
7fd59977 210 }
ad03c234 211 else if (anArg == "-b")
212 {
bf03eb83 213 Draw_Batch = Standard_True;
ad03c234 214 }
215 else if (anArg == "-v")
216 {
7fd59977 217 // force virtual windows
218 Draw_VirtualWindows = Standard_True;
ad03c234 219 }
220 else if (anArg == "-i")
221 {
7fd59977 222 // force interactive
223 Draw_VirtualWindows = Standard_False;
224 isInteractiveForced = Standard_True;
ad03c234 225 }
226 else if (anArg == "-f") // -f option should be LAST!
227 {
7fd59977 228 Draw_VirtualWindows = !isInteractiveForced;
ad03c234 229 if (++anArgIter < argc)
230 {
231 aRunFile = TCollection_AsciiString (argv[anArgIter]);
7fd59977 232 }
233 break;
ad03c234 234 }
235 else if (anArg == "-c") // -c option should be LAST!
236 {
7fd59977 237 Draw_VirtualWindows = !isInteractiveForced;
ad03c234 238 if (++anArgIter < argc)
239 {
240 aCommand = TCollection_AsciiString (argv[anArgIter]);
bf03eb83 241 }
ad03c234 242 while (++anArgIter < argc)
243 {
bf03eb83 244 aCommand.AssignCat (" ");
ad03c234 245 aCommand.AssignCat (argv[anArgIter]);
7fd59977 246 }
247 break;
ad03c234 248 }
249 else
250 {
251 std::cout << "Error: unsupported option " << TCollection_AsciiString (argv[anArgIter]) << "\n";
7fd59977 252 }
253 }
bf03eb83 254
7fd59977 255 // *****************************************************************
256 // set signals
257 // *****************************************************************
d538d7a2 258 OSD::SetSignal(Standard_False);
7fd59977 259
bf03eb83 260#ifdef _WIN32
261 // in interactive mode, force Windows to report dll loading problems interactively
262 if ( ! Draw_VirtualWindows && ! Draw_Batch )
263 ::SetErrorMode (0);
264#endif
265
7fd59977 266 // *****************************************************************
267 // init X window and create display
268 // *****************************************************************
57c28b61 269#ifdef _WIN32
1d47d8d0 270 HWND hWnd = NULL;
7fd59977 271#endif
272
273 if (!Draw_Batch)
57c28b61 274#ifdef _WIN32
bf03eb83 275 Draw_Batch=!Init_Appli(hInst, hPrevInst, nShow, hWnd);
7fd59977 276#else
277 Draw_Batch=!Init_Appli();
278#endif
279 else
bf03eb83 280 cout << "DRAW is running in batch mode" << endl;
7fd59977 281
282 XLoop = !Draw_Batch;
ad03c234 283 if (XLoop)
284 {
7fd59977 285 // Default colors
ad03c234 286 for (int i = 0; i < MAXCOLOR; ++i)
287 {
288 if (!dout.DefineColor (i, ColorNames[i]))
289 {
290 std::cout <<"Could not allocate default color " << ColorNames[i] << std::endl;
291 }
7fd59977 292 }
293 }
294
295 // *****************************************************************
296 // set maximum precision for cout
297 // *****************************************************************
298 cout.precision(15);
299
300 // *****************************************************************
301 // standard commands
302 // *****************************************************************
303 Draw::BasicCommands(theCommands);
304 Draw::VariableCommands(theCommands);
305 Draw::UnitCommands(theCommands);
306 if (!Draw_Batch) Draw::GraphicCommands(theCommands);
307
308 // *****************************************************************
309 // user commands
310 // *****************************************************************
311 Draw_InitAppli(theCommands);
312
57c28b61 313#ifndef _WIN32
7fd59977 314 Tcl_CreateExitHandler(exitProc, 0);
315#endif
316
317 // *****************************************************************
318 // read init files
319 // *****************************************************************
320 // default
86be4295
A
321
322 if (getenv ("DRAWDEFAULT") == NULL)
7fd59977 323 {
86be4295 324 if (getenv ("CASROOT") == NULL)
7fd59977 325 {
57c28b61 326#ifdef _WIN32
86be4295 327 ReadInitFile ("ddefault");
7fd59977 328#else
86be4295
A
329 cout << " the CASROOT variable is mandatory to Run OpenCascade "<< endl;
330 cout << "No default file" << endl;
7fd59977 331#endif
332 }
333 else
334 {
86be4295
A
335 TCollection_AsciiString aDefStr (getenv ("CASROOT"));
336 aDefStr += "/src/DrawResources/DrawDefault";
337 ReadInitFile (aDefStr);
7fd59977 338 }
339 }
340 else
341 {
86be4295 342 ReadInitFile (getenv ("DRAWDEFAULT"));
7fd59977 343 }
344
bf03eb83 345 // read commands from file
86be4295 346 if (!aRunFile.IsEmpty()) {
bf03eb83 347 ReadInitFile (aRunFile);
348 // provide a clean exit, this is useful for some analysis tools
349 if ( ! isInteractiveForced )
57c28b61 350#ifndef _WIN32
bf03eb83 351 return;
352#else
353 ExitProcess(0);
7fd59977 354#endif
bf03eb83 355 }
7fd59977 356
bf03eb83 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 )
57c28b61 362#ifndef _WIN32
bf03eb83 363 return;
7fd59977 364#else
bf03eb83 365 ExitProcess(0);
7fd59977 366#endif
367 }
368
369 // *****************************************************************
370 // X loop
371 // *****************************************************************
372 if (XLoop) {
57c28b61 373#ifdef _WIN32
bf03eb83 374 Run_Appli(hWnd);
7fd59977 375#else
376 Run_Appli(Draw_Interprete);
377#endif
378 }
379 else
380 {
381 char cmd[255];
dde68833 382 for (;;)
383 {
7fd59977 384 cout << "Viewer>";
ad03c234 385 int i = -1;
7fd59977 386 do {
387 cin.get(cmd[++i]);
388 } while ((cmd[i] != '\n') && (!cin.fail()));
389 cmd[i] = '\0';
dde68833 390 Draw_Interprete(cmd);
391 }
7fd59977 392 }
57c28b61 393#ifdef _WIN32
7fd59977 394 // Destruction de l'application
395 Destroy_Appli(hInst);
396#endif
397}
398//#endif
399
400// User functions called before and after each command
401void (*Draw_BeforeCommand)() = NULL;
402void (*Draw_AfterCommand)(Standard_Integer) = NULL;
403
bf03eb83 404Standard_Boolean Draw_Interprete(const char* com)
7fd59977 405{
406
407 static Standard_Boolean first = Standard_True;
408 static Tcl_DString command;
409
410 if (first) {
411 first = Standard_False;
412 Tcl_DStringInit(&command);
413 }
414
ad03c234 415#ifdef _WIN32
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)))
7fd59977 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())
ad03c234 457 {
458 #ifdef _WIN32
459 const TCollection_ExtendedString aResWide (theCommands.Result());
460 std::wcout << aResWide.ToWideString() << std::endl;
461 #else
462 std::cout << theCommands.Result() << std::endl;
463 #endif
464 }
7fd59977 465
466 if (Draw_Chrono && hadchrono) {
467 tictac.Stop();
468 tictac.Show();
469 }
470
471 Tcl_DStringFree(&command);
472
473 return Standard_True;
474}
475
476//
477// for TCl
478//
479
480Standard_Integer Tcl_AppInit (Tcl_Interp *)
481{
482 return 0;
483}
484
485//
486// for debug call
487//
488
489
490
491Standard_Integer Draw_Call (char *c)
492{
493 Standard_Integer r = theCommands.Eval(c);
494 cout << theCommands.Result() << endl;
495 return r;
496}
497
7fd59977 498//=================================================================================
499//
500//=================================================================================
501void 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 ) {
506
97385d61 507 static Plugin_MapOfFunctions theMapOfFunctions;
7fd59977 508 OSD_Function f;
509
510 if(!theMapOfFunctions.IsBound(theKey)) {
511
512 Handle(Resource_Manager) aPluginResource = new Resource_Manager(theResourceFileName.ToCString(), theDefaultsDirectory, theUserDefaultsDirectory, Verbose);
513
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 Draw_Failure::Raise(aMsg);
519 }
520
521 TCollection_AsciiString aPluginLibrary("");
7c65581d 522#if !defined(_WIN32) || defined(__MINGW32__)
7fd59977 523 aPluginLibrary += "lib";
524#endif
525 aPluginLibrary += aPluginResource->Value(theKey.ToCString());
57c28b61 526#ifdef _WIN32
7fd59977 527 aPluginLibrary += ".dll";
528#elif __APPLE__
529 aPluginLibrary += ".dylib";
530#elif defined (HPUX) || defined(_hpux)
531 aPluginLibrary += ".sl";
532#else
533 aPluginLibrary += ".so";
534#endif
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();
0797d9d3 542#ifdef OCCT_DEBUG
7fd59977 543 cout << "could not open: " << aPluginResource->Value(theKey.ToCString())<< " ; reason: "<< error.ToCString() << endl;
544#endif
545 Draw_Failure::Raise(aMsg);
546 }
547 f = aSharedLibrary.DlSymb("PLUGINFACTORY");
548 if( f == NULL ) {
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 Draw_Failure::Raise(aMsg);
554 }
555 theMapOfFunctions.Bind(theKey, f);
556 }
557 else
558 f = theMapOfFunctions(theKey);
559
560// void (*fp) (Draw_Interpretor&, const TCollection_AsciiString&) = NULL;
561// fp = (void (*)(Draw_Interpretor&, const TCollection_AsciiString&)) f;
562// (*fp) (theDI, theKey);
563
564 void (*fp) (Draw_Interpretor&) = NULL;
565 fp = (void (*)(Draw_Interpretor&)) f;
566 (*fp) (theDI);
567
568}