winMain.cpp

Go to the documentation of this file.
00001 /* 
00002  * winMain.c --
00003  *
00004  *      Main entry point for wish and other Tk-based applications.
00005  *
00006  * Copyright (c) 1995-1997 Sun Microsystems, Inc.
00007  * Copyright (c) 1998-1999 by Scriptics Corporation.
00008  *
00009  * See the file "license.terms" for information on usage and redistribution
00010  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
00011  *
00012  * RCS: @(#) $Id: winMain.cpp,v 1.3 2004/07/21 00:01:23 fmk Exp $
00013  */
00014 
00015 /*                       MODIFIED   FOR                              */
00016 
00017 /* ****************************************************************** **
00018 **    OpenSees - Open System for Earthquake Engineering Simulation    **
00019 **          Pacific Earthquake Engineering Research Center            **
00020 ** ****************************************************************** */
00021 
00022 extern "C" {
00023 #include <tk.h>
00024 #define WIN32_LEAN_AND_MEAN
00025 #include <windows.h>
00026 #undef WIN32_LEAN_AND_MEAN
00027 #include <malloc.h>
00028 #include <locale.h>
00029 }
00030 
00031 #include <tk.h>
00032 #include <commands.h>
00033 
00034 
00035 void Tk_MainOpenSees(int argc, char **argv,Tcl_AppInitProc *appInitProc, 
00036                                          Tcl_Interp *interp);
00037 
00038 /*
00039  * The following declarations refer to internal Tk routines.  These
00040  * interfaces are available for use, but are not supported.
00041  */
00042 
00043 
00044 
00045 /*
00046  * Forward declarations for procedures defined later in this file:
00047  */
00048 static void             setargv _ANSI_ARGS_((int *argcPtr, char ***argvPtr));
00049 #ifdef _TCL84
00050 static Tcl_PanicProc WishPanic;
00051 #else
00052 static void             WishPanic _ANSI_ARGS_(TCL_VARARGS(char *,format));
00053 #endif
00054 
00055 #ifdef TK_TEST
00056 extern int              Tktest_Init(Tcl_Interp *interp);
00057 #endif /* TK_TEST */
00058 
00059 #ifdef TCL_TEST
00060 extern int              TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp));
00061 extern int              Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp));
00062 #endif /* TCL_TEST */
00063 
00064 static BOOL consoleRequired = TRUE;
00065 
00066 /*
00067  * The following #if block allows you to change the AppInit
00068  * function by using a #define of TCL_LOCAL_APPINIT instead
00069  * of rewriting this entire file.  The #if checks for that
00070  * #define and uses Tcl_AppInit if it doesn't exist.
00071  */
00072     
00073 #ifndef TK_LOCAL_APPINIT
00074 #define TK_LOCAL_APPINIT Tcl_AppInit    
00075 #endif
00076 extern int TK_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp));
00077     
00078 /*
00079  * The following #if block allows you to change how Tcl finds the startup
00080  * script, prime the library or encoding paths, fiddle with the argv,
00081  * etc., without needing to rewrite Tk_Main()
00082  */
00083 
00084 #ifdef TK_LOCAL_MAIN_HOOK
00085 extern int TK_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv));
00086 #endif
00087 
00088 
00089 /*
00090  *----------------------------------------------------------------------
00091  *
00092  * WinMain --
00093  *
00094  *      Main entry point from Windows.
00095  *
00096  * Results:
00097  *      Returns false if initialization fails, otherwise it never
00098  *      returns. 
00099  *
00100  * Side effects:
00101  *      Just about anything, since from here we call arbitrary Tcl code.
00102  *
00103  *----------------------------------------------------------------------
00104  */
00105 
00106 int APIENTRY
00107 WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow)
00108 {
00109     char **argv;
00110     int argc;
00111     char buffer[MAX_PATH+1];
00112     char *p;
00113 
00114     Tcl_SetPanicProc(WishPanic);
00115 
00116     /*
00117      * Increase the application queue size from default value of 8.
00118      * At the default value, cross application SendMessage of WM_KILLFOCUS
00119      * will fail because the handler will not be able to do a PostMessage!
00120      * This is only needed for Windows 3.x, since NT dynamically expands
00121      * the queue.
00122      */
00123 
00124     SetMessageQueue(64);
00125 
00126     /*
00127      * Create the console channels and install them as the standard
00128      * channels.  All I/O will be discarded until Tk_CreateConsoleWindow is
00129      * called to attach the console to a text widget.
00130      */
00131 
00132     consoleRequired = TRUE;
00133 
00134     /*
00135      * Set up the default locale to be standard "C" locale so parsing
00136      * is performed correctly.
00137      */
00138 
00139     setlocale(LC_ALL, "C");
00140     setargv(&argc, &argv);
00141 
00142     /*
00143      * Replace argv[0] with full pathname of executable, and forward
00144      * slashes substituted for backslashes.
00145      */
00146 
00147     GetModuleFileName(NULL, buffer, sizeof(buffer));
00148     argv[0] = buffer;
00149     for (p = buffer; *p != '\0'; p++) {
00150         if (*p == '\\') {
00151             *p = '/';
00152         }
00153     }
00154 
00155 #ifdef TK_LOCAL_MAIN_HOOK
00156     TK_LOCAL_MAIN_HOOK(&argc, &argv);
00157 #endif
00158 
00159     Tk_MainOpenSees(argc, argv, TK_LOCAL_APPINIT, Tcl_CreateInterp());
00160     return 1;
00161 }
00162 
00163 
00164 /*
00165  *----------------------------------------------------------------------
00166  *
00167  * Tcl_AppInit --
00168  *
00169  *      This procedure performs application-specific initialization.
00170  *      Most applications, especially those that incorporate additional
00171  *      packages, will have their own version of this procedure.
00172  *
00173  * Results:
00174  *      Returns a standard Tcl completion code, and leaves an error
00175  *      message in the interp's result if an error occurs.
00176  *
00177  * Side effects:
00178  *      Depends on the startup script.
00179  *
00180  *----------------------------------------------------------------------
00181  */
00182 
00183 int
00184 Tcl_AppInit(Tcl_Interp *interp)
00185 {
00186     if (Tcl_Init(interp) == TCL_ERROR) {
00187         goto error;
00188     }
00189     if (Tk_Init(interp) == TCL_ERROR) {
00190         goto error;
00191     }
00192     Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit);
00193 
00194     /*
00195      * Initialize the console only if we are running as an interactive
00196      * application.
00197      */
00198 
00199     if (consoleRequired) {
00200         if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) {
00201             goto error;
00202         }
00203     }
00204 
00205 #ifdef TCL_TEST
00206     if (Tcltest_Init(interp) == TCL_ERROR) {
00207         return TCL_ERROR;
00208     }
00209     Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init,
00210             (Tcl_PackageInitProc *) NULL);
00211     if (TclObjTest_Init(interp) == TCL_ERROR) {
00212         return TCL_ERROR;
00213     }
00214 #endif /* TCL_TEST */
00215 
00216 #ifdef TK_TEST
00217     if (Tktest_Init(interp) == TCL_ERROR) {
00218         goto error;
00219     }
00220     Tcl_StaticPackage(interp, "Tktest", Tktest_Init,
00221             (Tcl_PackageInitProc *) NULL);
00222 #endif /* TK_TEST */
00223 
00224 
00225     if (g3AppInit(interp) < 0)
00226                 return TCL_ERROR;
00227 
00228 
00229     Tcl_SetVar(interp, "tcl_rcFileName", "~/wishrc.tcl", TCL_GLOBAL_ONLY);
00230     return TCL_OK;
00231 
00232 error:
00233     MessageBeep(MB_ICONEXCLAMATION);
00234     MessageBox(NULL, Tcl_GetStringResult(interp), "Error in Wish",
00235             MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
00236     ExitProcess(1);
00237     /* we won't reach this, but we need the return */
00238     return TCL_ERROR;
00239 }
00240 
00241 /*
00242  *----------------------------------------------------------------------
00243  *
00244  * WishPanic --
00245  *
00246  *      Display a message and exit.
00247  *
00248  * Results:
00249  *      None.
00250  *
00251  * Side effects:
00252  *      Exits the program.
00253  *
00254  *----------------------------------------------------------------------
00255  */
00256 
00257 #ifdef _TCL84
00258 void
00259 WishPanic TCL_VARARGS_DEF(CONST char *,arg1)
00260 {
00261     va_list argList;
00262     char buf[1024];
00263     CONST char *format;
00264     
00265     format = TCL_VARARGS_START(CONST char *,arg1,argList);
00266     vsprintf(buf, format, argList);
00267 
00268     MessageBeep(MB_ICONEXCLAMATION);
00269     MessageBox(NULL, buf, "Fatal Error in Wish",
00270             MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
00271 #ifdef _MSC_VER
00272     DebugBreak();
00273 #endif
00274     ExitProcess(1);
00275 }
00276 #else
00277 void
00278 WishPanic TCL_VARARGS_DEF(char *,arg1)
00279 {
00280     va_list argList;
00281     char buf[1024];
00282     char *format;
00283     
00284     format = TCL_VARARGS_START(char *,arg1,argList);
00285     vsprintf(buf, format, argList);
00286 
00287     MessageBeep(MB_ICONEXCLAMATION);
00288     MessageBox(NULL, buf, "Fatal Error in Wish",
00289             MB_ICONSTOP | MB_OK | MB_TASKMODAL | MB_SETFOREGROUND);
00290 #ifdef _MSC_VER
00291     DebugBreak();
00292 #endif
00293     ExitProcess(1);
00294 }
00295 #endif
00296 /*
00297  *-------------------------------------------------------------------------
00298  *
00299  * setargv --
00300  *
00301  *      Parse the Windows command line string into argc/argv.  Done here
00302  *      because we don't trust the builtin argument parser in crt0.  
00303  *      Windows applications are responsible for breaking their command
00304  *      line into arguments.
00305  *
00306  *      2N backslashes + quote -> N backslashes + begin quoted string
00307  *      2N + 1 backslashes + quote -> literal
00308  *      N backslashes + non-quote -> literal
00309  *      quote + quote in a quoted string -> single quote
00310  *      quote + quote not in quoted string -> empty string
00311  *      quote -> begin quoted string
00312  *
00313  * Results:
00314  *      Fills argcPtr with the number of arguments and argvPtr with the
00315  *      array of arguments.
00316  *
00317  * Side effects:
00318  *      Memory allocated.
00319  *
00320  *--------------------------------------------------------------------------
00321  */
00322 
00323 static void
00324 setargv(int *argcPtr, char ***argvPtr)
00325 {
00326     char *cmdLine, *p, *arg, *argSpace;
00327     char **argv;
00328     int argc, size, inquote, copy, slashes;
00329     
00330     cmdLine = GetCommandLine(); /* INTL: BUG */
00331 
00332     /*
00333      * Precompute an overly pessimistic guess at the number of arguments
00334      * in the command line by counting non-space spans.
00335      */
00336 
00337     size = 2;
00338     for (p = cmdLine; *p != '\0'; p++) {
00339         if ((*p == ' ') || (*p == '\t')) {      /* INTL: ISO space. */
00340             size++;
00341             while ((*p == ' ') || (*p == '\t')) { /* INTL: ISO space. */
00342                 p++;
00343             }
00344             if (*p == '\0') {
00345                 break;
00346             }
00347         }
00348     }
00349     argSpace = (char *) Tcl_Alloc(
00350             (unsigned) (size * sizeof(char *) + strlen(cmdLine) + 1));
00351     argv = (char **) argSpace;
00352     argSpace += size * sizeof(char *);
00353     size--;
00354 
00355     p = cmdLine;
00356     for (argc = 0; argc < size; argc++) {
00357         argv[argc] = arg = argSpace;
00358         while ((*p == ' ') || (*p == '\t')) {   /* INTL: ISO space. */
00359             p++;
00360         }
00361         if (*p == '\0') {
00362             break;
00363         }
00364 
00365         inquote = 0;
00366         slashes = 0;
00367         while (1) {
00368             copy = 1;
00369             while (*p == '\\') {
00370                 slashes++;
00371                 p++;
00372             }
00373             if (*p == '"') {
00374                 if ((slashes & 1) == 0) {
00375                     copy = 0;
00376                     if ((inquote) && (p[1] == '"')) {
00377                         p++;
00378                         copy = 1;
00379                     } else {
00380                         inquote = !inquote;
00381                     }
00382                 }
00383                 slashes >>= 1;
00384             }
00385 
00386             while (slashes) {
00387                 *arg = '\\';
00388                 arg++;
00389                 slashes--;
00390             }
00391 
00392             if ((*p == '\0')
00393                     || (!inquote && ((*p == ' ') || (*p == '\t')))) { /* INTL: ISO space. */
00394                 break;
00395             }
00396             if (copy != 0) {
00397                 *arg = *p;
00398                 arg++;
00399             }
00400             p++;
00401         }
00402         *arg = '\0';
00403         argSpace = arg + 1;
00404     }
00405     argv[argc] = NULL;
00406 
00407     *argcPtr = argc;
00408     *argvPtr = argv;
00409 }
00410 
00411 
00412 /*
00413  *----------------------------------------------------------------------
00414  *
00415  * main --
00416  *
00417  *      Main entry point from the console.
00418  *
00419  * Results:
00420  *      None: Tk_Main never returns here, so this procedure never
00421  *      returns either.
00422  *
00423  * Side effects:
00424  *      Whatever the applications does.
00425  *
00426  *----------------------------------------------------------------------
00427  */
00428 
00429 int main(int argc, char **argv)
00430 {
00431     Tcl_SetPanicProc(WishPanic);
00432 
00433     /*
00434      * Set up the default locale to be standard "C" locale so parsing
00435      * is performed correctly.
00436      */
00437 
00438     setlocale(LC_ALL, "C");
00439     /*
00440      * Increase the application queue size from default value of 8.
00441      * At the default value, cross application SendMessage of WM_KILLFOCUS
00442      * will fail because the handler will not be able to do a PostMessage!
00443      * This is only needed for Windows 3.x, since NT dynamically expands
00444      * the queue.
00445      */
00446 
00447     SetMessageQueue(64);
00448 
00449     /*
00450      * Create the console channels and install them as the standard
00451      * channels.  All I/O will be discarded until Tk_CreateConsoleWindow is
00452      * called to attach the console to a text widget.
00453      */
00454 
00455     consoleRequired = FALSE;
00456 
00457     Tk_MainOpenSees(argc, argv, Tcl_AppInit, Tcl_CreateInterp());
00458     return 0;
00459 }
00460 

Generated on Mon Oct 23 15:05:31 2006 for OpenSees by doxygen 1.5.0