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 // On ne cree pas tout de suite l'interpreteur tcl car s'il est detenu
154 // par une variable globale il est cree et ecrase avant le main().
158 //=======================================================================
160 //purpose : Il faut appeler cette fonction
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);
266 //=======================================================================
269 //=======================================================================
271 Standard_Boolean Draw_Interpretor::Remove(Standard_CString const n)
273 Standard_PCharacter pN;
275 pN=(Standard_PCharacter)n;
277 Standard_Integer result = Tcl_DeleteCommand(myInterp,pN);
281 //=======================================================================
284 //=======================================================================
286 Standard_CString Draw_Interpretor::Result() const
288 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 5)))
289 return Tcl_GetStringResult(myInterp);
291 return myInterp->result;
295 //=======================================================================
298 //=======================================================================
300 void Draw_Interpretor::Reset()
302 Tcl_ResetResult(myInterp);
305 //=======================================================================
308 //=======================================================================
310 Draw_Interpretor& Draw_Interpretor::Append(const Standard_CString s)
313 // Convert string to UTF-8 format for Tcl
314 Tcl_DString TclString;
315 Tcl_ExternalToUtfDString ( NULL, s, -1, &TclString );
316 Tcl_AppendResult ( myInterp, Tcl_DStringValue ( &TclString ), (Standard_CString)0 );
317 Tcl_DStringFree ( &TclString );
319 Tcl_AppendResult(myInterp,s,(Standard_CString)0);
324 //=======================================================================
327 //=======================================================================
329 Draw_Interpretor& Draw_Interpretor::Append(const TCollection_AsciiString& s)
331 return Append (s.ToCString());
334 //=======================================================================
337 //=======================================================================
339 Draw_Interpretor& Draw_Interpretor::Append(const TCollection_ExtendedString& theString)
342 // Convert string to UTF-8 format for Tcl
343 char *str = new char[theString.LengthOfCString()+1];
344 theString.ToUTF8CString (str);
345 Tcl_AppendResult ( myInterp, str, (Standard_CString)0 );
348 // put as ascii string, replacing non-ascii characters by '?'
349 TCollection_AsciiString str (theString, '?');
350 Tcl_AppendResult(myInterp,str.ToCString(),(Standard_CString)0);
355 //=======================================================================
358 //=======================================================================
360 Draw_Interpretor& Draw_Interpretor::Append(const Standard_Integer i)
364 Tcl_AppendResult(myInterp,c,(Standard_CString)0);
368 //=======================================================================
371 //=======================================================================
373 Draw_Interpretor& Draw_Interpretor::Append(const Standard_Real r)
376 sprintf(s,"%.17g",r);
377 Tcl_AppendResult(myInterp,s,(Standard_CString)0);
381 //=======================================================================
384 //=======================================================================
386 Draw_Interpretor& Draw_Interpretor::Append(const Standard_SStream& s)
388 #ifdef USE_STL_STREAM
389 return Append (s.str().c_str());
391 // Note: use dirty tricks -- unavoidable with old streams
392 TCollection_AsciiString aStr (((Standard_SStream&)AReason).str(), AReason.pcount());
393 ((Standard_SStream&)AReason).freeze (false);
394 return Append (aStr.ToCString());
398 //=======================================================================
399 //function : AppendElement
401 //=======================================================================
403 void Draw_Interpretor::AppendElement(const Standard_CString s)
406 // Convert string to UTF-8 format for Tcl
407 Tcl_DString TclString;
408 Tcl_ExternalToUtfDString ( NULL, s, -1, &TclString );
409 Tcl_AppendElement ( myInterp, Tcl_DStringValue ( &TclString ) );
410 Tcl_DStringFree ( &TclString );
413 //AppendElement is declared as (Tcl_Interp *interp, char *string)
415 Tcl_AppendElement(myInterp,(char*) s);
417 Tcl_AppendElement(myInterp, s);
422 //=======================================================================
425 //=======================================================================
427 Standard_Integer Draw_Interpretor::Eval(const Standard_CString line)
429 Standard_PCharacter pLine;
431 pLine=(Standard_PCharacter)line;
433 return Tcl_Eval(myInterp,pLine);
437 //=======================================================================
440 //=======================================================================
442 Standard_Integer Draw_Interpretor::RecordAndEval(const Standard_CString line,
443 const Standard_Integer flags)
445 Standard_PCharacter pLine;
447 pLine=(Standard_PCharacter)line;
448 return Tcl_RecordAndEval(myInterp,pLine,flags);
451 //=======================================================================
452 //function : EvalFile
454 //=======================================================================
456 Standard_Integer Draw_Interpretor::EvalFile(const Standard_CString fname)
458 Standard_PCharacter pfname;
460 pfname=(Standard_PCharacter)fname;
461 return Tcl_EvalFile(myInterp,pfname);
464 //=======================================================================
467 //=======================================================================
469 Standard_Boolean Draw_Interpretor::Complete(const Standard_CString line)
471 Standard_PCharacter pLine;
473 pLine=(Standard_PCharacter)line;
474 return Tcl_CommandComplete(pLine);
477 //=======================================================================
480 //=======================================================================
482 void Draw_Interpretor::Destroy()
485 #if ((TCL_MAJOR_VERSION > 8) || ((TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION >= 4)))
490 catch (Standard_Failure) {
492 cout <<"Tcl_Exit have an exeption" << endl;
502 //=======================================================================
505 //=======================================================================
507 Draw_PInterp Draw_Interpretor::Interp() const
509 Standard_DomainError_Raise_if (myInterp==NULL , "No call for Draw_Interpretor::Init()");
513 void Draw_Interpretor::Set(const Draw_PInterp& PIntrp)
516 Tcl_DeleteInterp(myInterp);
517 isAllocated = Standard_False;