1 // File: Draw_Interpretor.cxx
2 // Created: Thu Feb 23 17:53:09 1995
3 // Author: Remi LEQUETTE
7 #include <Draw_Interpretor.ixx>
8 #include <Draw_Appli.hxx>
9 #include <Standard_SStream.hxx>
10 #include <Standard_RangeError.hxx>
11 #include <Standard_ErrorHandler.hxx>
12 #include <Standard_Macro.hxx>
14 #include <TCollection_AsciiString.hxx>
15 #include <TCollection_ExtendedString.hxx>
21 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 1)))
26 // Auxiliary tool to convert strings in command arguments from UTF-8
27 // (Tcl internal encoding since Tcl 8.1) to system local encoding,
28 // normally extended Ascii as expected by OCC commands
30 class TclUTFToLocalStringSentry {
34 TclUTFToLocalStringSentry (int argc, const char **argv) :
36 TclArgv(new Tcl_DString[argc]),
39 for (; nb < argc; nb++ ) {
40 Tcl_UtfToExternalDString ( NULL, argv[nb], -1, &TclArgv[nb] );
41 Argv[nb] = Tcl_DStringValue ( &TclArgv[nb] );
45 ~TclUTFToLocalStringSentry ()
48 while ( nb-- >0 ) Tcl_DStringFree ( &TclArgv[nb] );
52 TclUTFToLocalStringSentry (int, const char **argv) : Argv((char**)argv) {}
55 const char **GetArgv () const { return (const char **)Argv; }
69 CData(Draw_CommandFunction ff, Draw_Interpretor* ii) : f(ff), i(ii) {}
70 Draw_CommandFunction f;
75 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))) && !defined(USE_NON_CONST)
76 static Standard_Integer CommandCmd
77 (ClientData clientData, Tcl_Interp *interp,
78 Standard_Integer argc, const char* argv[])
80 static Standard_Integer CommandCmd
81 (ClientData clientData, Tcl_Interp *interp,
82 Standard_Integer argc, char* argv[])
85 static Standard_Integer code;
87 CData* C = (CData*) clientData;
92 // OCC63: Convert strings from UTF-8 to local encoding, normally expected by OCC commands
93 TclUTFToLocalStringSentry anArgs ( argc, (const char**)argv );
95 Draw_Interpretor& di = *(C->i);
96 Standard_Integer fres = C->f ( di, argc, anArgs.GetArgv() );
100 catch (Standard_Failure) {
102 Handle(Standard_Failure) E = Standard_Failure::Caught();
104 // fail if Draw_ExitOnCatch is set
106 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4))) && !defined(USE_NON_CONST)
107 const char* cc = Tcl_GetVar(interp,
108 "Draw_ExitOnCatch",TCL_GLOBAL_ONLY);
110 char* const cc = Tcl_GetVar(interp,
111 "Draw_ExitOnCatch",TCL_GLOBAL_ONLY);
114 cout << "An exception was caught " << E << endl;
116 if (cc && atoi(cc)) {
120 Tcl_Eval(interp,"exit");
124 // get the error message
126 ss << "** Exception ** " << E << ends ;
127 #ifdef USE_STL_STREAM
128 Tcl_SetResult(interp,(char*)(ss.str().c_str()),TCL_VOLATILE);
130 Tcl_SetResult(interp,(char*)(ss.str()),TCL_VOLATILE);
139 static void CommandDelete (ClientData clientData)
141 CData *C = (CData*) clientData;
145 //=======================================================================
146 //function : Draw_Interpretor
148 //=======================================================================
150 Draw_Interpretor::Draw_Interpretor() :
151 isAllocated(Standard_False)
153 // The tcl interpreter is not created immediately as it is kept
154 // by a global variable and created and deleted before the main().
158 //=======================================================================
160 //purpose : It is necessary to call this function
161 //=======================================================================
163 void Draw_Interpretor::Init()
166 Tcl_DeleteInterp(myInterp);
167 isAllocated=Standard_True;
168 myInterp=Tcl_CreateInterp();
171 //=======================================================================
172 //function : Draw_Interpretor
174 //=======================================================================
176 Draw_Interpretor::Draw_Interpretor(const Draw_PInterp& p) :
177 isAllocated(Standard_False),
182 //=======================================================================
185 //=======================================================================
187 void Draw_Interpretor::Add(const Standard_CString n,
188 const Standard_CString help,
189 const Draw_CommandFunction f,
190 const Standard_CString group)
192 //void Draw_Interpretor::Add(const Standard_CString n,
193 // const Standard_CString help,
194 // const Draw_CommandFunction& f,
195 // const Standard_CString group)
198 Standard_PCharacter pN, pHelp, pGroup;
200 pN=(Standard_PCharacter)n;
201 pHelp=(Standard_PCharacter)help;
202 pGroup=(Standard_PCharacter)group;
204 if (myInterp==NULL) Init();
206 CData* C = new CData(f,this);
208 Tcl_CreateCommand(myInterp, pN ,CommandCmd, (ClientData) C, CommandDelete);
211 Tcl_SetVar2(myInterp,"Draw_Helps", pN, pHelp, TCL_GLOBAL_ONLY);
212 Tcl_SetVar2(myInterp,"Draw_Groups",pGroup,pN,
213 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
215 //=======================================================================
218 //=======================================================================
219 void Draw_Interpretor::Add(const Standard_CString n,
220 const Standard_CString help,
221 const Standard_CString file_name,
222 const Draw_CommandFunction f,
223 const Standard_CString group)
225 Standard_PCharacter pN, pHelp, pGroup, pFileName;
227 pN=(Standard_PCharacter)n;
228 pHelp=(Standard_PCharacter)help;
229 pGroup=(Standard_PCharacter)group;
230 pFileName=(Standard_PCharacter)file_name;
232 if (myInterp==NULL) Init();
234 CData* C = new CData(f,this);
235 Standard_Integer length, num_slashes, ii, jj, kk;
236 Tcl_CreateCommand(myInterp,pN,CommandCmd, (ClientData) C, CommandDelete);
239 Tcl_SetVar2(myInterp,"Draw_Helps",pN,pHelp,TCL_GLOBAL_ONLY);
240 Tcl_SetVar2(myInterp,"Draw_Groups",pGroup,pN,
241 TCL_GLOBAL_ONLY|TCL_APPEND_VALUE|TCL_LIST_ELEMENT);
242 length = strlen(pFileName) ;
244 new char[length + 1] ;
248 while (num_slashes < 3 && ii >= 0) {
249 if (file_name[ii] == '/') {
255 for (kk = ii+2 , jj =0 ; kk < length ; kk++) {
256 a_string[jj] = file_name[kk] ;
259 a_string[jj] = '\0' ;
261 Tcl_SetVar2(myInterp,"Draw_Files",pN,a_string,TCL_GLOBAL_ONLY);
268 //=======================================================================
271 //=======================================================================
273 Standard_Boolean Draw_Interpretor::Remove(Standard_CString const n)
275 Standard_PCharacter pN;
277 pN=(Standard_PCharacter)n;
279 Standard_Integer result = Tcl_DeleteCommand(myInterp,pN);
283 //=======================================================================
286 //=======================================================================
288 Standard_CString Draw_Interpretor::Result() const
290 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
291 return Tcl_GetStringResult(myInterp);
293 return myInterp->result;
297 //=======================================================================
300 //=======================================================================
302 void Draw_Interpretor::Reset()
304 Tcl_ResetResult(myInterp);
307 //=======================================================================
310 //=======================================================================
312 Draw_Interpretor& Draw_Interpretor::Append(const Standard_CString s)
315 // Convert string to UTF-8 format for Tcl
316 Tcl_DString TclString;
317 Tcl_ExternalToUtfDString ( NULL, s, -1, &TclString );
318 Tcl_AppendResult ( myInterp, Tcl_DStringValue ( &TclString ), (Standard_CString)0 );
319 Tcl_DStringFree ( &TclString );
321 Tcl_AppendResult(myInterp,s,(Standard_CString)0);
326 //=======================================================================
329 //=======================================================================
331 Draw_Interpretor& Draw_Interpretor::Append(const TCollection_AsciiString& s)
333 return Append (s.ToCString());
336 //=======================================================================
339 //=======================================================================
341 Draw_Interpretor& Draw_Interpretor::Append(const TCollection_ExtendedString& theString)
344 // Convert string to UTF-8 format for Tcl
345 char *str = new char[theString.LengthOfCString()+1];
346 theString.ToUTF8CString (str);
347 Tcl_AppendResult ( myInterp, str, (Standard_CString)0 );
350 // put as ascii string, replacing non-ascii characters by '?'
351 TCollection_AsciiString str (theString, '?');
352 Tcl_AppendResult(myInterp,str.ToCString(),(Standard_CString)0);
357 //=======================================================================
360 //=======================================================================
362 Draw_Interpretor& Draw_Interpretor::Append(const Standard_Integer i)
366 Tcl_AppendResult(myInterp,c,(Standard_CString)0);
370 //=======================================================================
373 //=======================================================================
375 Draw_Interpretor& Draw_Interpretor::Append(const Standard_Real r)
378 sprintf(s,"%.17g",r);
379 Tcl_AppendResult(myInterp,s,(Standard_CString)0);
383 //=======================================================================
386 //=======================================================================
388 Draw_Interpretor& Draw_Interpretor::Append(const Standard_SStream& s)
390 #ifdef USE_STL_STREAM
391 return Append (s.str().c_str());
393 // Note: use dirty tricks -- unavoidable with old streams
394 TCollection_AsciiString aStr (((Standard_SStream&)AReason).str(), AReason.pcount());
395 ((Standard_SStream&)AReason).freeze (false);
396 return Append (aStr.ToCString());
400 //=======================================================================
401 //function : AppendElement
403 //=======================================================================
405 void Draw_Interpretor::AppendElement(const Standard_CString s)
408 // Convert string to UTF-8 format for Tcl
409 Tcl_DString TclString;
410 Tcl_ExternalToUtfDString ( NULL, s, -1, &TclString );
411 Tcl_AppendElement ( myInterp, Tcl_DStringValue ( &TclString ) );
412 Tcl_DStringFree ( &TclString );
415 //AppendElement is declared as (Tcl_Interp *interp, char *string)
417 Tcl_AppendElement(myInterp,(char*) s);
419 Tcl_AppendElement(myInterp, s);
424 //=======================================================================
427 //=======================================================================
429 Standard_Integer Draw_Interpretor::Eval(const Standard_CString line)
431 Standard_PCharacter pLine;
433 pLine=(Standard_PCharacter)line;
435 return Tcl_Eval(myInterp,pLine);
439 //=======================================================================
442 //=======================================================================
444 Standard_Integer Draw_Interpretor::RecordAndEval(const Standard_CString line,
445 const Standard_Integer flags)
447 Standard_PCharacter pLine;
449 pLine=(Standard_PCharacter)line;
450 return Tcl_RecordAndEval(myInterp,pLine,flags);
453 //=======================================================================
454 //function : EvalFile
456 //=======================================================================
458 Standard_Integer Draw_Interpretor::EvalFile(const Standard_CString fname)
460 Standard_PCharacter pfname;
462 pfname=(Standard_PCharacter)fname;
463 return Tcl_EvalFile(myInterp,pfname);
466 //=======================================================================
469 //=======================================================================
471 Standard_Boolean Draw_Interpretor::Complete(const Standard_CString line)
473 Standard_PCharacter pLine;
475 pLine=(Standard_PCharacter)line;
476 return Tcl_CommandComplete(pLine);
479 //=======================================================================
482 //=======================================================================
484 void Draw_Interpretor::Destroy()
487 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
492 catch (Standard_Failure) {
494 cout <<"Tcl_Exit have an exeption" << endl;
504 //=======================================================================
507 //=======================================================================
509 Draw_PInterp Draw_Interpretor::Interp() const
511 Standard_DomainError_Raise_if (myInterp==NULL , "No call for Draw_Interpretor::Init()");
515 void Draw_Interpretor::Set(const Draw_PInterp& PIntrp)
518 Tcl_DeleteInterp(myInterp);
519 isAllocated = Standard_False;