tclMacBOAMain.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:8k
源码类别:

通讯编程

开发平台:

Visual C++

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