/[dtapublic]/projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkmain.c
ViewVC logotype

Diff of /projs/ets/trunk/src/c_tk_base_7_5_w_mods/tkmain.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 70 by dashley, Sat Nov 5 10:54:17 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2    
3  /*  /*
4   * tkMain.c --   * tkMain.c --
5   *   *
6   *      This file contains a generic main program for Tk-based applications.   *      This file contains a generic main program for Tk-based applications.
7   *      It can be used as-is for many applications, just by supplying a   *      It can be used as-is for many applications, just by supplying a
8   *      different appInitProc procedure for each specific application.   *      different appInitProc procedure for each specific application.
9   *      Or, it can be used as a template for creating new main programs   *      Or, it can be used as a template for creating new main programs
10   *      for Tk applications.   *      for Tk applications.
11   *   *
12   * Copyright (c) 1990-1994 The Regents of the University of California.   * Copyright (c) 1990-1994 The Regents of the University of California.
13   * Copyright (c) 1994-1997 Sun Microsystems, Inc.   * Copyright (c) 1994-1997 Sun Microsystems, Inc.
14   *   *
15   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
16   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
17   *   *
18   * RCS: @(#) $Id: tkmain.c,v 1.1.1.1 2001/06/13 05:05:07 dtashley Exp $   * RCS: @(#) $Id: tkmain.c,v 1.1.1.1 2001/06/13 05:05:07 dtashley Exp $
19   */   */
20    
21  #define MODULE_TK_MAIN  #define MODULE_TK_MAIN
22    
23  #include <ctype.h>  #include <ctype.h>
24  #include <stdio.h>  #include <stdio.h>
25  #include <string.h>  #include <string.h>
26  #include <tcl.h>  #include <tcl.h>
27  #include <tclInt.h>  #include <tclInt.h>
28    
29  #include "appinit.h"  #include "appinit.h"
30  #include "build_config.h"  #include "build_config.h"
31  #include "extninit.h"  #include "extninit.h"
32  #include "msgstrs.h"  #include "msgstrs.h"
33    
34  #include "tk.h"  #include "tk.h"
35  #include "tkInt.h"  #include "tkInt.h"
36  #ifdef NO_STDLIB_H  #ifdef NO_STDLIB_H
37  #   include "../compat/stdlib.h"  #   include "../compat/stdlib.h"
38  #else  #else
39  #   include <stdlib.h>  #   include <stdlib.h>
40  #endif  #endif
41  #ifdef __WIN32__  #ifdef __WIN32__
42  #include "tkWinInt.h"  #include "tkWinInt.h"
43  #endif  #endif
44    
45    
46  typedef struct ThreadSpecificData {  typedef struct ThreadSpecificData {
47      Tcl_Interp *interp;         /* Interpreter for this thread. */      Tcl_Interp *interp;         /* Interpreter for this thread. */
48      Tcl_DString command;        /* Used to assemble lines of terminal input      Tcl_DString command;        /* Used to assemble lines of terminal input
49                                   * into Tcl commands. */                                   * into Tcl commands. */
50      Tcl_DString line;           /* Used to read the next line from the      Tcl_DString line;           /* Used to read the next line from the
51                                   * terminal input. */                                   * terminal input. */
52      int tty;                    /* Non-zero means standard input is a      int tty;                    /* Non-zero means standard input is a
53                                   * terminal-like device.  Zero means it's                                   * terminal-like device.  Zero means it's
54                                   * a file. */                                   * a file. */
55  } ThreadSpecificData;  } ThreadSpecificData;
56  Tcl_ThreadDataKey dataKey;  Tcl_ThreadDataKey dataKey;
57    
58  /*  /*
59   * Declarations for various library procedures and variables (don't want   * Declarations for various library procedures and variables (don't want
60   * to include tkInt.h or tkPort.h here, because people might copy this   * to include tkInt.h or tkPort.h here, because people might copy this
61   * file out of the Tk source directory to make their own modified versions).   * file out of the Tk source directory to make their own modified versions).
62   * Note: don't declare "exit" here even though a declaration is really   * Note: don't declare "exit" here even though a declaration is really
63   * needed, because it will conflict with a declaration elsewhere on   * needed, because it will conflict with a declaration elsewhere on
64   * some systems.   * some systems.
65   */   */
66    
67  #if !defined(__WIN32__) && !defined(_WIN32)  #if !defined(__WIN32__) && !defined(_WIN32)
68  extern int              isatty _ANSI_ARGS_((int fd));  extern int              isatty _ANSI_ARGS_((int fd));
69  extern char *           strrchr _ANSI_ARGS_((CONST char *string, int c));  extern char *           strrchr _ANSI_ARGS_((CONST char *string, int c));
70  #endif  #endif
71  extern void             TkpDisplayWarning _ANSI_ARGS_((char *msg,  extern void             TkpDisplayWarning _ANSI_ARGS_((char *msg,
72                              char *title));                              char *title));
73    
74  /*  /*
75   * Forward declarations for procedures defined later in this file.   * Forward declarations for procedures defined later in this file.
76   */   */
77    
78  static void             Prompt _ANSI_ARGS_((Tcl_Interp *interp, int partial));  static void             Prompt _ANSI_ARGS_((Tcl_Interp *interp, int partial));
79  static void             StdinProc _ANSI_ARGS_((ClientData clientData,  static void             StdinProc _ANSI_ARGS_((ClientData clientData,
80                              int mask));                              int mask));
81    
82  /*  /*
83   *----------------------------------------------------------------------   *----------------------------------------------------------------------
84   *   *
85   * Tk_MainEx --   * Tk_MainEx --
86   *   *
87   *      Main program for Wish and most other Tk-based applications.   *      Main program for Wish and most other Tk-based applications.
88   *   *
89   * Results:   * Results:
90   *      None. This procedure never returns (it exits the process when   *      None. This procedure never returns (it exits the process when
91   *      it's done.   *      it's done.
92   *   *
93   * Side effects:   * Side effects:
94   *      This procedure initializes the Tk world and then starts   *      This procedure initializes the Tk world and then starts
95   *      interpreting commands;  almost anything could happen, depending   *      interpreting commands;  almost anything could happen, depending
96   *      on the script being interpreted.   *      on the script being interpreted.
97   *   *
98   *----------------------------------------------------------------------   *----------------------------------------------------------------------
99   */   */
100  void  void
101  Tk_MainEx(argc, argv, appInitProc, interp)  Tk_MainEx(argc, argv, appInitProc, interp)
102      int argc;                           /* Number of arguments. */      int argc;                           /* Number of arguments. */
103      char **argv;                        /* Array of argument strings. */      char **argv;                        /* Array of argument strings. */
104      Tcl_AppInitProc *appInitProc;       /* Application-specific initialization      Tcl_AppInitProc *appInitProc;       /* Application-specific initialization
105                                                           * procedure to call after most                                                           * procedure to call after most
106                                                           * initialization but before starting                                                           * initialization but before starting
107                                                           * to execute commands.  This input                                                           * to execute commands.  This input
108                                           * parameter is ignored because of the                                           * parameter is ignored because of the
109                                           * integration of the code automatically                                           * integration of the code automatically
110                                           * generated by "mktclapp".                                           * generated by "mktclapp".
111                                           */                                           */
112      Tcl_Interp *interp;      Tcl_Interp *interp;
113  {  {
114      char *args, *fileName;      char *args, *fileName;
115      char buf[TCL_INTEGER_SPACE];      char buf[TCL_INTEGER_SPACE];
116      int code;      int code;
117      size_t length;      size_t length;
118      Tcl_Channel inChannel, outChannel;      Tcl_Channel inChannel, outChannel;
119      Tcl_DString argString;      Tcl_DString argString;
120      ThreadSpecificData *tsdPtr;      ThreadSpecificData *tsdPtr;
121  #ifdef __WIN32__  #ifdef __WIN32__
122      HANDLE handle;      HANDLE handle;
123  #endif  #endif
124  #if 1  #if 1
125      /* Dope the environment variables so that the first place the      /* Dope the environment variables so that the first place the
126      ** run-time code searches for the library files is in the "baked in"      ** run-time code searches for the library files is in the "baked in"
127      ** libraries.  Over time, this should be changed to permanently      ** libraries.  Over time, this should be changed to permanently
128      ** bake things in so that this trick isn't necessary.      ** bake things in so that this trick isn't necessary.
129      */      */
130      putenv("TCL_LIBRARY=" ET_TCL_LIBRARY);      putenv("TCL_LIBRARY=" ET_TCL_LIBRARY);
131      putenv("TK_LIBRARY=" ET_TK_LIBRARY);      putenv("TK_LIBRARY=" ET_TK_LIBRARY);
132    
133      /* Run the local initialization procedure for the ET module.      /* Run the local initialization procedure for the ET module.
134      ** This will dope the interpreter so that attempts to load the      ** This will dope the interpreter so that attempts to load the
135      ** library files will get redirected internally.      ** library files will get redirected internally.
136      */      */
137    
138      Et_DoInit(interp);      Et_DoInit(interp);
139  #endif  #endif
140    
141  /*     appInitProc = Et_DoInit; */  /*     appInitProc = Et_DoInit; */
142    
143      /*      /*
144       * Ensure that we are getting the matching version of Tcl.  This is       * Ensure that we are getting the matching version of Tcl.  This is
145       * really only an issue when Tk is loaded dynamically.       * really only an issue when Tk is loaded dynamically.
146       */       */
147    
148      if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {      if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) {
149          abort();          abort();
150      }      }
151    
152      tsdPtr = (ThreadSpecificData *)      tsdPtr = (ThreadSpecificData *)
153          Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));          Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
154            
155      Tcl_FindExecutable(argv[0]);      Tcl_FindExecutable(argv[0]);
156      tsdPtr->interp = interp;      tsdPtr->interp = interp;
157    
158  #if (defined(__WIN32__) || defined(MAC_TCL))  #if (defined(__WIN32__) || defined(MAC_TCL))
159      Tk_InitConsoleChannels(interp);      Tk_InitConsoleChannels(interp);
160  #endif  #endif
161            
162  #ifdef TCL_MEM_DEBUG  #ifdef TCL_MEM_DEBUG
163      Tcl_InitMemory(interp);      Tcl_InitMemory(interp);
164  #endif  #endif
165    
166      /*      /*
167       * Parse command-line arguments.  A leading "-file" argument is       * Parse command-line arguments.  A leading "-file" argument is
168       * ignored (a historical relic from the distant past).  If the       * ignored (a historical relic from the distant past).  If the
169       * next argument doesn't start with a "-" then strip it off and       * next argument doesn't start with a "-" then strip it off and
170       * use it as the name of a script file to process.       * use it as the name of a script file to process.
171       */       */
172    
173      fileName = TclGetStartupScriptFileName();      fileName = TclGetStartupScriptFileName();
174    
175      if (argc > 1) {      if (argc > 1) {
176          length = strlen(argv[1]);          length = strlen(argv[1]);
177          if ((length >= 2) && (strncmp(argv[1], "-file", length) == 0)) {          if ((length >= 2) && (strncmp(argv[1], "-file", length) == 0)) {
178              argc--;              argc--;
179              argv++;              argv++;
180          }          }
181      }      }
182      if (fileName == NULL) {      if (fileName == NULL) {
183          if ((argc > 1) && (argv[1][0] != '-')) {          if ((argc > 1) && (argv[1][0] != '-')) {
184              fileName = argv[1];              fileName = argv[1];
185              argc--;              argc--;
186              argv++;              argv++;
187          }          }
188      }      }
189            
190      /*      /*
191       * Make command-line arguments available in the Tcl variables "argc"       * Make command-line arguments available in the Tcl variables "argc"
192       * and "argv".       * and "argv".
193       */       */
194    
195      args = Tcl_Merge(argc-1, argv+1);      args = Tcl_Merge(argc-1, argv+1);
196      Tcl_ExternalToUtfDString(NULL, args, -1, &argString);      Tcl_ExternalToUtfDString(NULL, args, -1, &argString);
197      Tcl_SetVar(interp, "argv", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY);      Tcl_SetVar(interp, "argv", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY);
198      Tcl_DStringFree(&argString);      Tcl_DStringFree(&argString);
199      ckfree(args);      ckfree(args);
200      sprintf(buf, "%d", argc-1);      sprintf(buf, "%d", argc-1);
201    
202      if (fileName == NULL) {      if (fileName == NULL) {
203          Tcl_ExternalToUtfDString(NULL, argv[0], -1, &argString);          Tcl_ExternalToUtfDString(NULL, argv[0], -1, &argString);
204      } else {      } else {
205          fileName = Tcl_ExternalToUtfDString(NULL, fileName, -1, &argString);          fileName = Tcl_ExternalToUtfDString(NULL, fileName, -1, &argString);
206      }      }
207      Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);      Tcl_SetVar(interp, "argc", buf, TCL_GLOBAL_ONLY);
208      Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY);      Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&argString), TCL_GLOBAL_ONLY);
209    
210      /*      /*
211       * Set the "tcl_interactive" variable.       * Set the "tcl_interactive" variable.
212       */       */
213    
214      /*      /*
215       * For now, under Windows, we assume we are not running as a console mode       * For now, under Windows, we assume we are not running as a console mode
216       * app, so we need to use the GUI console.  In order to enable this, we       * app, so we need to use the GUI console.  In order to enable this, we
217       * always claim to be running on a tty.  This probably isn't the right       * always claim to be running on a tty.  This probably isn't the right
218       * way to do it.       * way to do it.
219       */       */
220    
221  #ifdef __WIN32__  #ifdef __WIN32__
222      handle = GetStdHandle(STD_INPUT_HANDLE);      handle = GetStdHandle(STD_INPUT_HANDLE);
223    
224      if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)      if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)
225               || (GetFileType(handle) == FILE_TYPE_UNKNOWN)) {               || (GetFileType(handle) == FILE_TYPE_UNKNOWN)) {
226          /*          /*
227           * If it's a bad or closed handle, then it's been connected           * If it's a bad or closed handle, then it's been connected
228           * to a wish console window.           * to a wish console window.
229           */           */
230    
231          tsdPtr->tty = 1;          tsdPtr->tty = 1;
232      } else if (GetFileType(handle) == FILE_TYPE_CHAR) {      } else if (GetFileType(handle) == FILE_TYPE_CHAR) {
233          /*          /*
234           * A character file handle is a tty by definition.           * A character file handle is a tty by definition.
235           */           */
236    
237          tsdPtr->tty = 1;          tsdPtr->tty = 1;
238      } else {      } else {
239          tsdPtr->tty = 0;          tsdPtr->tty = 0;
240      }      }
241    
242  #else  #else
243      tsdPtr->tty = isatty(0);      tsdPtr->tty = isatty(0);
244  #endif  #endif
245      Tcl_SetVar(interp, "tcl_interactive",      Tcl_SetVar(interp, "tcl_interactive",
246              ((fileName == NULL) && tsdPtr->tty) ? "1" : "0", TCL_GLOBAL_ONLY);              ((fileName == NULL) && tsdPtr->tty) ? "1" : "0", TCL_GLOBAL_ONLY);
247    
248      /*      /*
249       * Invoke application-specific initialization.       * Invoke application-specific initialization.
250       */       */
251    
252      if ((*appInitProc)(interp) != TCL_OK) {      if ((*appInitProc)(interp) != TCL_OK) {
253          TkpDisplayWarning(Tcl_GetStringResult(interp),          TkpDisplayWarning(Tcl_GetStringResult(interp),
254                  "Application initialization failed");                  "Application initialization failed");
255      }      }
256    
257     /* Register any extensions that should be registered for the     /* Register any extensions that should be registered for the
258     ** executable currently being built.     ** executable currently being built.
259     */     */
260     ExtninitInit(interp);     ExtninitInit(interp);
261    
262     /* Set a Tcl variable to indicate the particular product     /* Set a Tcl variable to indicate the particular product
263     ** we are building.  This is used in the startup message script     ** we are building.  This is used in the startup message script
264     ** to announce product version, and may be used other     ** to announce product version, and may be used other
265     ** places, as well.     ** places, as well.
266     */     */
267     Tcl_SetVar(interp,     Tcl_SetVar(interp,
268                BUILD_CONFIG_PRODUCT_NAME_VARIABLE,                BUILD_CONFIG_PRODUCT_NAME_VARIABLE,
269                BUILD_CONFIG_STATIC_WISH_ALIAS,                BUILD_CONFIG_STATIC_WISH_ALIAS,
270                TCL_GLOBAL_ONLY);                TCL_GLOBAL_ONLY);
271    
272     /* Set  Tcl variable to indicate the relese version of the     /* Set  Tcl variable to indicate the relese version of the
273     ** product we are building.  This is used in the startup message script     ** product we are building.  This is used in the startup message script
274     ** to announce product version, and may be used other     ** to announce product version, and may be used other
275     ** places, as well.     ** places, as well.
276     */     */
277     Tcl_SetVar(interp,     Tcl_SetVar(interp,
278                BUILD_CONFIG_PRODUCT_VERSION_VARIABLE,                BUILD_CONFIG_PRODUCT_VERSION_VARIABLE,
279                BUILD_CONFIG_RELEASE_VERSION,                BUILD_CONFIG_RELEASE_VERSION,
280                TCL_GLOBAL_ONLY);                TCL_GLOBAL_ONLY);
281    
282     /* Change the title of the console window to reflect     /* Change the title of the console window to reflect
283     ** the product name and version.     ** the product name and version.
284     */     */
285     Tcl_GlobalEval(interp,     Tcl_GlobalEval(interp,
286                    "wm title . \""                    "wm title . \""
287                    BUILD_CONFIG_STATIC_WISH_ALIAS                    BUILD_CONFIG_STATIC_WISH_ALIAS
288                    " v"                    " v"
289                    BUILD_CONFIG_RELEASE_VERSION                    BUILD_CONFIG_RELEASE_VERSION
290                    "\"");                    "\"");
291    
292     /* Output the introductory message to the console.     /* Output the introductory message to the console.
293     ** The script called is generic and applies to both     ** The script called is generic and applies to both
294     ** IjuScripter and IjuConsole.     ** IjuScripter and IjuConsole.
295     */     */
296     Tcl_GlobalEval(interp, BUILD_CONFIG_StartupMessageScript);     Tcl_GlobalEval(interp, BUILD_CONFIG_StartupMessageScript);
297    
298     /*     /*
299      * Invoke the script specified on the command line, if any.      * Invoke the script specified on the command line, if any.
300      */      */
301    
302      if (fileName != NULL) {      if (fileName != NULL) {
303          Tcl_ResetResult(interp);          Tcl_ResetResult(interp);
304          code = Tcl_EvalFile(interp, fileName);          code = Tcl_EvalFile(interp, fileName);
305          if (code != TCL_OK) {          if (code != TCL_OK) {
306              /*              /*
307               * The following statement guarantees that the errorInfo               * The following statement guarantees that the errorInfo
308               * variable is set properly.               * variable is set properly.
309               */               */
310    
311              Tcl_AddErrorInfo(interp, "");              Tcl_AddErrorInfo(interp, "");
312              TkpDisplayWarning(Tcl_GetVar(interp, "errorInfo",              TkpDisplayWarning(Tcl_GetVar(interp, "errorInfo",
313                      TCL_GLOBAL_ONLY), "Error in startup script");                      TCL_GLOBAL_ONLY), "Error in startup script");
314              Tcl_DeleteInterp(interp);              Tcl_DeleteInterp(interp);
315              Tcl_Exit(1);              Tcl_Exit(1);
316          }          }
317          tsdPtr->tty = 0;          tsdPtr->tty = 0;
318      } else {      } else {
319    
320          /*          /*
321           * Evaluate the .rc file, if one has been specified.           * Evaluate the .rc file, if one has been specified.
322           */           */
323    
324          Tcl_SourceRCFile(interp);          Tcl_SourceRCFile(interp);
325    
326          /*          /*
327           * Establish a channel handler for stdin.           * Establish a channel handler for stdin.
328           */           */
329    
330          inChannel = Tcl_GetStdChannel(TCL_STDIN);          inChannel = Tcl_GetStdChannel(TCL_STDIN);
331          if (inChannel) {          if (inChannel) {
332              Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc,              Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc,
333                      (ClientData) inChannel);                      (ClientData) inChannel);
334          }          }
335          if (tsdPtr->tty) {          if (tsdPtr->tty) {
336              Prompt(interp, 0);              Prompt(interp, 0);
337          }          }
338      }      }
339      Tcl_DStringFree(&argString);      Tcl_DStringFree(&argString);
340    
341      outChannel = Tcl_GetStdChannel(TCL_STDOUT);      outChannel = Tcl_GetStdChannel(TCL_STDOUT);
342      if (outChannel) {      if (outChannel) {
343          Tcl_Flush(outChannel);          Tcl_Flush(outChannel);
344      }      }
345      Tcl_DStringInit(&tsdPtr->command);      Tcl_DStringInit(&tsdPtr->command);
346      Tcl_DStringInit(&tsdPtr->line);      Tcl_DStringInit(&tsdPtr->line);
347      Tcl_ResetResult(interp);      Tcl_ResetResult(interp);
348    
349      /*      /*
350       * Loop infinitely, waiting for commands to execute.  When there       * Loop infinitely, waiting for commands to execute.  When there
351       * are no windows left, Tk_MainLoop returns and we exit.       * are no windows left, Tk_MainLoop returns and we exit.
352       */       */
353    
354      Tk_MainLoop();      Tk_MainLoop();
355      Tcl_DeleteInterp(interp);      Tcl_DeleteInterp(interp);
356      Tcl_Exit(0);      Tcl_Exit(0);
357  }  }
358    
359  /*  /*
360   *----------------------------------------------------------------------   *----------------------------------------------------------------------
361   *   *
362   * StdinProc --   * StdinProc --
363   *   *
364   *      This procedure is invoked by the event dispatcher whenever   *      This procedure is invoked by the event dispatcher whenever
365   *      standard input becomes readable.  It grabs the next line of   *      standard input becomes readable.  It grabs the next line of
366   *      input characters, adds them to a command being assembled, and   *      input characters, adds them to a command being assembled, and
367   *      executes the command if it's complete.   *      executes the command if it's complete.
368   *   *
369   * Results:   * Results:
370   *      None.   *      None.
371   *   *
372   * Side effects:   * Side effects:
373   *      Could be almost arbitrary, depending on the command that's   *      Could be almost arbitrary, depending on the command that's
374   *      typed.   *      typed.
375   *   *
376   *----------------------------------------------------------------------   *----------------------------------------------------------------------
377   */   */
378    
379      /* ARGSUSED */      /* ARGSUSED */
380  static void  static void
381  StdinProc(clientData, mask)  StdinProc(clientData, mask)
382      ClientData clientData;              /* Not used. */      ClientData clientData;              /* Not used. */
383      int mask;                           /* Not used. */      int mask;                           /* Not used. */
384  {  {
385      static int gotPartial = 0;      static int gotPartial = 0;
386      char *cmd;      char *cmd;
387      int code, count;      int code, count;
388      Tcl_Channel chan = (Tcl_Channel) clientData;      Tcl_Channel chan = (Tcl_Channel) clientData;
389      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)      ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
390              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));              Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
391      Tcl_Interp *interp = tsdPtr->interp;      Tcl_Interp *interp = tsdPtr->interp;
392    
393      count = Tcl_Gets(chan, &tsdPtr->line);      count = Tcl_Gets(chan, &tsdPtr->line);
394    
395      if (count < 0) {      if (count < 0) {
396          if (!gotPartial) {          if (!gotPartial) {
397              if (tsdPtr->tty) {              if (tsdPtr->tty) {
398                  Tcl_Exit(0);                  Tcl_Exit(0);
399              } else {              } else {
400                  Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan);                  Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan);
401              }              }
402              return;              return;
403          }          }
404      }      }
405    
406      (void) Tcl_DStringAppend(&tsdPtr->command, Tcl_DStringValue(      (void) Tcl_DStringAppend(&tsdPtr->command, Tcl_DStringValue(
407              &tsdPtr->line), -1);              &tsdPtr->line), -1);
408      cmd = Tcl_DStringAppend(&tsdPtr->command, "\n", -1);      cmd = Tcl_DStringAppend(&tsdPtr->command, "\n", -1);
409      Tcl_DStringFree(&tsdPtr->line);      Tcl_DStringFree(&tsdPtr->line);
410      if (!Tcl_CommandComplete(cmd)) {      if (!Tcl_CommandComplete(cmd)) {
411          gotPartial = 1;          gotPartial = 1;
412          goto prompt;          goto prompt;
413      }      }
414      gotPartial = 0;      gotPartial = 0;
415    
416      /*      /*
417       * Disable the stdin channel handler while evaluating the command;       * Disable the stdin channel handler while evaluating the command;
418       * otherwise if the command re-enters the event loop we might       * otherwise if the command re-enters the event loop we might
419       * process commands from stdin before the current command is       * process commands from stdin before the current command is
420       * finished.  Among other things, this will trash the text of the       * finished.  Among other things, this will trash the text of the
421       * command being evaluated.       * command being evaluated.
422       */       */
423    
424      Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan);      Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan);
425      code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL);      code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL);
426            
427      chan = Tcl_GetStdChannel(TCL_STDIN);      chan = Tcl_GetStdChannel(TCL_STDIN);
428      if (chan) {      if (chan) {
429          Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc,          Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc,
430                  (ClientData) chan);                  (ClientData) chan);
431      }      }
432      Tcl_DStringFree(&tsdPtr->command);      Tcl_DStringFree(&tsdPtr->command);
433      if (Tcl_GetStringResult(interp)[0] != '\0') {      if (Tcl_GetStringResult(interp)[0] != '\0') {
434          if ((code != TCL_OK) || (tsdPtr->tty)) {          if ((code != TCL_OK) || (tsdPtr->tty)) {
435              chan = Tcl_GetStdChannel(TCL_STDOUT);              chan = Tcl_GetStdChannel(TCL_STDOUT);
436              if (chan) {              if (chan) {
437                  Tcl_WriteObj(chan, Tcl_GetObjResult(interp));                  Tcl_WriteObj(chan, Tcl_GetObjResult(interp));
438                  Tcl_WriteChars(chan, "\n", 1);                  Tcl_WriteChars(chan, "\n", 1);
439              }              }
440          }          }
441      }      }
442    
443      /*      /*
444       * Output a prompt.       * Output a prompt.
445       */       */
446    
447      prompt:      prompt:
448      if (tsdPtr->tty) {      if (tsdPtr->tty) {
449          Prompt(interp, gotPartial);          Prompt(interp, gotPartial);
450      }      }
451      Tcl_ResetResult(interp);      Tcl_ResetResult(interp);
452  }  }
453    
454  /*  /*
455   *----------------------------------------------------------------------   *----------------------------------------------------------------------
456   *   *
457   * Prompt --   * Prompt --
458   *   *
459   *      Issue a prompt on standard output, or invoke a script   *      Issue a prompt on standard output, or invoke a script
460   *      to issue the prompt.   *      to issue the prompt.
461   *   *
462   * Results:   * Results:
463   *      None.   *      None.
464   *   *
465   * Side effects:   * Side effects:
466   *      A prompt gets output, and a Tcl script may be evaluated   *      A prompt gets output, and a Tcl script may be evaluated
467   *      in interp.   *      in interp.
468   *   *
469   *----------------------------------------------------------------------   *----------------------------------------------------------------------
470   */   */
471    
472  static void  static void
473  Prompt(interp, partial)  Prompt(interp, partial)
474      Tcl_Interp *interp;                 /* Interpreter to use for prompting. */      Tcl_Interp *interp;                 /* Interpreter to use for prompting. */
475      int partial;                        /* Non-zero means there already      int partial;                        /* Non-zero means there already
476                                           * exists a partial command, so use                                           * exists a partial command, so use
477                                           * the secondary prompt. */                                           * the secondary prompt. */
478  {  {
479      char *promptCmd;      char *promptCmd;
480      int code;      int code;
481      Tcl_Channel outChannel, errChannel;      Tcl_Channel outChannel, errChannel;
482    
483      promptCmd = Tcl_GetVar(interp,      promptCmd = Tcl_GetVar(interp,
484          partial ? "tcl_prompt2" : "tcl_prompt1", TCL_GLOBAL_ONLY);          partial ? "tcl_prompt2" : "tcl_prompt1", TCL_GLOBAL_ONLY);
485      if (promptCmd == NULL) {      if (promptCmd == NULL) {
486  defaultPrompt:  defaultPrompt:
487          if (!partial) {          if (!partial) {
488    
489              /*              /*
490               * We must check that outChannel is a real channel - it               * We must check that outChannel is a real channel - it
491               * is possible that someone has transferred stdout out of               * is possible that someone has transferred stdout out of
492               * this interpreter with "interp transfer".               * this interpreter with "interp transfer".
493               */               */
494    
495              outChannel = Tcl_GetChannel(interp, "stdout", NULL);              outChannel = Tcl_GetChannel(interp, "stdout", NULL);
496              if (outChannel != (Tcl_Channel) NULL) {              if (outChannel != (Tcl_Channel) NULL) {
497                  Tcl_WriteChars(outChannel, "% ", 2);                  Tcl_WriteChars(outChannel, "% ", 2);
498              }              }
499          }          }
500      } else {      } else {
501          code = Tcl_Eval(interp, promptCmd);          code = Tcl_Eval(interp, promptCmd);
502          if (code != TCL_OK) {          if (code != TCL_OK) {
503              Tcl_AddErrorInfo(interp,              Tcl_AddErrorInfo(interp,
504                      "\n    (script that generates prompt)");                      "\n    (script that generates prompt)");
505              /*              /*
506               * We must check that errChannel is a real channel - it               * We must check that errChannel is a real channel - it
507               * is possible that someone has transferred stderr out of               * is possible that someone has transferred stderr out of
508               * this interpreter with "interp transfer".               * this interpreter with "interp transfer".
509               */               */
510                            
511              errChannel = Tcl_GetChannel(interp, "stderr", NULL);              errChannel = Tcl_GetChannel(interp, "stderr", NULL);
512              if (errChannel != (Tcl_Channel) NULL) {              if (errChannel != (Tcl_Channel) NULL) {
513                  Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));                  Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp));
514                  Tcl_WriteChars(errChannel, "\n", 1);                  Tcl_WriteChars(errChannel, "\n", 1);
515              }              }
516              goto defaultPrompt;              goto defaultPrompt;
517          }          }
518      }      }
519      outChannel = Tcl_GetChannel(interp, "stdout", NULL);      outChannel = Tcl_GetChannel(interp, "stdout", NULL);
520      if (outChannel != (Tcl_Channel) NULL) {      if (outChannel != (Tcl_Channel) NULL) {
521          Tcl_Flush(outChannel);          Tcl_Flush(outChannel);
522      }      }
523  }  }
524    
525  /* End of tkmain.c */  /* End of tkmain.c */

Legend:
Removed from v.70  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25