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