home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / Level 1 Extensions 29Sep94 / Alert.c next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  14.8 KB  |  516 lines  |  [TEXT/KAHL]

  1. /* Alert.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    System Dependency Library for Building Portable Software               */
  5. /*    Macintosh Version                                                      */
  6. /*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
  7. /*                                                                           */
  8. /*    This file is Public Domain; it may be used for any purpose whatsoever  */
  9. /*    without restriction.                                                   */
  10. /*                                                                           */
  11. /*    This package is distributed in the hope that it will be useful,        */
  12. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  13. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
  14. /*                                                                           */
  15. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  16. /*                                                                           */
  17. /*****************************************************************************/
  18.  
  19. #include "MiscInfo.h"
  20. #include "Debug.h"
  21. #include "Audit.h"
  22. #include "Definitions.h"
  23.  
  24. #include "Alert.h"
  25. #include "Screen.h"
  26. #include "DataMunging.h"
  27. #include "Memory.h"
  28. #include "EventLoop.h"
  29. #include "SimpleButton.h"
  30. #include "WrapTextBox.h"
  31. #include "Menus.h"
  32.  
  33.  
  34. #define ALERTEMERGENCY (20480)
  35.  
  36. #define ALERTWIDTH (400)
  37. #define ALERTHEIGHT (160)
  38.  
  39. #define DLOGWIDTH (400)
  40. #define DLOGHEIGHT (180)
  41.  
  42. #define BUTTONWIDTH (93)
  43.  
  44. static unsigned char                RawStopIcon[] =
  45.     {
  46.         0x00,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0x80,0x03,0x80,0x01,0xC0,0x07,0x7F,0xFE,0xE0,
  47.         0x0E,0xFF,0xFF,0x70,0x1D,0xFF,0xFF,0xB8,0x3B,0xFF,0xFF,0xDC,0x77,0xFF,0xFF,0xEE,
  48.         0xEF,0xFF,0xFF,0xF7,0xDF,0xFD,0x3F,0xFB,0xDF,0xF9,0x2F,0xFB,0xDF,0xE9,0x27,0xFB,
  49.         0xDF,0xC9,0x27,0xFB,0xDF,0xC9,0x27,0xFB,0xDF,0xC8,0x24,0xFB,0xDF,0xC0,0x04,0xFB,
  50.         0xDF,0xC0,0x00,0xFB,0xDF,0xC0,0x01,0xFB,0xDF,0xC0,0x01,0xFB,0xDF,0xC0,0x01,0xFB,
  51.         0xDF,0xE0,0x03,0xFB,0xDF,0xE0,0x03,0xFB,0xDF,0xF0,0x07,0xFB,0xDF,0xF8,0x0F,0xFB,
  52.         0xEF,0xFF,0xFF,0xF7,0x77,0xFF,0xFF,0xEE,0x3B,0xFF,0xFF,0xDC,0x1D,0xFF,0xFF,0xB8,
  53.         0x0E,0xFF,0xFF,0x70,0x07,0x00,0x00,0xE0,0x03,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0x80
  54.     };
  55.  
  56. static unsigned char                RawExclamationIcon[] =
  57.     {
  58.         0x00,0x01,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x02,0x80,0x00,0x00,0x06,0xC0,0x00,
  59.         0x00,0x04,0x40,0x00,0x00,0x0C,0x60,0x00,0x00,0x08,0x20,0x00,0x00,0x1B,0xB0,0x00,
  60.         0x00,0x13,0x90,0x00,0x00,0x37,0xD8,0x00,0x00,0x27,0xC8,0x00,0x00,0x67,0xCC,0x00,
  61.         0x00,0x47,0xC4,0x00,0x00,0xC7,0xC6,0x00,0x00,0x87,0xC2,0x00,0x01,0x83,0x83,0x00,
  62.         0x01,0x03,0x81,0x00,0x03,0x03,0x81,0x80,0x02,0x03,0x80,0x80,0x06,0x03,0x80,0xC0,
  63.         0x04,0x01,0x00,0x40,0x0C,0x01,0x00,0x60,0x08,0x01,0x00,0x20,0x18,0x01,0x00,0x30,
  64.         0x10,0x00,0x00,0x10,0x30,0x01,0x80,0x18,0x20,0x03,0xC0,0x08,0x60,0x03,0xC0,0x0C,
  65.         0x40,0x01,0x80,0x04,0xC0,0x00,0x00,0x06,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFC
  66.     };
  67.  
  68. static unsigned char                RawSpeechIcon[] =
  69.     {
  70.         0x00,0x00,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x08,0x00,0x06,0x00,0x08,0x00,0x05,0x00,
  71.         0x08,0x00,0x04,0x80,0x08,0x00,0x04,0x40,0x08,0x00,0x04,0x20,0x08,0x00,0x07,0xF0,
  72.         0x0B,0xE0,0x00,0x10,0x08,0x84,0xF2,0x58,0x08,0x80,0x00,0x18,0x08,0x80,0x00,0x18,
  73.         0x08,0x86,0x79,0x98,0x08,0x80,0x00,0x18,0x0B,0xE0,0x00,0x18,0x08,0x07,0x79,0x98,
  74.         0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,0x0A,0xF2,0xE3,0x98,0x08,0x00,0x00,0x18,
  75.         0x08,0x00,0x00,0x18,0x0B,0xBB,0xB2,0x58,0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,
  76.         0x0A,0xFD,0x79,0x98,0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,0x0B,0x5B,0x90,0x18,
  77.         0x08,0x00,0x00,0x18,0x08,0x00,0x00,0x18,0x0F,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xF8
  78.     };
  79.  
  80.  
  81. static Bitmap*                SpeechIcon;
  82. static Bitmap*                ExclamationIcon;
  83. static Bitmap*                StopIcon;
  84.  
  85. EXECUTE(static MyBoolean Initialized = False;)
  86.  
  87. static char*                    EmergencyMemory;
  88.  
  89.  
  90. /* initialize the alert system, allocate the bitmaps and temporary memory stash */
  91. MyBoolean                    InitializeAlertSubsystem(void)
  92.     {
  93.         ERROR(Initialized,PRERR(ForceAbort,
  94.             "InitializeAlertSubsystem called more than once"));
  95.         EXECUTE(Initialized = True);
  96.         SpeechIcon = MakeBitmap(RawSpeechIcon,32,32,4);
  97.         if (SpeechIcon == NIL)
  98.             {
  99.              FailurePoint1:
  100.                 return False;
  101.             }
  102.         ExclamationIcon = MakeBitmap(RawExclamationIcon,32,32,4);
  103.         if (ExclamationIcon == NIL)
  104.             {
  105.              FailurePoint2:
  106.                 DisposeBitmap(SpeechIcon);
  107.                 goto FailurePoint1;
  108.             }
  109.         StopIcon = MakeBitmap(RawStopIcon,32,32,4);
  110.         if (StopIcon == NIL)
  111.             {
  112.              FailurePoint3:
  113.                 DisposeBitmap(ExclamationIcon);
  114.                 goto FailurePoint2;
  115.             }
  116.         EmergencyMemory = AllocPtrCanFail(ALERTEMERGENCY,"AlertEmergencyPtr");
  117.         if (EmergencyMemory == NIL)
  118.             {
  119.              FailurePoint4:
  120.                 DisposeBitmap(StopIcon);
  121.                 goto FailurePoint3;
  122.             }
  123.         return True;
  124.     }
  125.  
  126.  
  127. /* clean up internal data structures */
  128. void                            ShutdownAlertSubsystem(void)
  129.     {
  130.         ERROR(!Initialized,PRERR(ForceAbort,"Alert subsystem not initialized"));
  131.         DisposeBitmap(SpeechIcon);
  132.         DisposeBitmap(ExclamationIcon);
  133.         DisposeBitmap(StopIcon);
  134.         if (EmergencyMemory != NIL)
  135.             {
  136.                 ReleasePtr(EmergencyMemory);
  137.             }
  138.     }
  139.  
  140.  
  141. typedef struct
  142.     {
  143.         WinType*                        ScreenID;
  144.         char*                                TotalMessage;
  145.         SimpleButtonRec*        OKButton;
  146.         Bitmap*                            IconThing;
  147.     } AlertRec;
  148.  
  149.  
  150. static void                AlertUpdater(AlertRec* Window)
  151.     {
  152.         /* DON'T call CheckPtrExistence since Window is allocated on the stack */
  153.         SetClipRect(Window->ScreenID,0,0,ALERTWIDTH,ALERTHEIGHT);
  154.         DrawBitmap(Window->ScreenID,23,13,Window->IconThing);
  155.         DrawWrappedTextBox(Window->ScreenID,Window->TotalMessage,GetUglyFont(),12,
  156.             23 + 32 + 23,13,ALERTWIDTH - (23 + 32 + 23 + 13) - 10,
  157.             ALERTHEIGHT - (13 + 13 + 21 + 6));
  158.         RedrawSimpleButton(Window->OKButton);
  159.     }
  160.  
  161.  
  162. static void                LocalAlert(Bitmap* TheIcon, char* Message, char* ExtraInfo)
  163.     {
  164.         AlertRec                Window;
  165.         EXECUTE(static MyBoolean    Alerting = False;)
  166.  
  167.         APRINT(("+LocalAlert: '%t' '%t'",Message,ExtraInfo));
  168.         ERROR(!Initialized,PRERR(ForceAbort,"Alert subsystem not initialized"));
  169.         ERROR(Message == NIL,PRERR(ForceAbort,"LocalAlert:  Message is NIL"));
  170.         ERROR(Alerting,PRERR(ForceAbort,"LocalAlert called recursively"));
  171.         EXECUTE(Alerting = True;)
  172.         if (EmergencyMemory != NIL)
  173.             {
  174.                 ReleasePtr(EmergencyMemory);
  175.                 EmergencyMemory = NIL;
  176.             }
  177.         ErrorBeep();
  178.         SetArrowCursor();
  179.         if (ExtraInfo != NIL)
  180.             {
  181.                 char*                    Key;
  182.                 char*                    Replacement;
  183.                 char*                    Original;
  184.                 char*                    Temp;
  185.  
  186.                 Key = BlockFromRaw("_",1);
  187.                 Replacement = BlockFromRaw(ExtraInfo,StrLen(ExtraInfo));
  188.                 Original = BlockFromRaw(Message,StrLen(Message));
  189.                 if ((Key == NIL) || (Replacement == NIL) || (Original == NIL))
  190.                     {
  191.                         /* we don't care about releasing the memory since this is a fatal */
  192.                         /* error anyway. */
  193.                      Fault:
  194.                         PRERR(ForceAbort,"Out of memory in alert handler -- can't continue");
  195.                     }
  196.                 Temp = ReplaceBlockCopy(Original,Key,Replacement);
  197.                 if (Temp == NIL)
  198.                     {
  199.                         goto Fault;
  200.                     }
  201.                 ReleasePtr(Key);
  202.                 ReleasePtr(Replacement);
  203.                 ReleasePtr(Original);
  204.                 Window.TotalMessage = BlockToStringCopy(Temp);
  205.                 ReleasePtr(Temp);
  206.                 if (Window.TotalMessage == NIL)
  207.                     {
  208.                         goto Fault;
  209.                     }
  210.             }
  211.          else
  212.             {
  213.                 Window.TotalMessage = StringFromRaw(Message);
  214.             }
  215.         Window.IconThing = TheIcon;
  216.         Window.ScreenID = MakeNewWindow(eModelessDialogWindow,eWindowNotClosable,
  217.             eWindowNotZoomable,eWindowNotResizable,AlertLeftEdge(ALERTWIDTH),
  218.             AlertTopEdge(ALERTHEIGHT),ALERTWIDTH,ALERTHEIGHT,
  219.             (void (*)(void*))&AlertUpdater,&Window);
  220.         if (Window.ScreenID == NIL)
  221.             {
  222.                 goto Fault;
  223.             }
  224.         Window.OKButton = NewSimpleButton(Window.ScreenID,"OK",ALERTWIDTH
  225.             - (13 + BUTTONWIDTH),ALERTHEIGHT - (13 + 21 + 3),BUTTONWIDTH,21);
  226.         if (Window.OKButton == NIL)
  227.             {
  228.                 goto Fault;
  229.             }
  230.         SetDefaultButtonState(Window.OKButton,True);
  231.         while (True)
  232.             {
  233.                 OrdType                            X,Y;
  234.                 ModifierFlags                Modifiers;
  235.                 WinType*                        TheWindow;
  236.                 MenuItemType*                MenuItem;
  237.                 char                                KeyPressed;
  238.  
  239.                 switch (GetAnEvent(&X,&Y,&Modifiers,&TheWindow,&MenuItem,&KeyPressed))
  240.                     {
  241.                         default:
  242.                             break;
  243.                         case eCheckCursor:
  244.                             SetArrowCursor();
  245.                             break;
  246.                         case eNoEvent:
  247.                             break;
  248.                         case eMouseDown:
  249.                             if (SimpleButtonHitTest(Window.OKButton,X,Y))
  250.                                 {
  251.                                     if (SimpleButtonMouseDown(Window.OKButton,X,Y,NIL,NIL))
  252.                                         {
  253.                                          ExitPoint:
  254.                                             DisposeSimpleButton(Window.OKButton);
  255.                                             ReleasePtr(Window.TotalMessage);
  256.                                             KillWindow(Window.ScreenID);
  257.                                             EXECUTE(Alerting = False;)
  258.                                             EmergencyMemory = AllocPtrCanFail(ALERTEMERGENCY,
  259.                                                 "AlertEmergencyPtr");
  260.                                             APRINT(("-LocalAlert"));
  261.                                             return;
  262.                                         }
  263.                                 }
  264.                             break;
  265.                         case eKeyPressed:
  266.                             if (KeyPressed == 13)
  267.                                 {
  268.                                     FlashButton(Window.OKButton);
  269.                                     goto ExitPoint;
  270.                                 }
  271.                             break;
  272.                     }
  273.             }
  274.         APRINT(("-LocalAlert"));
  275.     }
  276.  
  277.  
  278. /* display a halt (Stopsign) alert.  ExtraInfo is inserted into Message where */
  279. /* the _ character is */
  280. void                            AlertHalt(char* Message, char* ExtraInfo)
  281.     {
  282.         LocalAlert(StopIcon,Message,ExtraInfo);
  283.     }
  284.  
  285.  
  286. /* display a warning (!) alert. ExtraInfo is inserted into Message where */
  287. /* the _ character is */
  288. void                            AlertWarning(char* Message, char* ExtraInfo)
  289.     {
  290.         LocalAlert(ExclamationIcon,Message,ExtraInfo);
  291.     }
  292.  
  293.  
  294. /* display an informational (I) alert. ExtraInfo is inserted into Message where */
  295. /* the _ character is */
  296. void                            AlertInfo(char* Message, char* ExtraInfo)
  297.     {
  298.         LocalAlert(SpeechIcon,Message,ExtraInfo);
  299.     }
  300.  
  301.  
  302. typedef struct
  303.     {
  304.         WinType*                        ScreenID;
  305.         char*                                TotalMessage;
  306.         SimpleButtonRec*        YesButton;
  307.         SimpleButtonRec*        NoButton;
  308.         SimpleButtonRec*        CancelButton;
  309.     } YesNoCancelRec;
  310.  
  311.  
  312. static void                YesNoCancelUpdater(YesNoCancelRec* Window)
  313.     {
  314.         /* do NOT call CheckPtrExistence since Window is allocated on the stack */
  315.         DrawBitmap(Window->ScreenID,23,13,ExclamationIcon);
  316.         DrawWrappedTextBox(Window->ScreenID,Window->TotalMessage,GetUglyFont(),12,
  317.             23 + 32 + 23,13,DLOGWIDTH - (23 + 32 + 23 + 13) - 16,
  318.             DLOGHEIGHT - (13 + 13 + 21 + 6));
  319.         RedrawSimpleButton(Window->YesButton);
  320.         RedrawSimpleButton(Window->NoButton);
  321.         if (Window->CancelButton != NIL)
  322.             {
  323.                 RedrawSimpleButton(Window->CancelButton);
  324.             }
  325.     }
  326.  
  327.  
  328. /* present a dialog with 3 buttons (yes, no, and cancel).  if Cancel is NIL, */
  329. /* then there will only be 2 buttons.  ExtraInfo is inserted into Message where */
  330. /* the _ character is */
  331. YesNoCancelType        AskYesNoCancel(char* Message, char* ExtraInfo,
  332.                                         char* Yes, char* No, char* Cancel)
  333.     {
  334.         YesNoCancelRec            Window;
  335.         YesNoCancelType            ReturnValue;
  336.  
  337.         ERROR(!Initialized,PRERR(ForceAbort,"Alert subsystem not initialized"));
  338.         if (ExtraInfo != NIL)
  339.             {
  340.                 MyBoolean            Error;
  341.                 char*                    Key;
  342.                 char*                    Replacement;
  343.                 char*                    Original;
  344.                 char*                    Temp;
  345.  
  346.                 Error = False;
  347.                 Key = BlockFromRaw("_",1);
  348.                 if (Key != NIL)
  349.                     {
  350.                         Replacement = BlockFromRaw(ExtraInfo,StrLen(ExtraInfo));
  351.                         if (Replacement != NIL)
  352.                             {
  353.                                 Original = BlockFromRaw(Message,StrLen(Message));
  354.                                 if (Original != NIL)
  355.                                     {
  356.                                         Temp = ReplaceBlockCopy(Original,Key,Replacement);
  357.                                         if (Temp != NIL)
  358.                                             {
  359.                                                 Window.TotalMessage = BlockToStringCopy(Temp);
  360.                                                 ReleasePtr(Temp);
  361.                                                 if (Window.TotalMessage == NIL)
  362.                                                     {
  363.                                                         Error = True;
  364.                                                     }
  365.                                             }
  366.                                          else
  367.                                             {
  368.                                                 Error = True;
  369.                                             }
  370.                                         ReleasePtr(Original);
  371.                                     }
  372.                                  else
  373.                                     {
  374.                                         Error = True;
  375.                                     }
  376.                                 ReleasePtr(Replacement);
  377.                             }
  378.                          else
  379.                             {
  380.                                 Error = True;
  381.                             }
  382.                         ReleasePtr(Key);
  383.                     }
  384.                  else
  385.                     {
  386.                         Error = True;
  387.                     }
  388.                 if (Error)
  389.                     {
  390.                         return eCancel;
  391.                     }
  392.             }
  393.          else
  394.             {
  395.                 Window.TotalMessage = StringFromRaw(Message);
  396.                 if (Window.TotalMessage == NIL)
  397.                     {
  398.                         return eCancel;
  399.                     }
  400.             }
  401.         SetArrowCursor();
  402.         Window.ScreenID = MakeNewWindow(eModelessDialogWindow,eWindowNotClosable,
  403.             eWindowNotZoomable,eWindowNotResizable,DialogLeftEdge(DLOGWIDTH),
  404.             DialogTopEdge(DLOGHEIGHT),DLOGWIDTH,DLOGHEIGHT,
  405.             (void (*)(void*))&YesNoCancelUpdater,&Window);
  406.         if (Window.ScreenID == 0)
  407.             {
  408.              MemOut1:
  409.                 ReleasePtr(Window.TotalMessage);
  410.                 return eCancel;
  411.             }
  412.         Window.YesButton = NewSimpleButton(Window.ScreenID,Yes,DLOGWIDTH
  413.             - (13 + BUTTONWIDTH),DLOGHEIGHT - (13 + 21 + 3),BUTTONWIDTH,21);
  414.         if (Window.YesButton == NIL)
  415.             {
  416.              MemOut2:
  417.                 KillWindow(Window.ScreenID);
  418.                 goto MemOut1;
  419.             }
  420.         SetDefaultButtonState(Window.YesButton,True);
  421.         Window.NoButton = NewSimpleButton(Window.ScreenID,No,13,
  422.             DLOGHEIGHT - (13 + 21 + 3),BUTTONWIDTH,21);
  423.         if (Window.NoButton == NIL)
  424.             {
  425.              MemOut3:
  426.                 DisposeSimpleButton(Window.YesButton);
  427.                 goto MemOut2;
  428.             }
  429.         if (Cancel != NIL)
  430.             {
  431.                 Window.CancelButton = NewSimpleButton(Window.ScreenID,Cancel,DLOGWIDTH
  432.                     - (13 + BUTTONWIDTH),DLOGHEIGHT - (13 + 21 + 3 + 21 + 10),BUTTONWIDTH,21);
  433.                 if (Window.CancelButton == NIL)
  434.                     {
  435.                      MemOut4:
  436.                         DisposeSimpleButton(Window.NoButton);
  437.                         goto MemOut3;
  438.                     }
  439.             }
  440.          else
  441.             {
  442.                 Window.CancelButton = NIL;
  443.             }
  444.         while (True)
  445.             {
  446.                 OrdType                            X,Y;
  447.                 ModifierFlags                Modifiers;
  448.                 WinType*                        TheWindow;
  449.                 MenuItemType*                MenuItem;
  450.                 char                                Key;
  451.  
  452.                 switch (GetAnEvent(&X,&Y,&Modifiers,&TheWindow,&MenuItem,&Key))
  453.                     {
  454.                         default:
  455.                             break;
  456.                         case eCheckCursor:
  457.                             SetArrowCursor();
  458.                             break;
  459.                         case eNoEvent:
  460.                             break;
  461.                         case eMouseDown:
  462.                             if (SimpleButtonHitTest(Window.YesButton,X,Y))
  463.                                 {
  464.                                     if (SimpleButtonMouseDown(Window.YesButton,X,Y,NIL,NIL))
  465.                                         {
  466.                                             ReturnValue = eYes;
  467.                                             goto ExitPoint;
  468.                                         }
  469.                                 }
  470.                             else if (SimpleButtonHitTest(Window.NoButton,X,Y))
  471.                                 {
  472.                                     if (SimpleButtonMouseDown(Window.NoButton,X,Y,NIL,NIL))
  473.                                         {
  474.                                             ReturnValue = eNo;
  475.                                             goto ExitPoint;
  476.                                         }
  477.                                 }
  478.                             else if ((Window.CancelButton != NIL)
  479.                                 && SimpleButtonHitTest(Window.CancelButton,X,Y))
  480.                                 {
  481.                                     if (SimpleButtonMouseDown(Window.CancelButton,X,Y,NIL,NIL))
  482.                                         {
  483.                                             ReturnValue = eCancel;
  484.                                             goto ExitPoint;
  485.                                         }
  486.                                 }
  487.                             break;
  488.                         case eKeyPressed:
  489.                             if (Key == 13)
  490.                                 {
  491.                                     FlashButton(Window.YesButton);
  492.                                     ReturnValue = eYes;
  493.                                     goto ExitPoint;
  494.                                 }
  495.                             else if ((Key == eCancelKey) && (Window.CancelButton != NIL))
  496.                                 {
  497.                                     FlashButton(Window.CancelButton);
  498.                                     ReturnValue = eCancel;
  499.                                     goto ExitPoint;
  500.                                 }
  501.                             break;
  502.                     }
  503.             }
  504.  
  505.      ExitPoint:
  506.         DisposeSimpleButton(Window.YesButton);
  507.         DisposeSimpleButton(Window.NoButton);
  508.         if (Window.CancelButton != NIL)
  509.             {
  510.                 DisposeSimpleButton(Window.CancelButton);
  511.             }
  512.         ReleasePtr(Window.TotalMessage);
  513.         KillWindow(Window.ScreenID);
  514.         return ReturnValue;
  515.     }
  516.