os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/mac/tclMacBOAMain.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /* 
     2  * tclMacBGMain.c --
     3  *
     4  *	Main program for Macintosh Background Only Application shells.
     5  *
     6  * Copyright (c) 1997 Sun Microsystems, Inc.
     7  *
     8  * See the file "license.terms" for information on usage and redistribution
     9  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    10  *
    11  * RCS: @(#) $Id: tclMacBOAMain.c,v 1.4 2001/12/28 23:36:31 dgp Exp $
    12  */
    13 
    14 #include "tcl.h"
    15 #include "tclInt.h"
    16 #include "tclMacInt.h"
    17 #include <Resources.h>
    18 #include <Notification.h>
    19 #include <Strings.h>
    20 
    21 /*
    22  * This variable is used to get out of the modal loop of the
    23  * notification manager.
    24  */
    25 
    26 int NotificationIsDone = 0;
    27 
    28 /*
    29  * The following code ensures that tclLink.c is linked whenever
    30  * Tcl is linked.  Without this code there's no reference to the
    31  * code in that file from anywhere in Tcl, so it may not be
    32  * linked into the application.
    33  */
    34 
    35 EXTERN int Tcl_LinkVar();
    36 int (*tclDummyLinkVarPtr)() = Tcl_LinkVar;
    37 
    38 /*
    39  * Declarations for various library procedures and variables (don't want
    40  * to include tclPort.h here, because people might copy this file out of
    41  * the Tcl source directory to make their own modified versions).
    42  * Note:  "exit" should really be declared here, but there's no way to
    43  * declare it without causing conflicts with other definitions elsewher
    44  * on some systems, so it's better just to leave it out.
    45  */
    46 
    47 extern int		isatty _ANSI_ARGS_((int fd));
    48 extern char *		strcpy _ANSI_ARGS_((char *dst, CONST char *src));
    49 
    50 static Tcl_Interp *interp;	/* Interpreter for application. */
    51 
    52 /*
    53  * Forward references for procedures defined later in this file:
    54  */
    55 
    56 void TclMacDoNotification(char *mssg);
    57 void TclMacNotificationResponse(NMRecPtr nmRec); 
    58 int Tcl_MacBGNotifyObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const *objv);
    59 
    60 
    61 /*
    62  *----------------------------------------------------------------------
    63  *
    64  * Tcl_Main --
    65  *
    66  *	Main program for tclsh and most other Tcl-based applications.
    67  *
    68  * Results:
    69  *	None. This procedure never returns (it exits the process when
    70  *	it's done.
    71  *
    72  * Side effects:
    73  *	This procedure initializes the Tk world and then starts
    74  *	interpreting commands;  almost anything could happen, depending
    75  *	on the script being interpreted.
    76  *
    77  *----------------------------------------------------------------------
    78  */
    79 
    80 void
    81 Tcl_Main(argc, argv, appInitProc)
    82     int argc;			/* Number of arguments. */
    83     char **argv;		/* Array of argument strings. */
    84     Tcl_AppInitProc *appInitProc;
    85 				/* Application-specific initialization
    86 				 * procedure to call after most
    87 				 * initialization but before starting to
    88 				 * execute commands. */
    89 {
    90     Tcl_Obj *prompt1NamePtr = NULL;
    91     Tcl_Obj *prompt2NamePtr = NULL;
    92     Tcl_Obj *commandPtr = NULL;
    93     char buffer[1000], *args, *fileName;
    94     int code, tty;
    95     int exitCode = 0;
    96 
    97     Tcl_FindExecutable(argv[0]);
    98     interp = Tcl_CreateInterp();
    99     Tcl_InitMemory(interp);
   100 
   101     /*
   102      * Make command-line arguments available in the Tcl variables "argc"
   103      * and "argv".  If the first argument doesn't start with a "-" then
   104      * strip it off and use it as the name of a script file to process.
   105      */
   106 
   107     fileName = NULL;
   108     if ((argc > 1) && (argv[1][0] != '-')) {
   109 	fileName = argv[1];
   110 	argc--;
   111 	argv++;
   112     }
   113     args = Tcl_Merge(argc-1, argv+1);
   114     Tcl_SetVar(interp, "argv", args, TCL_GLOBAL_ONLY);
   115     ckfree(args);
   116     TclFormatInt(buffer, argc-1);
   117     Tcl_SetVar(interp, "argc", buffer, TCL_GLOBAL_ONLY);
   118     Tcl_SetVar(interp, "argv0", (fileName != NULL) ? fileName : argv[0],
   119 	    TCL_GLOBAL_ONLY);
   120 
   121     /*
   122      * Set the "tcl_interactive" variable.
   123      */
   124 
   125     tty = isatty(0);
   126     Tcl_SetVar(interp, "tcl_interactive",
   127 	    ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY);
   128     
   129     /*
   130      * Invoke application-specific initialization.
   131      */
   132 
   133     if ((*appInitProc)(interp) != TCL_OK) {
   134 	Tcl_DString errStr;
   135 
   136 	Tcl_DStringInit(&errStr);
   137 	Tcl_DStringAppend(&errStr,
   138 		"application-specific initialization failed: \n", -1);
   139 	Tcl_DStringAppend(&errStr, Tcl_GetStringResult(interp), -1);
   140 	Tcl_DStringAppend(&errStr, "\n", 1);
   141 	TclMacDoNotification(Tcl_DStringValue(&errStr));
   142 	Tcl_DStringFree(&errStr);
   143 	goto done;
   144     }
   145 
   146     /*
   147      * Install the BGNotify command:
   148      */
   149     
   150     if ( Tcl_CreateObjCommand(interp, "bgnotify", Tcl_MacBGNotifyObjCmd, NULL,
   151              (Tcl_CmdDeleteProc *) NULL) == NULL) {
   152         goto done;
   153     }
   154     
   155     /*
   156      * If a script file was specified then just source that file
   157      * and quit.  In this Mac BG Application version, we will try the
   158      * resource fork first, then the file system second...
   159      */
   160 
   161     if (fileName != NULL) {
   162         Str255 resName;
   163         Handle resource;
   164         
   165         strcpy((char *) resName + 1, fileName);
   166         resName[0] = strlen(fileName);
   167         resource = GetNamedResource('TEXT',resName);
   168         if (resource != NULL) {
   169             code = Tcl_MacEvalResource(interp, fileName, -1, NULL);
   170         } else {
   171             code = Tcl_EvalFile(interp, fileName);
   172         }
   173         
   174 	if (code != TCL_OK) {
   175             Tcl_DString errStr;
   176             
   177             Tcl_DStringInit(&errStr);
   178             Tcl_DStringAppend(&errStr, " Error sourcing resource or file: ", -1);
   179             Tcl_DStringAppend(&errStr, fileName, -1);
   180             Tcl_DStringAppend(&errStr, "\n\nError was: ", -1);
   181             Tcl_DStringAppend(&errStr, Tcl_GetStringResult(interp), -1);
   182             TclMacDoNotification(Tcl_DStringValue(&errStr));
   183 	    Tcl_DStringFree(&errStr);
   184         }
   185 	goto done;
   186     }
   187 
   188 
   189     /*
   190      * Rather than calling exit, invoke the "exit" command so that
   191      * users can replace "exit" with some other command to do additional
   192      * cleanup on exit.  The Tcl_Eval call should never return.
   193      */
   194 
   195     done:
   196     if (commandPtr != NULL) {
   197 	Tcl_DecrRefCount(commandPtr);
   198     }
   199     if (prompt1NamePtr != NULL) {
   200 	Tcl_DecrRefCount(prompt1NamePtr);
   201     }
   202     if (prompt2NamePtr != NULL) {
   203 	Tcl_DecrRefCount(prompt2NamePtr);
   204     }
   205     sprintf(buffer, "exit %d", exitCode);
   206     Tcl_Eval(interp, buffer);
   207 }
   208 
   209 /*----------------------------------------------------------------------
   210  *
   211  * TclMacDoNotification --
   212  *
   213  *	This posts an error message using the Notification manager.
   214  *
   215  * Results:
   216  *	Post a Notification Manager dialog.
   217  *
   218  * Side effects:
   219  *	None.
   220  *
   221  *----------------------------------------------------------------------
   222  */
   223 void 
   224 TclMacDoNotification(mssg)
   225     char *mssg;
   226 {
   227     NMRec errorNot;
   228     EventRecord *theEvent = NULL;
   229     OSErr err;
   230     char *ptr;
   231     
   232     errorNot.qType = nmType;
   233     errorNot.nmMark = 0;
   234     errorNot.nmIcon = 0;
   235     errorNot.nmSound = (Handle) -1;
   236 
   237     for ( ptr = mssg; *ptr != '\0'; ptr++) {
   238         if (*ptr == '\n') {
   239             *ptr = '\r';
   240         }
   241     }
   242         
   243     c2pstr(mssg);
   244     errorNot.nmStr = (StringPtr) mssg;
   245 
   246     errorNot.nmResp = NewNMProc(TclMacNotificationResponse);
   247     errorNot.nmRefCon = SetCurrentA5();
   248     
   249     NotificationIsDone = 0;
   250     
   251     /*
   252      * Cycle while waiting for the user to click on the
   253      * notification box.  Don't take any events off the event queue,
   254      * since we want Tcl to do this but we want to block till the notification
   255      * has been handled...
   256      */
   257     
   258     err = NMInstall(&errorNot);
   259     if (err == noErr) { 
   260         while (!NotificationIsDone) {
   261             WaitNextEvent(0, theEvent, 20, NULL);
   262         }
   263         NMRemove(&errorNot);
   264     }
   265     	
   266     p2cstr((unsigned char *) mssg);
   267 }
   268 
   269 void 
   270 TclMacNotificationResponse(nmRec) 
   271     NMRecPtr nmRec;
   272 {
   273     int curA5;
   274     
   275     curA5 = SetCurrentA5();
   276     SetA5(nmRec->nmRefCon);
   277     
   278     NotificationIsDone = 1;
   279     
   280     SetA5(curA5);
   281     
   282 }
   283 
   284 int 
   285 Tcl_MacBGNotifyObjCmd(clientData, interp, objc, objv)
   286     ClientData clientData;
   287     Tcl_Interp *interp;
   288     int objc;
   289     Tcl_Obj **objv;	
   290 {
   291     Tcl_Obj *resultPtr;
   292     
   293     resultPtr = Tcl_GetObjResult(interp);
   294     
   295     if ( objc != 2 ) {
   296         Tcl_WrongNumArgs(interp, 1, objv, "message");
   297         return TCL_ERROR;
   298     }
   299     
   300     TclMacDoNotification(Tcl_GetString(objv[1]));
   301     return TCL_OK;
   302            
   303 }
   304