home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / reference / amiga_mail_vol1 / intuition-wb / disabledrender next >
Text File  |  1990-01-26  |  21KB  |  689 lines

  1. (c)  Copyright 1989 Commodore-Amiga, Inc.   All rights reserved.
  2. The information contained herein is subject to change without notice, and 
  3. is provided "as is" without warranty of any kind, either expressed or implied.  
  4. The entire risk as to the use of this information is assumed by the user.
  5.  
  6.  
  7.  
  8.  
  9.            Disabled Render - How to Supply an Alternate 
  10.                Image for a Gadget Which Is Disabled
  11.  
  12.                         Adam Keith Levin   
  13.                 Commodore-Amiga Technical Support
  14.  
  15.  
  16.  
  17.  
  18. Intuition allows boolean gadgets to be rendered in many different ways -
  19. as plain text, as a simple line drawing or even as a custom bit mapped image.
  20. Intuition also provides several ways to show when a boolean gadget has been
  21. selected by the user.  Its rendering can be changed by complementing the 
  22. colors, drawing a box around the gadget, replacing the border or image with 
  23. a different border or image or by no change at all.
  24.  
  25. However, Intuition provides only one method for showing when a gadget is
  26. disabled and that is by ghosting.  A gadget which is disabled is temporarily 
  27. not available for use.  Intuition indicates this by ghosting the gadget's 
  28. image.  Ghosting is accomplished by overlaying a fine grid of pixels onto 
  29. the gadget.  This makes the image look "fuzzy".  When a disabled gadget is 
  30. subsequently enabled, the ghosting is removed and the gadget is again 
  31. available for use.
  32.  
  33. The program listed below shows an alternate method for indicating when a 
  34. boolean gadget is disabled.  You can use this program to provide a whole new
  35. custom image for the disabled gadget instead of using the ghosting feature
  36. of Intuition.
  37.  
  38. The ghosting feature of Intuition is provided through two routines OffGadget
  39. and OnGadget.  The program below provides two new routines, myOffGadget and
  40. myOnGadget.  Use these carefully.  They are not meant to be replacements for 
  41. OffGadget and OnGadget as they are not set up to handle more than one gadget 
  42. at a time.  They also work only with boolean gadgets.
  43.  
  44. The routine myOffGadget will cause the given gadget to stop generating both
  45. GADGETDOWN and GADGETUP events just as OffGadget will, but by a different
  46. method.  The myOffGadget routine does not set the GADGDISABLED flag in the 
  47. Flags field like OffGadget does.  This means that if your application is 
  48. handling the disabling of multiple gadgets and you have used myOffGadget 
  49. then you cannot check the status of the gadget by looking at the Flags field
  50. as you normally would.
  51.  
  52. Instead, you can look at the UserData field of the gadget.  The myOffGadget 
  53. routine must save a copy of the old GadgetRender and SelectRender pointers 
  54. and 2 IDCMP flags since it changes these and must restore them later.  To
  55. do this a pointer to a structure containing this information is placed in 
  56. the gadget's UserData field.  So, if the UserData field is not NULL then 
  57. myOffGadget has been called and the gadget is disabled - the UserData field 
  58. contains a pointer to the information needed to re-enable the gadget.
  59. If the UserData field is NULL, myOffGadget has not been called and the gadget
  60. is enabled. 
  61.  
  62. The example below handles the disabled rendering of image gadgets, not text 
  63. or border gadgets.  However, the method used is extensible to rendering these 
  64. other forms as well.  The example also assumes that boolean gadgets of fixed
  65. size are used as opposed to those which use GRELWIDTH, GRELHEIGHT, etc.
  66.  
  67. If the disabled rendering does not completely cover the original imagery,
  68. some of the original gadget will still be visible.  The example code 
  69. defines the disabled rendering as slightly larger than the gadget rendering, 
  70. so this is not a problem.  For more details on how the program works, see 
  71. the comments in the code.
  72.  
  73. Even though Intuition only provides one method for indicating to the user 
  74. that a gadget is disabled, it is not difficult to extend Intuition to provide
  75. an alternative method.  The DisabledRender program shows you how.
  76.  
  77.  
  78. ------------------- Lauren, code starts here -----------------------
  79.  
  80. /*
  81.  
  82.    DisabledRender
  83.  
  84.    A method for supplying a boolean gadget with alternate
  85.    (ie non-ghosted) imagery when it is disabled.
  86.  
  87.    Adam Keith Levin   Commodore-Amiga Technical Support
  88.  
  89.    Created with Manx's Aztec C v3.6a
  90.    For Manx, Compile with: cc DisabledRender.c +L
  91.             and Link with: ln DisabledRender.o -lc32
  92.  
  93.  
  94.  
  95.     O V E R V I E W
  96.  
  97.    A window with three boolean gadgets is created.
  98.       Two of the gadgets ("gadget1" and "gadget2") do nothing, but
  99.       have both gadget and select imagery.  The third gadget ("control")
  100.       alternately disables and enables the other two gadgets.
  101.  
  102.    Gadget1 is disabled and enabled normally, using OffGadget() and OnGadget().
  103.    Gadget2 is disabled by
  104.       1. Removing it from the gadget list.
  105.       2. Setting its GadgetRender and SelectRender fields to point
  106.          at a third "DisabledRender" Image structure.
  107.       3. Clearing the GADGIMMEDIATE and RELVERIFY bits in its
  108.          Activation flags field to prevent GADGETDOWN/GADGETUP events.
  109.       4. Saving the displaced information from steps 2 and 3 in a
  110.          special SavedGadgetData structure.
  111.       5. Adding the gadget to the gadget list in its previous position.
  112.       6. Calling RefreshGadgets() to display the "disabled" image.
  113.  
  114.    Gadget2 is enabled by
  115.       1. Removing it from the gadget list.
  116.       2. Restoring its previous GadgetRender and SelectRender fields.
  117.       3. Restoring the previous GADGIMMEDIATE and RELVERIFY bits in its
  118.          Activation flags field.  (The information for steps 2 and 3
  119.          is retrieved from the SavedGadgetData structure).
  120.       4. Adding it to the gadget list in its previous position.
  121.       5. Calling RefreshGadgets() to display the gadget image.
  122.  
  123.    Messages announcing gadget events are written
  124.       to the window via the console device.
  125.  
  126. */
  127.  
  128.  
  129. #include <exec/types.h>
  130. #include <exec/memory.h>
  131. #include <intuition/intuitionbase.h>
  132. #include <libraries/dos.h>
  133. #include <stdio.h>
  134.  
  135. struct IntuitionBase *IntuitionBase;
  136.  
  137.  
  138. /*  Image data for normal rendering of gadget1 and gadget2.  */
  139. USHORT newGadgetRenderData[] =
  140. {
  141.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  142.     0x0000,0x0000,0x0000,0x0000,0x0007,0xFF80,0x0007,0xFF80,
  143.     0x0007,0xFF80,0x0007,0xFF80,0x0007,0xFF80,0x0007,0xFF80,
  144.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  145.     0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
  146.     0x0001,0xFE60,0x0001,0xFE60,0x0001,0xFE60,0x0001,0xFE60,
  147.     0x0000,0x0060,0x0001,0xFFE0
  148. };
  149.  
  150. /*  Image data for select rendering of gadget1 and gadget2.  */
  151. USHORT newSelectRenderData[] =
  152. {
  153.     0xFFFF,0xFF80,0xFFFF,0xFF80,0xFFFF,0xFF80,0xFFFF,0xFF80,
  154.     0xFFFF,0xFF80,0xFFFF,0xFF80,0xFFFF,0xFF80,0xFFFF,0xFF80,
  155.     0xFFFF,0xFF80,0xFFFF,0xFF80,0xFFFF,0xFF80,0xFFFF,0xFF80,
  156.     0x0000,0x0000,0x0000,0x0000,0x3FFF,0xFE60,0x3FFF,0xFE60,
  157.     0x3FFF,0xFE60,0x3FFF,0xFE60,0x3FFF,0xFE60,0x3FFF,0xFE60,
  158.     0x3FFF,0xFE60,0x3FFF,0xFE60,0x3FFF,0xFE60,0x3FFF,0xFE60,
  159.     0x0000,0x0060,0x3FFF,0xFFE0
  160. };
  161.  
  162. /*  Image data for disabled rendering of gadget2.  */
  163. USHORT newDisabledRenderData[] =
  164. {
  165.     0x03FF,0x0000,0x1E01,0xE000,0x7380,0x3800,0xC0E0,0x0C00,
  166.     0xC038,0x0C00,0xC00E,0x0C00,0x7003,0xB800,0x1E01,0xE000,
  167.     0x03FF,0x0000,0x03FF,0x03FF,0x1E01,0xE3FF,0x7380,0x3BFF,
  168.     0xC0E0,0x0FFF,0xC038,0x0FFF,0xC00E,0x0FFF,0x7003,0xBBFF,
  169.     0x1E01,0xE3FF,0x03FF,0x03FF
  170. };
  171.  
  172.  
  173. /*
  174.     Make the default RenderData the newRenderData arrays.
  175.     If they are in chip RAM, they will be used as they are;
  176.     if in fast RAM, they will be copied to chip RAM by chipImage().
  177. */
  178. USHORT *gadgetRenderData = (USHORT *) &newGadgetRenderData,
  179.           *selectRenderData = (USHORT *) &newSelectRenderData,
  180.              *disabledRenderData = (USHORT *) &newDisabledRenderData;
  181.  
  182.  
  183. /*  The ImageData fields will be filled by prepImage()
  184.     once a chip RAM pointer is obtained from chipImage().
  185. */
  186. struct Image gadgetRender = {0,0,27,13,2,NULL,0x0003,0x0000,NULL},
  187.                 selectRender = {0,0,27,13,2,NULL,0x0003,0x0000,NULL}, 
  188.                    disabledRender = {5,4,22,9,2,NULL,0x0003,0x0000,NULL};
  189.  
  190.  
  191. /*  Imagery for the control gadget.  */
  192. SHORT vertices[] = { 0,0,75,0,75,12,0,12,0,0 };
  193. struct Border border = { -1,-1,3,0,JAM1,5,vertices,NULL };
  194. struct IntuiText intuiText = { 3,0,JAM2,8,2,NULL,(UBYTE *)"CONTROL",NULL };
  195.  
  196.  
  197. /*  Constants for GadgetID.  */
  198. #define GADGET1 0
  199. #define GADGET2 1
  200. #define CONTROL 2
  201.  
  202. struct Gadget control =
  203. {
  204.     NULL,
  205.     129,38,
  206.     74,11,
  207.     NULL,
  208.     RELVERIFY|TOGGLESELECT,
  209.     BOOLGADGET,
  210.     (APTR)&border,
  211.     NULL,
  212.     &intuiText,
  213.     NULL,
  214.     NULL,
  215.     CONTROL,
  216.     NULL
  217. };
  218.  
  219. struct Gadget gadget2 =
  220. {
  221.     &control,
  222.     178,18,
  223.     27,13,
  224.     GADGHIMAGE|GADGIMAGE,
  225.     RELVERIFY,
  226.     BOOLGADGET,
  227.     (APTR)&gadgetRender,
  228.     (APTR)&selectRender,
  229.     NULL,
  230.     NULL,
  231.     NULL,
  232.     GADGET2,
  233.     NULL
  234. };
  235.  
  236. struct Gadget gadget1 =
  237. {
  238.     &gadget2,
  239.     128,18,
  240.     27,13,
  241.     GADGHIMAGE|GADGIMAGE,
  242.     RELVERIFY,
  243.     BOOLGADGET,
  244.     (APTR)&gadgetRender,
  245.     (APTR)&selectRender,
  246.     NULL,
  247.     NULL,
  248.     NULL,
  249.     GADGET1,
  250.     NULL
  251. };
  252.  
  253.  
  254. /*  The return value from OpenDevice() is used to
  255.     tell whether the console.device was opened or not.
  256. */
  257. LONG consoleOpen = 1L;
  258.  
  259. struct IOStdReq *console;
  260. struct MsgPort *msgPort;
  261. struct Window *window;
  262. struct NewWindow newWindow =
  263. {
  264.     148,47,
  265.     340,105,
  266.     0,1,
  267.     GADGETUP|CLOSEWINDOW,
  268.     WINDOWDRAG|WINDOWDEPTH|WINDOWCLOSE|ACTIVATE|NOCAREREFRESH,
  269.     NULL,  /*  The gadget list will be attached later.  */
  270.     NULL,
  271.     (UBYTE *)"DisabledRender",
  272.     NULL,
  273.     NULL,
  274.     5,5,
  275.     -1,-1,
  276.     WBENCHSCREEN
  277. };
  278.  
  279.  
  280. /*  Anchor for AllocRemember.  */
  281. struct Remember *remember = NULL;
  282.  
  283. /*  Console control sequence characters to set top offset
  284.     of text and to turn window cursor off.
  285. */
  286. char conPrep[] =
  287. {
  288.     0x9b, 0x35, 0x35, 0x79, 0x9b, 0x30, 0x20, 0x70, 0x00
  289. };
  290.  
  291. /*  Indication of where this program started from.  */
  292. BOOL fromCLI = FALSE;
  293.  
  294.  
  295. main(argc, argv)
  296. int argc;
  297. char *argv[];
  298. {
  299. BOOL windowOpen=TRUE;    /*  FALSE once user has clicked close gadget.  */
  300. ULONG class;    /*  IntuiMessage Class.  */
  301. APTR iAddress;    /*  IntuiMessage IAddress.  */
  302. struct IntuiMessage *intuiMessage;
  303. BOOL prepImage();
  304. void cPrint(), doGadget(), cleanExit();
  305.  
  306.  
  307.     /*  If started from CLI, set global variable to TRUE.  */
  308.     if (argc) fromCLI = TRUE;
  309.  
  310.     IntuitionBase =
  311.         (struct IntuitionBase *) OpenLibrary("intuition.library", 0L);
  312.  
  313.     if (IntuitionBase == NULL)
  314.         cleanExit("\nUnable to open \"intuition.library\".\n",
  315.             ERROR_INVALID_RESIDENT_LIBRARY);
  316.  
  317.     /*  Ensure that gadget imagery is in chip RAM.  */
  318.     if (prepImage() != TRUE)
  319.         cleanExit("\nInsufficent chip RAM for gadget imagery.\n",
  320.             ERROR_NO_FREE_STORE);
  321.  
  322.     window = (struct Window *) OpenWindow(&newWindow);
  323.     if (window == NULL)
  324.         cleanExit("\nUnable to open a window.\n", RETURN_FAIL);
  325.  
  326.     msgPort = (struct MsgPort *) CreatePort("DisabledRender", 0L);
  327.     if (msgPort == NULL) 
  328.         cleanExit("\nUnable to create a message port.\n", RETURN_FAIL);
  329.  
  330.     console = (struct IOStdReq *) CreateStdIO(msgPort);
  331.     if (console == NULL)
  332.         cleanExit("\nUnable to create a standard I/O requester.\n",
  333.             RETURN_FAIL);
  334.  
  335.     console->io_Data = (APTR) window;
  336.     console->io_Length = (LONG) sizeof(*window);
  337.  
  338.     consoleOpen = OpenDevice("console.device", 0L, console, 0L);
  339.     if (consoleOpen != 0L)
  340.         cleanExit("\nUnable to open \"console.device\".\n", RETURN_FAIL);
  341.  
  342.     /*  Send control sequences to set top offset and invisible cursor.  */
  343.     cPrint(console, conPrep);
  344.  
  345.     /*  Print a welcome message.  */
  346.     cPrint(console, "Gadget events are announced here.\n");
  347.  
  348.     /*  Add the gadget list and see that it is displayed.  */
  349.     (void) AddGList(window, &gadget1, -1, -1, NULL);
  350.     RefreshGadgets(&gadget1, window, NULL);
  351.  
  352.     /*  Intuition event processing loop.  */
  353.     while (windowOpen)
  354.     {
  355.         (void) Wait(1<<window->UserPort->mp_SigBit);
  356.         while (intuiMessage = (struct IntuiMessage *) GetMsg(window->UserPort))
  357.         {
  358.             class = intuiMessage->Class;
  359.             iAddress = intuiMessage->IAddress;
  360.             ReplyMsg(intuiMessage);
  361.  
  362.             switch (class)
  363.             {
  364.                 case (CLOSEWINDOW):
  365.                     windowOpen = FALSE;
  366.                     cPrint(console, "\nCLOSEWINDOW.");
  367.                     Delay(2L * TICKS_PER_SECOND);
  368.                     break;
  369.                 case (GADGETUP):
  370.                     cPrint(console, "\nGADGETUP:  ");
  371.                     doGadget(window, ((struct Gadget *)iAddress)->GadgetID);
  372.                     break;
  373.                 default:
  374.                     break;
  375.             } /*  end switch(class)  */
  376.         } /*  end while(intuiMessage...  */
  377.     } /*  end while(windowOpen)  */
  378.  
  379.     cleanExit(NULL, RETURN_OK);
  380. }
  381.  
  382.  
  383. /*  Return code from chipImage() to prepImage().  */
  384. #define cI_ORIG    0    /*  Array was already in chip RAM.  */
  385. #define cI_COPY    1    /*  Array was copied to chip RAM.  */
  386. #define cI_FAIL    2    /*  Array could not be copied to chip RAM.  */
  387.  
  388. /*
  389.     prepImage
  390.     Ensures that the gadget imagery is in chip RAM.
  391. */
  392. BOOL
  393. prepImage()
  394. {
  395.     /*  Ensure that gadgetRenderData points to an array in chip RAM.  */
  396.     if (chipImage(&gadgetRenderData, sizeof(newGadgetRenderData)) == cI_FAIL)
  397.         return(FALSE);
  398.  
  399.     /*  Fill the ImageData field of the gadgetRender Image structure.  */
  400.     gadgetRender.ImageData = gadgetRenderData;
  401.  
  402.     if (chipImage(&selectRenderData, sizeof(newSelectRenderData)) == cI_FAIL)
  403.         return(FALSE);
  404.     selectRender.ImageData = selectRenderData;
  405.  
  406.    if (chipImage(&disabledRenderData, sizeof(newDisabledRenderData)) == cI_FAIL)
  407.         return(FALSE);
  408.     disabledRender.ImageData = disabledRenderData;
  409.  
  410.     return(TRUE);
  411. }
  412.  
  413.  
  414. /*  chipImage
  415.     Ensures that the array pointed to by imageData is in
  416.     chip RAM.  It creates a chip RAM copy if necessary.
  417. */
  418. int
  419. chipImage(imageData, sizeOfImageData)
  420. USHORT **imageData;
  421. int sizeOfImageData;
  422. {
  423. USHORT *tmpImageData;
  424.  
  425.     /*  If it is already in CHIP RAM, return.  */
  426.     if (TypeOfMem(*imageData) & MEMF_CHIP) return(cI_ORIG);
  427.  
  428.     /*  Otherwise create a copy in CHIP RAM and point imageData to it.  */
  429.     else
  430.     {
  431.         tmpImageData = (USHORT *)
  432.             AllocRemember(&remember, sizeOfImageData, MEMF_CHIP|MEMF_PUBLIC);
  433.  
  434.         if (tmpImageData != NULL)
  435.         {
  436.             CopyMem(*imageData, tmpImageData, sizeOfImageData);
  437.             *imageData = tmpImageData;
  438.             return(cI_COPY);
  439.         }
  440.     }
  441.     return(cI_FAIL);
  442. }
  443.  
  444.  
  445. /*
  446.     doGadget
  447.     Handles the gadget events.  "Gadget1" and "gadget2" do nothing.
  448.     "Control" alternately disables and enables gadget1 and gadget2.
  449. */
  450. void
  451. doGadget(window, gadgetID)
  452. struct Window *window;
  453. USHORT gadgetID;
  454. {
  455. static BOOL on=TRUE;
  456. void cPrint(), myOffGadget(), myOnGadget();
  457.  
  458.     switch (gadgetID)
  459.     {
  460.         case (GADGET1):
  461.             cPrint(console, "Left gadget.");
  462.             break;
  463.         case (GADGET2):
  464.             cPrint(console, "Right gadget.");
  465.             break;
  466.         case (CONTROL):
  467.             cPrint(console, "Control gadget.\nLeft and right gadgets are now ");
  468.                 if (on)
  469.                 {
  470.                     /*  Normal method of disabling.  Image will be ghosted.  */ 
  471.                     OffGadget(&gadget1, window, NULL);
  472.  
  473.                     /*  Alternate method of disabling.  "Disabled" image
  474.                         will be displayed.
  475.                     */
  476.                     myOffGadget(&gadget2, window, NULL, &disabledRender);
  477.  
  478.                     on = FALSE;
  479.                     cPrint(console, "disabled.");
  480.                 }
  481.                 else
  482.                 {
  483.                     /*  Normal method of enabling.  */
  484.                     OnGadget(&gadget1, window, NULL);
  485.  
  486.                     /*  Alternate method of enabling.  */
  487.                     myOnGadget(&gadget2, window, NULL);
  488.  
  489.                     on = TRUE;
  490.                     cPrint(console, "enabled.");
  491.                 }
  492.                 break;
  493.             default:
  494.                 cPrint(console, "Unknown gadget.");
  495.             break;
  496.     }
  497. }
  498.  
  499.  
  500. /*  A mask to clear and restore the corresponding Activation flags.  */
  501. #define GI_RV    (GADGIMMEDIATE|RELVERIFY)
  502.  
  503. /*  A structure to hold gadget information while the gadget is disabled.  */
  504. struct SavedGadgetData
  505. {
  506.     USHORT Activation;
  507.     APTR gadgetRender;
  508.     APTR selectRender;
  509. };
  510.  
  511. /*  Since there is only one gadget to be disabled with this example method,
  512.     an instance of the SavedGadgetData structure is declared.
  513.     If several gadgets will be disabled, it is advised that memory
  514.     for each be allocated at runtime.
  515. */
  516. struct SavedGadgetData savedGadgetData;
  517.  
  518.  
  519. /*  myOffGadget
  520.     Disables a boolean gadget by clearing the GADGIMMEDIATE and RELVERIFY
  521.     Activation flags and swaping in a third "disabled" image for
  522.     both the gadget and select images.  The removed information is saved 
  523.     in a SavedGadgetData structure which is hung off of Gadget->UserID.
  524. */
  525. void
  526. myOffGadget(gadget, window, requester, image)
  527. struct Gadget *gadget;
  528. struct Window *window;
  529. struct Requester *requester;
  530. struct Image *image;
  531. {
  532. USHORT position;
  533.  
  534.     /*  Ensure that this gadget is not currently disabled by
  535.         either the normal method or by the method in this example.
  536.         This test should always fail, but the check is here nonetheless.
  537.     */
  538.     if ((gadget->Flags & GADGDISABLED) || (gadget->UserData != NULL))
  539.         return;
  540.  
  541.     /*  Remove the gadget so changes may be made.  */
  542.     position = RemoveGadget(window, gadget);
  543.  
  544.     /*  Save Gadget and Select renderings.  */
  545.     savedGadgetData.gadgetRender = gadget->GadgetRender;
  546.     savedGadgetData.selectRender = gadget->SelectRender;
  547.  
  548.     /*  Swap in disabledRender image.  */
  549.     gadget->GadgetRender = gadget->SelectRender = image;
  550.  
  551.     /*  Save the current GI_RV state.  */
  552.     savedGadgetData.Activation = gadget->Activation & GI_RV;
  553.  
  554.     /*  Keep gadget from causing IDCMP messages by clearing
  555.         both the GADGIMMEDIATE and RELVERIFY Activation Flags.
  556.     */
  557.     gadget->Activation &= ~GI_RV;
  558.  
  559.     /*  Put the address of the savedGadgetData structure in the UserData
  560.         field of the gadget, to be used when it is re-enabled.
  561.     */
  562.     gadget->UserData = (APTR) &savedGadgetData;
  563.  
  564.     (void) AddGadget(window, gadget, position);
  565.     RefreshGadgets(gadget, window, requester);
  566. }
  567.  
  568.  
  569. /*  myOnGadget
  570.     Enables a gadget by restoring the GADGIMMEDIATE and RELVERIFY
  571.     Activation flags as well as the gadget and select images.
  572.     The information is retrieved from the SavedGadgetData structure.
  573. */
  574. void
  575. myOnGadget(gadget, window, requester)
  576. struct Gadget *gadget;
  577. struct Window *window;
  578. struct Requester *requester;
  579. {
  580. USHORT position;
  581.  
  582.  
  583.     /*  Ensure that this gadget was disabled.  */
  584.     if (gadget->UserData == NULL) return;
  585.  
  586.     position = RemoveGadget(window, gadget);
  587.  
  588.     /*  Restore the Gadget and Select rendering.  */
  589.     gadget->GadgetRender = savedGadgetData.gadgetRender;
  590.     gadget->SelectRender = savedGadgetData.selectRender;
  591.  
  592.     /*  Restore the gadget's ability to cause IDCMP messages
  593.         by restoring the previous state of the
  594.         GADGIMMEDIATE and RELVERIFY Activation Flags.
  595.     */
  596.     gadget->Activation |= savedGadgetData.Activation;
  597.  
  598.     /*  Clear the gadget's UserData field to indicate that it is enabled.  */
  599.     gadget->UserData = NULL;
  600.  
  601.     (void) AddGadget(window, gadget, position);
  602.     RefreshGadgets(gadget, window, requester);
  603. }
  604.  
  605.  
  606. /*
  607.     cPrint
  608.     Sends the given (NULL terminated) string to the given console window.
  609. */
  610. void
  611. cPrint(ioStdReq, string)
  612. struct IOStdReq *ioStdReq;
  613. char *string;
  614. {
  615.     if (*string)
  616.     {
  617.         ioStdReq->io_Data = (APTR) string;
  618.         ioStdReq->io_Length = -1L;
  619.         ioStdReq->io_Command = CMD_WRITE;
  620.  
  621.         (void) DoIO(ioStdReq);
  622.     }
  623. }
  624.  
  625.  
  626. /*  cleanExit
  627.     Prints an exit message.
  628.     Replys to any pending console messages, closes the console.device,
  629.         deletes the I/O request block and the message Port.
  630.     Replys to any pending Intuition messages, closes the window.
  631.     Frees any allocated memory.
  632.     Closes the Intuition library.
  633.     Exits with an exit value.
  634. */
  635.  
  636. void
  637. cleanExit(exitString, exitValue)
  638. char *exitString;
  639. int exitValue;
  640. {
  641. struct FileHandle *fileHandle;
  642. struct Message *message;
  643. struct IntuiMessage *intuiMessage;
  644.  
  645.     if (*exitString)
  646.     {
  647.         fileHandle = (struct FileHandle *)
  648.             Open("CON:138/100/358/50/DisabledRender Message", MODE_OLDFILE);
  649.         if (fileHandle != NULL)
  650.         {
  651.             (void) Write(fileHandle, exitString, strlen(exitString));
  652.             Delay(10L * TICKS_PER_SECOND);
  653.             Close(fileHandle);
  654.         }
  655.         else
  656.         {
  657.             if (fromCLI)
  658.                 (void) fprintf(stderr, exitString);
  659.        }
  660.     }
  661.  
  662.     if (consoleOpen == 0) CloseDevice(console);
  663.  
  664.     if (console) DeleteStdIO(console);
  665.  
  666.     if (msgPort)
  667.     {
  668.         while (message = (struct Message *) GetMsg(msgPort))
  669.             ReplyMsg(message);
  670.         DeletePort(msgPort);
  671.     }
  672.  
  673.     if (window)
  674.     {
  675.         while (intuiMessage = (struct IntuiMessage *) GetMsg(window->UserPort))
  676.             ReplyMsg(intuiMessage);
  677.         CloseWindow(window);
  678.     }
  679.  
  680.     if (remember) FreeRemember(&remember, TRUE);
  681.  
  682.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  683.  
  684.     exit(exitValue);
  685. }
  686.  
  687.  
  688.  
  689.