diff options
Diffstat (limited to 'generic/tkMain.c')
-rw-r--r-- | generic/tkMain.c | 534 |
1 files changed, 278 insertions, 256 deletions
diff --git a/generic/tkMain.c b/generic/tkMain.c index 34f9054..fee669e 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -1,76 +1,141 @@ -/* +/* * tkMain.c -- * * This file contains a generic main program for Tk-based applications. * It can be used as-is for many applications, just by supplying a - * different appInitProc procedure for each specific application. - * Or, it can be used as a template for creating new main programs - * for Tk applications. + * different appInitProc function for each specific application. Or, it + * can be used as a template for creating new main programs for Tk + * applications. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * - * See the file "license.terms" for information on usage and redistribution - * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +/** + * On Windows, this file needs to be compiled twice, once with + * TK_ASCII_MAIN defined. This way both Tk_MainEx and Tk_MainExW + * can be implemented, sharing the same source code. */ +#if defined(TK_ASCII_MAIN) +# ifdef UNICODE +# undef UNICODE +# undef _UNICODE +# else +# define UNICODE +# define _UNICODE +# endif +#endif #include <ctype.h> #include <stdio.h> #include <string.h> -#include <tcl.h> -#include <tclInt.h> -#include <tk.h> #include "tkInt.h" #ifdef NO_STDLIB_H # include "../compat/stdlib.h" #else # include <stdlib.h> #endif + +/* + * The default prompt used when the user has not overridden it. + */ + +#define DEFAULT_PRIMARY_PROMPT "% " + +/* + * This file can be compiled on Windows in UNICODE mode, as well as + * on all other platforms using the native encoding. This is done + * by using the normal Windows functions like _tcscmp, but on + * platforms which don't have <tchar.h> we have to translate that + * to strcmp here. + */ #ifdef __WIN32__ -#include "tkWinInt.h" +# include "tkWinInt.h" +#else +# define TCHAR char +# define TEXT(arg) arg +# define _tcscmp strcmp +# define _tcslen strlen +# define _tcsncmp strncmp #endif + #ifdef MAC_OSX_TK #include "tkMacOSXInt.h" #endif - -typedef struct ThreadSpecificData { - Tcl_Interp *interp; /* Interpreter for this thread. */ - Tcl_DString command; /* Used to assemble lines of terminal input - * into Tcl commands. */ - Tcl_DString line; /* Used to read the next line from the - * terminal input. */ - int tty; /* Non-zero means standard input is a - * terminal-like device. Zero means it's - * a file. */ -} ThreadSpecificData; -static Tcl_ThreadDataKey dataKey; +/* + * Further on, in UNICODE mode, we need to use Tcl_NewUnicodeObj, + * while otherwise NewNativeObj is needed (which provides proper + * conversion from native encoding to UTF-8). + */ +#ifdef UNICODE +# define NewNativeObj Tcl_NewUnicodeObj +#else /* !UNICODE */ + static Tcl_Obj *NewNativeObj(char *string, int length) { + Tcl_Obj *obj; + Tcl_DString ds; + Tcl_ExternalToUtfDString(NULL, string, length, &ds); + obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)); + Tcl_DStringFree(&ds); + return obj; +} +#endif /* !UNICODE */ /* - * Declarations for various library procedures and variables (don't want - * to include tkInt.h or tkPort.h here, because people might copy this - * file out of the Tk source directory to make their own modified versions). - * Note: don't declare "exit" here even though a declaration is really - * needed, because it will conflict with a declaration elsewhere on - * some systems. + * Declarations for various library functions and variables (don't want to + * include tkInt.h or tkPort.h here, because people might copy this file out + * of the Tk source directory to make their own modified versions). Note: do + * not declare "exit" here even though a declaration is really needed, because + * it will conflict with a declaration elsewhere on some systems. */ -#if !defined(__WIN32__) && !defined(_WIN32) -#if !defined(MAC_TCL) -extern int isatty _ANSI_ARGS_((int fd)); +#if defined(_WIN32) +#define isatty WinIsTty +static int WinIsTty(int fd) { + HANDLE handle; + /* + * For now, under Windows, we assume we are not running as a console mode + * app, so we need to use the GUI console. In order to enable this, we + * always claim to be running on a tty. This probably isn't the right way + * to do it. + */ + handle = GetStdHandle(STD_INPUT_HANDLE + fd); + /* + * If it's a bad or closed handle, then it's been connected to a wish + * console window. A character file handle is a tty by definition. + */ + return (handle == INVALID_HANDLE_VALUE) || (handle == 0) + || (GetFileType(handle) == FILE_TYPE_UNKNOWN) + || (GetFileType(handle) == FILE_TYPE_CHAR); +} #else -#include <unistd.h> -#endif -extern char * strrchr _ANSI_ARGS_((CONST char *string, int c)); +extern int isatty(int fd); #endif +typedef struct InteractiveState { + Tcl_Channel input; /* The standard input channel from which lines + * are read. */ + int tty; /* Non-zero means standard input is a + * terminal-like device. Zero means it's a + * file. */ + Tcl_DString command; /* Used to assemble lines of terminal input + * into Tcl commands. */ + Tcl_DString line; /* Used to read the next line from the + * terminal input. */ + int gotPartial; + Tcl_Interp *interp; /* Interpreter that evaluates interactive + * commands. */ +} InteractiveState; + /* - * Forward declarations for procedures defined later in this file. + * Forward declarations for functions defined later in this file. */ -static void Prompt _ANSI_ARGS_((Tcl_Interp *interp, int partial)); -static void StdinProc _ANSI_ARGS_((ClientData clientData, - int mask)); +static void Prompt(Tcl_Interp *interp, InteractiveState *isPtr); +static void StdinProc(ClientData clientData, int mask); /* *---------------------------------------------------------------------- @@ -80,101 +145,103 @@ static void StdinProc _ANSI_ARGS_((ClientData clientData, * Main program for Wish and most other Tk-based applications. * * Results: - * None. This procedure never returns (it exits the process when - * it's done. + * None. This function never returns (it exits the process when it's + * done). * * Side effects: - * This procedure initializes the Tk world and then starts - * interpreting commands; almost anything could happen, depending - * on the script being interpreted. + * This function initializes the Tk world and then starts interpreting + * commands; almost anything could happen, depending on the script being + * interpreted. * *---------------------------------------------------------------------- */ + void -Tk_MainEx(argc, argv, appInitProc, interp) - int argc; /* Number of arguments. */ - char **argv; /* Array of argument strings. */ - Tcl_AppInitProc *appInitProc; /* Application-specific initialization - * procedure to call after most - * initialization but before starting - * to execute commands. */ - Tcl_Interp *interp; +Tk_MainEx( + int argc, /* Number of arguments. */ + TCHAR **argv, /* Array of argument strings. */ + Tcl_AppInitProc *appInitProc, + /* Application-specific initialization + * function to call after most initialization + * but before starting to execute commands. */ + Tcl_Interp *interp) { - Tcl_Obj *argvPtr; + Tcl_Obj *path, *argvPtr, *appName; + const char *encodingName; int code, nullStdin = 0; - size_t length; - Tcl_Channel inChannel, outChannel; - Tcl_DString appName; - ThreadSpecificData *tsdPtr; -#ifdef __WIN32__ - HANDLE handle; -#endif + Tcl_Channel chan; + InteractiveState is; /* - * Ensure that we are getting the matching version of Tcl. This is - * really only an issue when Tk is loaded dynamically. + * Ensure that we are getting a compatible version of Tcl. This is really + * only an issue when Tk is loaded dynamically. */ - if (Tcl_InitStubs(interp, TCL_VERSION, 1) == NULL) { + if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { abort(); } - tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - - Tcl_FindExecutable(argv[0]); - tsdPtr->interp = interp; - Tcl_Preserve((ClientData) interp); + Tcl_InitMemory(interp); + + is.interp = interp; + is.gotPartial = 0; + Tcl_Preserve(interp); -#if (defined(__WIN32__) || defined(MAC_TCL)) +#if defined(__WIN32__) Tk_InitConsoleChannels(interp); #endif #ifdef MAC_OSX_TK - if (TclGetStartupScriptFileName() == NULL) { - TkMacOSXDefaultStartupScript(); + if (Tcl_GetStartupScript(NULL) == NULL) { + TkMacOSXDefaultStartupScript(); } #endif - -#ifdef TCL_MEM_DEBUG - Tcl_InitMemory(interp); -#endif /* - * Parse command-line arguments. A leading "-file" argument is - * ignored (a historical relic from the distant past). If the - * next argument doesn't start with a "-" then strip it off and - * use it as the name of a script file to process. + * If the application has not already set a startup script, parse the + * first few command line arguments to determine the script path and + * encoding. */ - if (argc > 1) { - length = strlen(argv[1]); - if ((length >= 2) && (strncmp(argv[1], "-file", length) == 0)) { - argc--; - argv++; - } - } - if (TclGetStartupScriptFileName() == NULL) { - if ((argc > 1) && (argv[1][0] != '-')) { - TclSetStartupScriptFileName(argv[1]); + if (NULL == Tcl_GetStartupScript(NULL)) { + size_t length; + + /* + * Check whether first 3 args (argv[1] - argv[3]) look like + * -encoding ENCODING FILENAME + * or like + * FILENAME + * or like + * -file FILENAME (ancient history support only) + */ + + if ((argc > 3) && (0 == _tcscmp(TEXT("-encoding"), argv[1])) + && (TEXT('-') != argv[3][0])) { + Tcl_Obj *value = NewNativeObj(argv[2], -1); + Tcl_SetStartupScript(NewNativeObj(argv[3], -1), Tcl_GetString(value)); + Tcl_DecrRefCount(value); + argc -= 3; + argv += 3; + } else if ((argc > 1) && (TEXT('-') != argv[1][0])) { + Tcl_SetStartupScript(NewNativeObj(argv[1], -1), NULL); argc--; argv++; + } else if ((argc > 2) && (length = _tcslen(argv[1])) + && (length > 1) && (0 == _tcsncmp(TEXT("-file"), argv[1], length)) + && (TEXT('-') != argv[2][0])) { + Tcl_SetStartupScript(NewNativeObj(argv[2], -1), NULL); + argc -= 2; + argv += 2; } } - - /* - * Make command-line arguments available in the Tcl variables "argc" - * and "argv". - */ - if (TclGetStartupScriptFileName() == NULL) { - Tcl_ExternalToUtfDString(NULL, argv[0], -1, &appName); + path = Tcl_GetStartupScript(&encodingName); + if (path == NULL) { + appName = NewNativeObj(argv[0], -1); } else { - TclSetStartupScriptFileName(Tcl_ExternalToUtfDString(NULL, - TclGetStartupScriptFileName(), -1, &appName)); + appName = path; } - Tcl_SetVar(interp, "argv0", Tcl_DStringValue(&appName), TCL_GLOBAL_ONLY); - Tcl_DStringFree(&appName); + Tcl_SetVar2Ex(interp, "argv0", NULL, appName, TCL_GLOBAL_ONLY); argc--; argv++; @@ -182,11 +249,7 @@ Tk_MainEx(argc, argv, appInitProc, interp) argvPtr = Tcl_NewListObj(0, NULL); while (argc--) { - Tcl_DString ds; - Tcl_ExternalToUtfDString(NULL, *argv++, -1, &ds); - Tcl_ListObjAppendElement(NULL, argvPtr, Tcl_NewStringObj( - Tcl_DStringValue(&ds), Tcl_DStringLength(&ds))); - Tcl_DStringFree(&ds); + Tcl_ListObjAppendElement(NULL, argvPtr, NewNativeObj(*argv++, -1)); } Tcl_SetVar2Ex(interp, "argv", NULL, argvPtr, TCL_GLOBAL_ONLY); @@ -194,74 +257,45 @@ Tk_MainEx(argc, argv, appInitProc, interp) * Set the "tcl_interactive" variable. */ -#ifdef __WIN32__ - /* - * For now, under Windows, we assume we are not running as a console mode - * app, so we need to use the GUI console. In order to enable this, we - * always claim to be running on a tty. This probably isn't the right - * way to do it. - */ - - handle = GetStdHandle(STD_INPUT_HANDLE); - - if ((handle == INVALID_HANDLE_VALUE) || (handle == 0) - || (GetFileType(handle) == FILE_TYPE_UNKNOWN)) { - /* - * If it's a bad or closed handle, then it's been connected - * to a wish console window. - */ - - tsdPtr->tty = 1; - } else if (GetFileType(handle) == FILE_TYPE_CHAR) { - /* - * A character file handle is a tty by definition. - */ - - tsdPtr->tty = 1; - } else { - tsdPtr->tty = 0; - } - -#else - tsdPtr->tty = isatty(0); -#endif + is.tty = isatty(0); #if defined(MAC_OSX_TK) /* * On TkAqua, if we don't have a TTY and stdin is a special character file * of length 0, (e.g. /dev/null, which is what Finder sets when double * clicking Wish) then use the GUI console. */ - - if (!tsdPtr->tty) { + + if (!is.tty) { struct stat st; nullStdin = fstat(0, &st) || (S_ISCHR(st.st_mode) && !st.st_blocks); } #endif - Tcl_SetVar(interp, "tcl_interactive", - ((TclGetStartupScriptFileName() == NULL) && (tsdPtr->tty - || nullStdin)) ? "1" : "0", TCL_GLOBAL_ONLY); + Tcl_SetVar2Ex(interp, "tcl_interactive", NULL, + Tcl_NewIntObj(!path && (is.tty || nullStdin)), TCL_GLOBAL_ONLY); /* * Invoke application-specific initialization. */ - if ((*appInitProc)(interp) != TCL_OK) { + if (appInitProc(interp) != TCL_OK) { TkpDisplayWarning(Tcl_GetStringResult(interp), - "Application initialization failed"); + "application-specific initialization failed"); } /* - * Invoke the script specified on the command line, if any. + * Invoke the script specified on the command line, if any. Must fetch it + * again, as the appInitProc might have reset it. */ - if (TclGetStartupScriptFileName() != NULL) { + path = Tcl_GetStartupScript(&encodingName); + if (path != NULL) { Tcl_ResetResult(interp); - code = Tcl_EvalFile(interp, TclGetStartupScriptFileName()); + code = Tcl_FSEvalFileEx(interp, path, encodingName); if (code != TCL_OK) { /* - * The following statement guarantees that the errorInfo - * variable is set properly. + * The following statement guarantees that the errorInfo variable + * is set properly. */ Tcl_AddErrorInfo(interp, ""); @@ -270,7 +304,7 @@ Tk_MainEx(argc, argv, appInitProc, interp) Tcl_DeleteInterp(interp); Tcl_Exit(1); } - tsdPtr->tty = 0; + is.tty = 0; } else { /* @@ -283,32 +317,32 @@ Tk_MainEx(argc, argv, appInitProc, interp) * Establish a channel handler for stdin. */ - inChannel = Tcl_GetStdChannel(TCL_STDIN); - if (inChannel) { - Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc, - (ClientData) inChannel); + is.input = Tcl_GetStdChannel(TCL_STDIN); + if (is.input) { + Tcl_CreateChannelHandler(is.input, TCL_READABLE, StdinProc, &is); } - if (tsdPtr->tty) { - Prompt(interp, 0); + if (is.tty) { + Prompt(interp, &is); } } - outChannel = Tcl_GetStdChannel(TCL_STDOUT); - if (outChannel) { - Tcl_Flush(outChannel); + chan = Tcl_GetStdChannel(TCL_STDOUT); + if (chan) { + Tcl_Flush(chan); } - Tcl_DStringInit(&tsdPtr->command); - Tcl_DStringInit(&tsdPtr->line); + Tcl_DStringInit(&is.command); + Tcl_DStringInit(&is.line); Tcl_ResetResult(interp); /* - * Loop infinitely, waiting for commands to execute. When there - * are no windows left, Tk_MainLoop returns and we exit. + * Loop infinitely, waiting for commands to execute. When there are no + * windows left, Tk_MainLoop returns and we exit. */ Tk_MainLoop(); Tcl_DeleteInterp(interp); - Tcl_Release((ClientData) interp); + Tcl_Release(interp); + Tcl_SetStartupScript(NULL, NULL); Tcl_Exit(0); } @@ -317,78 +351,70 @@ Tk_MainEx(argc, argv, appInitProc, interp) * * StdinProc -- * - * This procedure is invoked by the event dispatcher whenever - * standard input becomes readable. It grabs the next line of - * input characters, adds them to a command being assembled, and - * executes the command if it's complete. + * This function is invoked by the event dispatcher whenever standard + * input becomes readable. It grabs the next line of input characters, + * adds them to a command being assembled, and executes the command if + * it's complete. * * Results: * None. * * Side effects: - * Could be almost arbitrary, depending on the command that's - * typed. + * Could be almost arbitrary, depending on the command that's typed. * *---------------------------------------------------------------------- */ /* ARGSUSED */ static void -StdinProc(clientData, mask) - ClientData clientData; /* Not used. */ - int mask; /* Not used. */ +StdinProc( + ClientData clientData, /* The state of interactive cmd line */ + int mask) /* Not used. */ { - static int gotPartial = 0; char *cmd; int code, count; - Tcl_Channel chan = (Tcl_Channel) clientData; - ThreadSpecificData *tsdPtr = (ThreadSpecificData *) - Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - Tcl_Interp *interp = tsdPtr->interp; - - count = Tcl_Gets(chan, &tsdPtr->line); - - if (count < 0) { - if (!gotPartial) { - if (tsdPtr->tty) { - Tcl_Exit(0); - } else { - Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan); - } - return; - } + InteractiveState *isPtr = clientData; + Tcl_Channel chan = isPtr->input; + Tcl_Interp *interp = isPtr->interp; + + count = Tcl_Gets(chan, &isPtr->line); + + if (count < 0 && !isPtr->gotPartial) { + if (isPtr->tty) { + Tcl_Exit(0); + } else { + Tcl_DeleteChannelHandler(chan, StdinProc, isPtr); + } + return; } - (void) Tcl_DStringAppend(&tsdPtr->command, Tcl_DStringValue( - &tsdPtr->line), -1); - cmd = Tcl_DStringAppend(&tsdPtr->command, "\n", -1); - Tcl_DStringFree(&tsdPtr->line); + Tcl_DStringAppend(&isPtr->command, Tcl_DStringValue(&isPtr->line), -1); + cmd = Tcl_DStringAppend(&isPtr->command, "\n", -1); + Tcl_DStringFree(&isPtr->line); if (!Tcl_CommandComplete(cmd)) { - gotPartial = 1; - goto prompt; + isPtr->gotPartial = 1; + goto prompt; } - gotPartial = 0; + isPtr->gotPartial = 0; /* * Disable the stdin channel handler while evaluating the command; - * otherwise if the command re-enters the event loop we might - * process commands from stdin before the current command is - * finished. Among other things, this will trash the text of the - * command being evaluated. + * otherwise if the command re-enters the event loop we might process + * commands from stdin before the current command is finished. Among other + * things, this will trash the text of the command being evaluated. */ - Tcl_CreateChannelHandler(chan, 0, StdinProc, (ClientData) chan); + Tcl_CreateChannelHandler(chan, 0, StdinProc, isPtr); code = Tcl_RecordAndEval(interp, cmd, TCL_EVAL_GLOBAL); - - chan = Tcl_GetStdChannel(TCL_STDIN); - if (chan) { - Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, - (ClientData) chan); + + isPtr->input = Tcl_GetStdChannel(TCL_STDIN); + if (isPtr->input) { + Tcl_CreateChannelHandler(isPtr->input, TCL_READABLE, StdinProc, isPtr); } - Tcl_DStringFree(&tsdPtr->command); + Tcl_DStringFree(&isPtr->command); if (Tcl_GetStringResult(interp)[0] != '\0') { - if ((code != TCL_OK) || (tsdPtr->tty)) { - chan = Tcl_GetStdChannel(TCL_STDOUT); + if ((code != TCL_OK) || (isPtr->tty)) { + chan = Tcl_GetStdChannel((code != TCL_OK) ? TCL_STDERR : TCL_STDOUT); if (chan) { Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); Tcl_WriteChars(chan, "\n", 1); @@ -397,12 +423,12 @@ StdinProc(clientData, mask) } /* - * Output a prompt. + * If a tty stdin is still around, output a prompt. */ - prompt: - if (tsdPtr->tty) { - Prompt(interp, gotPartial); + prompt: + if (isPtr->tty && (isPtr->input != NULL)) { + Prompt(interp, isPtr); } Tcl_ResetResult(interp); } @@ -412,68 +438,64 @@ StdinProc(clientData, mask) * * Prompt -- * - * Issue a prompt on standard output, or invoke a script - * to issue the prompt. + * Issue a prompt on standard output, or invoke a script to issue the + * prompt. * * Results: * None. * * Side effects: - * A prompt gets output, and a Tcl script may be evaluated - * in interp. + * A prompt gets output, and a Tcl script may be evaluated in interp. * *---------------------------------------------------------------------- */ static void -Prompt(interp, partial) - Tcl_Interp *interp; /* Interpreter to use for prompting. */ - int partial; /* Non-zero means there already - * exists a partial command, so use - * the secondary prompt. */ +Prompt( + Tcl_Interp *interp, /* Interpreter to use for prompting. */ + InteractiveState *isPtr) /* InteractiveState. */ { - Tcl_Obj *promptCmd; + Tcl_Obj *promptCmdPtr; int code; - Tcl_Channel outChannel, errChannel; - - promptCmd = Tcl_GetVar2Ex(interp, - partial ? "tcl_prompt2" : "tcl_prompt1", NULL, TCL_GLOBAL_ONLY); - if (promptCmd == NULL) { -defaultPrompt: - if (!partial) { - - /* - * We must check that outChannel is a real channel - it - * is possible that someone has transferred stdout out of - * this interpreter with "interp transfer". - */ - - outChannel = Tcl_GetChannel(interp, "stdout", NULL); - if (outChannel != (Tcl_Channel) NULL) { - Tcl_WriteChars(outChannel, "% ", 2); - } + Tcl_Channel chan; + + promptCmdPtr = Tcl_GetVar2Ex(interp, + isPtr->gotPartial ? "tcl_prompt2" : "tcl_prompt1", NULL, TCL_GLOBAL_ONLY); + if (promptCmdPtr == NULL) { + defaultPrompt: + if (!isPtr->gotPartial) { + chan = Tcl_GetStdChannel(TCL_STDOUT); + if (chan != NULL) { + Tcl_WriteChars(chan, DEFAULT_PRIMARY_PROMPT, + strlen(DEFAULT_PRIMARY_PROMPT)); + } } } else { - code = Tcl_EvalObjEx(interp, promptCmd, TCL_EVAL_GLOBAL); + code = Tcl_EvalObjEx(interp, promptCmdPtr, TCL_EVAL_GLOBAL); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (script that generates prompt)"); - /* - * We must check that errChannel is a real channel - it - * is possible that someone has transferred stderr out of - * this interpreter with "interp transfer". - */ - - errChannel = Tcl_GetChannel(interp, "stderr", NULL); - if (errChannel != (Tcl_Channel) NULL) { - Tcl_WriteObj(errChannel, Tcl_GetObjResult(interp)); - Tcl_WriteChars(errChannel, "\n", 1); - } + if (Tcl_GetStringResult(interp)[0] != '\0') { + chan = Tcl_GetStdChannel(TCL_STDERR); + if (chan != NULL) { + Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); + Tcl_WriteChars(chan, "\n", 1); + } + } goto defaultPrompt; } } - outChannel = Tcl_GetChannel(interp, "stdout", NULL); - if (outChannel != (Tcl_Channel) NULL) { - Tcl_Flush(outChannel); + + chan = Tcl_GetStdChannel(TCL_STDOUT); + if (chan != NULL) { + Tcl_Flush(chan); } } + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * End: + */ |