home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / 3_1EXAM1.DMS / in.adf / intuition / attachdemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-17  |  18.7 KB  |  912 lines

  1. /*
  2.  * attachdemo.c - demonstrates handling attached screens
  3.  *
  4.  * (c) Copyright 1992-93 Commodore-Amiga, Inc.  All rights reserved.
  5.  *
  6.  * This software is provided as-is and is subject to change; no warranties
  7.  * are made.  All use is at your own risk.  No liability or responsibility
  8.  * is assumed.
  9.  *
  10.  */
  11.  
  12. /*----------------------------------------------------------------------*/
  13.  
  14. #include <exec/types.h>
  15. #include <graphics/displayinfo.h>
  16. #include <intuition/intuition.h>
  17. #include <intuition/intuitionbase.h>
  18.  
  19. #include <clib/exec_protos.h>
  20. #include <clib/graphics_protos.h>
  21. #include <clib/intuition_protos.h>
  22. #include <clib/gadtools_protos.h>
  23.  
  24. /*----------------------------------------------------------------------*/
  25.  
  26. struct ScreenDescriptor
  27. {
  28.     LONG sd_Top;    /* Top edge in non-lace coords */
  29.     LONG sd_Open;    /* If screen is supposed to be open */
  30.     LONG sd_Lace;    /* If screen is supposed to be lace */
  31.     LONG sd_Size;    /* Screen's intended size (see below) */
  32.     LONG sd_Drag;    /* If screen is supposed to be draggable */
  33.     LONG sd_IsLace;    /* If screen was actually last lace */
  34. };
  35.  
  36. #define SIZE_NORMAL    0
  37. #define SIZE_TALL    1
  38. #define SIZE_WIDE    2
  39. #define SIZE_HUGE    3
  40.  
  41. /*----------------------------------------------------------------------*/
  42.  
  43. void error_exit( STRPTR errorstring );
  44. void CloseWindowSafely( struct Window *win );
  45. void StripIntuiMessages( struct MsgPort *mp, struct Window *win );
  46. struct Screen *findPanelScreen( void );
  47. struct Window *openPanel( void );
  48. void closePanel( void );
  49. void handleGadget( struct Gadget *gad, UWORD code );
  50. void jiggleScreen( struct Screen *sc, ULONG flags );
  51.  
  52. /*----------------------------------------------------------------------*/
  53.  
  54. struct GfxBase *GfxBase = NULL;
  55. struct IntuitionBase *IntuitionBase = NULL;
  56. struct Library *GadToolsBase = NULL;
  57. struct MsgPort *sharedport = NULL;
  58. void *panel_vi = NULL;
  59. struct Gadget *panel_gadgets = NULL;
  60. struct Window *panel_win = NULL;
  61. struct Screen *panel_screen = NULL;
  62.  
  63. struct Screen *parent_sc = NULL;
  64. struct Screen *child_sc = NULL;
  65. struct ScreenDescriptor parent_desc =
  66. {
  67.     0,            /* sd_Top */
  68.     FALSE,        /* sd_Open */
  69.     FALSE,        /* sd_Lace */
  70.     SIZE_NORMAL,    /* sd_Size */
  71.     TRUE,        /* sd_Drag */
  72. };
  73.  
  74. struct ScreenDescriptor child_desc =
  75. {
  76.     80,            /* sd_Top */
  77.     TRUE,        /* sd_Open */
  78.     FALSE,        /* sd_Lace */
  79.     SIZE_NORMAL,    /* sd_Size */
  80.     TRUE,        /* sd_Drag */
  81. };
  82.  
  83. /*----------------------------------------------------------------------*/
  84.  
  85. #define CHILD_MAGIC    ( (APTR)0x0FACE0FF )
  86. #define PARENT_MAGIC    ( (APTR)0x8FACE0FF )
  87.  
  88. #define GAD_PARENT_OPEN    0    /* settable */
  89. #define GAD_PARENT_LACE    1
  90. #define GAD_PARENT_SIZE    2
  91. #define GAD_PARENT_DRAG    3
  92.  
  93. #define GAD_CHILD_OPEN    4    /* settable */
  94. #define GAD_CHILD_LACE    5
  95. #define GAD_CHILD_SIZE    6
  96. #define GAD_CHILD_DRAG    7
  97.  
  98. #define GAD_FORWARD    8
  99. #define GAD_BACK    9
  100. #define GAD_CFORWARD    10
  101. #define GAD_CBACK    11
  102.  
  103. #define GAD_MOVEPARENT    12
  104. #define GAD_MOVECHILD    13
  105. #define GAD_FMOVEPARENT    14
  106. #define GAD_FMOVECHILD    15
  107.  
  108. #define GAD_HOMEPARENT    16
  109. #define GAD_HOMECHILD    17
  110.  
  111. #define NUM_SETTABLE    2
  112.  
  113. struct Gadget *mygad[ NUM_SETTABLE ];
  114.  
  115. UWORD pens[] =
  116. {
  117.     0, /* DETAILPEN */
  118.     1, /* BLOCKPEN    */
  119.     1, /* TEXTPEN    */
  120.     2, /* SHINEPEN    */
  121.     1, /* SHADOWPEN    */
  122.     3, /* FILLPEN    */
  123.     1, /* FILLTEXTPEN    */
  124.     0, /* BACKGROUNDPEN    */
  125.     2, /* HIGHLIGHTTEXTPEN    */
  126.  
  127.     1, /* BARDETAILPEN    */
  128.     2, /* BARBLOCKPEN    */
  129.     1, /* BARTRIMPEN    */
  130.  
  131.     ~0,
  132. };
  133.  
  134. /*----------------------------------------------------------------------*/
  135.  
  136. STRPTR OpenLabels[] =
  137. {
  138.     "Closed",
  139.     "Open",
  140.     NULL,
  141. };
  142.  
  143. STRPTR LaceLabels[] =
  144. {
  145.     "Non-Laced",
  146.     "Interlaced",
  147.     NULL,
  148. };
  149.  
  150. STRPTR SizeLabels[] =
  151. {
  152.     "Normal",
  153.     "Tall",
  154.     "Wide",
  155.     "Huge",
  156.     NULL,
  157. };
  158.  
  159. STRPTR DragLabels[] =
  160. {
  161.     "Non-Drag",
  162.     "Draggable",
  163.     NULL,
  164. };
  165.  
  166. LONG scwidth[ 4 ] =
  167. {
  168.     640, 640, 960, 960,    /* normal, tall, wide, huge */
  169. };
  170.  
  171. LONG cheight[ 4 ] =
  172. {
  173.     
  174.     120, 380, 120, 380,    /* normal, tall, wide, huge */
  175. };
  176.  
  177. LONG pheight[ 4 ] =
  178. {
  179.     
  180.     200, 400, 200, 400,    /* normal, tall, wide, huge */
  181. };
  182.  
  183. /*----------------------------------------------------------------------*/
  184.  
  185. struct Screen *
  186. openMyScreen( BOOL isparent )
  187. {
  188.     struct Screen *sc;
  189.     LONG top, drag, width, height, id;
  190.     STRPTR title;
  191.     ULONG attachtag;
  192.     APTR userdata;
  193.     struct Screen *attachdata = NULL;
  194.  
  195.     if ( isparent )
  196.     {
  197.     top = parent_desc.sd_Top;
  198.     drag = parent_desc.sd_Drag;
  199.     width = scwidth[ parent_desc.sd_Size ];
  200.     if ( parent_desc.sd_Lace )
  201.     {
  202.         title = "Laced Parent";
  203.         height = 2*pheight[ parent_desc.sd_Size ];
  204.         top *= 2;
  205.         id = HIRESLACE_KEY;
  206.     }
  207.     else
  208.     {
  209.         title = "Non-laced Parent";
  210.         height = pheight[ parent_desc.sd_Size ];
  211.         id = HIRES_KEY;
  212.     }
  213.     attachtag = SA_FrontChild;
  214.     attachdata = child_sc;
  215.     userdata = CHILD_MAGIC;
  216.     }
  217.     else
  218.     {
  219.     top = child_desc.sd_Top;
  220.     drag = child_desc.sd_Drag;
  221.     width = scwidth[ child_desc.sd_Size ];
  222.     if ( child_desc.sd_Lace )
  223.     {
  224.         title = "Laced Child";
  225.         height = cheight[ child_desc.sd_Size ]*2;
  226.         top *= 2;
  227.         id = HIRESLACE_KEY;
  228.     }
  229.     else
  230.     {
  231.         title = "Non-laced Child";
  232.         height = cheight[ child_desc.sd_Size ];
  233.         id = HIRES_KEY;
  234.     }
  235.     attachtag = SA_Parent;
  236.     attachdata = parent_sc;
  237.     userdata = PARENT_MAGIC;
  238.     }
  239.     
  240.     if ( sc = OpenScreenTags( NULL,
  241.     SA_DisplayID, id,
  242.     SA_Top, top,
  243.     SA_Title, title,
  244.     SA_Width, width,
  245.     SA_Height, height,
  246.     SA_Overscan, OSCAN_TEXT,
  247.     /*  Other tags can go here: */
  248.     SA_Depth, 2,
  249.     SA_Pens, pens,
  250.     SA_Draggable, drag,
  251.     SA_AutoScroll, TRUE,
  252.     attachtag, attachdata,
  253.     TAG_DONE ) )
  254.     {
  255.     sc->UserData = userdata;
  256.     }
  257.     return( sc );
  258. }
  259.  
  260. struct Screen *
  261. closeMyScreen( struct Screen *sc )
  262. {
  263.     if ( sc )
  264.     {
  265.     if ( panel_screen == sc )
  266.     {
  267.         closePanel();
  268.     }
  269.     CloseScreen( sc );
  270.     }
  271.     return( ( struct Screen * )NULL );
  272. }
  273.  
  274. /*----------------------------------------------------------------------*/
  275.  
  276. void
  277. main( void )
  278.  
  279. {
  280.     BOOL done = FALSE;
  281.     struct IntuiMessage *imsg;
  282.     ULONG imsgClass;
  283.     UWORD imsgCode;
  284.     APTR imsgIAddress;
  285.  
  286.     if ( !( GfxBase = ( struct GfxBase * )
  287.     OpenLibrary( "graphics.library", 39L ) ) )
  288.     {
  289.     error_exit( "Couldn't open Gfx V39\n" );
  290.     }
  291.  
  292.     if ( !( IntuitionBase = ( struct IntuitionBase * )
  293.     OpenLibrary( "intuition.library", 39L ) ) )
  294.     {
  295.     error_exit( "Couldn't open Intuition V39\n" );
  296.     }
  297.  
  298.     if ( !( GadToolsBase =
  299.     OpenLibrary( "gadtools.library", 39L ) ) )
  300.     {
  301.     error_exit( "Couldn't open GadTools V39\n" );
  302.     }
  303.  
  304.     if ( !( sharedport = CreateMsgPort() ) )
  305.     {
  306.     error_exit( "No port\n" );
  307.     }
  308.  
  309.     if ( child_desc.sd_Open )
  310.     {
  311.     child_sc = openMyScreen( FALSE );
  312.     child_desc.sd_IsLace = child_desc.sd_Lace;
  313.     }
  314.  
  315.     if ( parent_desc.sd_Open )
  316.     {
  317.     parent_sc = openMyScreen( TRUE );
  318.     parent_desc.sd_IsLace = parent_desc.sd_Lace;
  319.     }
  320.  
  321.     openPanel();
  322.  
  323.     while ( !done )
  324.     {
  325.     Wait( 1 << sharedport->mp_SigBit );
  326.     while ( imsg = GT_GetIMsg( sharedport ) )
  327.     {
  328.         imsgClass = imsg->Class;
  329.         imsgCode = imsg->Code;
  330.         imsgIAddress = imsg->IAddress;
  331.         GT_ReplyIMsg( imsg );
  332.  
  333.         switch ( imsgClass )
  334.         {
  335.         case CLOSEWINDOW:
  336.             done = TRUE;
  337.             break;
  338.  
  339.         case REFRESHWINDOW:
  340.             /* Only the panel-window has IDCMP_REFRESHWINDOW set */
  341.             GT_BeginRefresh( panel_win );
  342.             GT_EndRefresh( panel_win, TRUE );
  343.             break;
  344.  
  345.         case GADGETUP:
  346.             handleGadget( imsgIAddress, imsgCode );
  347.             break;
  348.         }
  349.     }
  350.     }
  351.     error_exit( NULL );
  352. }
  353.  
  354.  
  355. /*----------------------------------------------------------------------*/
  356.  
  357. void error_exit( STRPTR errorstring )
  358.  
  359. {
  360.     closePanel();
  361.  
  362.     closeMyScreen( child_sc );
  363.  
  364.     closeMyScreen( parent_sc );
  365.  
  366.     if ( sharedport )
  367.     {
  368.     DeleteMsgPort( sharedport );
  369.     }
  370.  
  371.     if ( GadToolsBase )
  372.     {
  373.     CloseLibrary( GadToolsBase );
  374.     }
  375.  
  376.     if ( IntuitionBase )
  377.     {
  378.     CloseLibrary( ( struct Library * )IntuitionBase );
  379.     }
  380.  
  381.     if ( GfxBase )
  382.     {
  383.     CloseLibrary( GfxBase );
  384.     }
  385.  
  386.     if ( errorstring )
  387.     {
  388.     printf( errorstring );
  389.     exit( 20 );
  390.     }
  391.  
  392.     exit( 0 );
  393. }
  394.  
  395.  
  396. /*----------------------------------------------------------------------*/
  397.  
  398. /* these functions close an Intuition window
  399.  * that shares a port with other Intuition
  400.  * windows or IPC customers.
  401.  *
  402.  * We are careful to set the UserPort to
  403.  * null before closing, and to free
  404.  * any messages that it might have been
  405.  * sent.
  406.  */
  407.  
  408. void CloseWindowSafely( win )
  409. struct Window *win;
  410. {
  411.     /* we forbid here to keep out of race conditions with Intuition */
  412.     Forbid();
  413.  
  414.     /* send back any messages for this window 
  415.      * that have not yet been processed
  416.      */
  417.     StripIntuiMessages( win->UserPort, win );
  418.  
  419.     /* clear UserPort so Intuition will not free it */
  420.     win->UserPort = NULL;
  421.  
  422.     /* tell Intuition to stop sending more messages */
  423.     ModifyIDCMP( win, 0L );
  424.  
  425.     /* turn multitasking back on */
  426.     Permit();
  427.  
  428.     /* and really close the window */
  429.     CloseWindow( win );
  430. }
  431.  
  432. /* remove and reply all IntuiMessages on a port that
  433.  * have been sent to a particular window
  434.  * ( note that we don't rely on the ln_Succ pointer
  435.  *  of a message after we have replied it )
  436.  */
  437. void StripIntuiMessages( mp, win )
  438. struct MsgPort *mp;
  439. struct Window *win;
  440. {
  441.     struct IntuiMessage *msg;
  442.     struct Node *succ;
  443.  
  444.     msg = ( struct IntuiMessage * ) mp->mp_MsgList.lh_Head;
  445.  
  446.     while( succ =  msg->ExecMessage.mn_Node.ln_Succ ) {
  447.  
  448.     if( msg->IDCMPWindow ==  win ) {
  449.  
  450.         /* Intuition is about to free this message.
  451.          * Make sure that we have politely sent it back.
  452.          */
  453.         Remove( ( struct Node * )msg );
  454.  
  455.         ReplyMsg( ( struct Message * )msg );
  456.     }
  457.         
  458.     msg = ( struct IntuiMessage * ) succ;
  459.     }
  460. }
  461.  
  462. /*----------------------------------------------------------------------*/
  463.  
  464. struct TextAttr Topaz80 =
  465. {
  466.     "topaz.font",
  467.     8,
  468.     0,
  469.     0,
  470. };
  471.  
  472. struct Window *openPanel( void )
  473. {
  474.     struct NewGadget ng;
  475.     struct Gadget *gad;
  476.     LONG topborder;
  477.     int settable = 0;
  478.  
  479.     panel_screen = findPanelScreen();
  480.  
  481.     topborder = panel_screen->WBorTop + panel_screen->Font->ta_YSize + 1;
  482.  
  483.     if ( panel_vi = GetVisualInfo( panel_screen,
  484.     TAG_DONE ) )
  485.     {
  486.     gad = CreateContext( &panel_gadgets );
  487.  
  488.     ng.ng_LeftEdge = 90;
  489.     ng.ng_TopEdge = 2+topborder;
  490.     ng.ng_GadgetText = "Parent";
  491.     ng.ng_Width = 120;
  492.     ng.ng_Height = 14;
  493.     ng.ng_TextAttr = &Topaz80;
  494.     ng.ng_VisualInfo = panel_vi;
  495.     ng.ng_GadgetID = GAD_PARENT_OPEN;
  496.     ng.ng_UserData = &parent_desc.sd_Open;
  497.     ng.ng_Flags = NULL;
  498.  
  499.     mygad[ settable++ ] = gad = CreateGadget( CYCLE_KIND, gad, &ng,
  500.         GTCY_Labels, OpenLabels,
  501.         GTCY_Active, parent_desc.sd_Open,
  502.         TAG_DONE );
  503.     ng.ng_GadgetText = NULL;
  504.     ng.ng_UserData = 0;
  505.  
  506.     ng.ng_LeftEdge += 130;
  507.     ng.ng_GadgetID++;
  508.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  509.         GTCY_Labels, LaceLabels,
  510.         GTCY_Active, parent_desc.sd_Lace,
  511.         TAG_DONE );
  512.  
  513.     ng.ng_LeftEdge += 130;
  514.     ng.ng_GadgetID++;
  515.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  516.         GTCY_Labels, SizeLabels,
  517.         GTCY_Active, parent_desc.sd_Size,
  518.         TAG_DONE );
  519.  
  520.     ng.ng_LeftEdge += 130;
  521.     ng.ng_GadgetID++;
  522.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  523.         GTCY_Labels, DragLabels,
  524.         GTCY_Active, parent_desc.sd_Drag,
  525.         TAG_DONE );
  526.  
  527.     ng.ng_LeftEdge = 90;
  528.     ng.ng_TopEdge += 18;
  529.     ng.ng_GadgetText = "Child";
  530.     ng.ng_GadgetID++;
  531.     ng.ng_UserData = &child_desc.sd_Open;
  532.  
  533.     mygad[ settable++ ] = gad = CreateGadget( CYCLE_KIND, gad, &ng,
  534.         GTCY_Labels, OpenLabels,
  535.         GTCY_Active, child_desc.sd_Open,
  536.         TAG_DONE );
  537.     ng.ng_GadgetText = NULL;
  538.     ng.ng_UserData = NULL;
  539.  
  540.     ng.ng_LeftEdge += 130;
  541.     ng.ng_GadgetID++;
  542.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  543.         GTCY_Labels, LaceLabels,
  544.         GTCY_Active, child_desc.sd_Lace,
  545.         TAG_DONE );
  546.  
  547.     ng.ng_LeftEdge += 130;
  548.     ng.ng_GadgetID++;
  549.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  550.         GTCY_Labels, SizeLabels,
  551.         GTCY_Active, child_desc.sd_Size,
  552.         TAG_DONE );
  553.  
  554.     ng.ng_LeftEdge += 130;
  555.     ng.ng_GadgetID++;
  556.     gad = CreateGadget( CYCLE_KIND, gad, &ng,
  557.         GTCY_Labels, DragLabels,
  558.         GTCY_Active, child_desc.sd_Drag,
  559.         TAG_DONE );
  560.  
  561.     ng.ng_LeftEdge = 90;
  562.     ng.ng_TopEdge += 18;
  563.     ng.ng_GadgetText = "Forward";
  564.     ng.ng_GadgetID++;
  565.     ng.ng_UserData = SDEPTH_TOFRONT;
  566.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  567.         TAG_DONE );
  568.  
  569.     ng.ng_LeftEdge += 130;
  570.     ng.ng_GadgetText = "Back";
  571.     ng.ng_GadgetID++;
  572.     ng.ng_UserData = ( APTR )( SDEPTH_TOBACK );
  573.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  574.         TAG_DONE );
  575.  
  576.     ng.ng_LeftEdge += 130;
  577.     ng.ng_GadgetText = "Child Forward";
  578.     ng.ng_GadgetID++;
  579.     ng.ng_UserData = ( APTR )( SDEPTH_TOFRONT|SDEPTH_CHILDONLY );
  580.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  581.         TAG_DONE );
  582.  
  583.     ng.ng_LeftEdge += 130;
  584.     ng.ng_GadgetText = "Child Back";
  585.     ng.ng_GadgetID++;
  586.     ng.ng_UserData = ( APTR )( SDEPTH_TOBACK|SDEPTH_CHILDONLY );
  587.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  588.         TAG_DONE );
  589.  
  590.     ng.ng_LeftEdge = 90;
  591.     ng.ng_TopEdge += 18;
  592.     ng.ng_GadgetText = "Move Parent";
  593.     ng.ng_GadgetID++;
  594.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  595.         TAG_DONE );
  596.  
  597.     ng.ng_LeftEdge += 130;
  598.     ng.ng_GadgetText = "Move Child";
  599.     ng.ng_GadgetID++;
  600.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  601.         TAG_DONE );
  602.  
  603.     ng.ng_LeftEdge += 130;
  604.     ng.ng_GadgetText = "FMove Parent";
  605.     ng.ng_GadgetID++;
  606.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  607.         TAG_DONE );
  608.  
  609.     ng.ng_LeftEdge += 130;
  610.     ng.ng_GadgetText = "FMove Child";
  611.     ng.ng_GadgetID++;
  612.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  613.         TAG_DONE );
  614.  
  615.     ng.ng_LeftEdge = 90;
  616.     ng.ng_TopEdge += 18;
  617.     ng.ng_UserData = 0;
  618.     ng.ng_GadgetText = "Home Parent";
  619.     ng.ng_GadgetID++;
  620.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  621.         TAG_DONE );
  622.  
  623.     ng.ng_LeftEdge += 130;
  624.     ng.ng_GadgetText = "Home Child";
  625.     ng.ng_GadgetID++;
  626.     gad = CreateGadget( BUTTON_KIND, gad, &ng,
  627.         TAG_DONE );
  628.  
  629.     if ( gad )    
  630.     {
  631.         if ( panel_win = OpenWindowTags( NULL,
  632.         WA_Width, 640,
  633.         WA_Height, 105,
  634.         WA_Top, 11,
  635.         WA_Activate, TRUE,
  636.         WA_CloseGadget, TRUE,
  637.         WA_DragBar, TRUE,
  638.         WA_SizeGadget, TRUE,
  639.         WA_DepthGadget, TRUE,
  640.         WA_SimpleRefresh, TRUE,
  641.         WA_Title, "Control Panel",
  642.         WA_Gadgets, panel_gadgets,
  643.         WA_CustomScreen, panel_screen,
  644.         TAG_DONE ) )
  645.         {
  646.         /* whew! all is OK */
  647.         panel_win->UserPort = sharedport;
  648.         ModifyIDCMP( panel_win, CLOSEWINDOW | VANILLAKEY | CYCLEIDCMP | BUTTONIDCMP | REFRESHWINDOW );
  649.         GT_RefreshWindow( panel_win, NULL );
  650.         return( panel_win );
  651.         }
  652.         FreeGadgets( panel_gadgets );
  653.         panel_gadgets = NULL;
  654.     }
  655.     FreeVisualInfo( panel_vi );
  656.     panel_vi = NULL;
  657.     }
  658.     return( NULL );
  659. }
  660.  
  661. /*----------------------------------------------------------------------*/
  662.  
  663. void closePanel( void )
  664. {
  665.     if ( panel_win )
  666.     {
  667.     CloseWindowSafely( panel_win ); panel_win = NULL;
  668.     FreeGadgets( panel_gadgets ); panel_gadgets = NULL;
  669.     FreeVisualInfo( panel_vi ); panel_vi = NULL;
  670.     panel_screen = NULL;
  671.     }
  672. }
  673.  
  674. /*----------------------------------------------------------------------*/
  675.  
  676. struct Screen *findPanelScreen( void )
  677. {
  678.     struct Screen *sc;
  679.  
  680.     ULONG lock = LockIBase( NULL );
  681.     for ( sc = IntuitionBase->FirstScreen; sc; sc = sc->NextScreen )
  682.     {
  683.     if ( ( sc->UserData == CHILD_MAGIC ) || ( sc->UserData == PARENT_MAGIC ) )
  684.     {
  685.         break;
  686.     }
  687.     }
  688.     UnlockIBase( lock );
  689.     return( sc );
  690. }
  691.  
  692. /*----------------------------------------------------------------------*/
  693.  
  694. void handleGadget( struct Gadget *gad, UWORD code )
  695. {
  696.     BOOL undo = FALSE;    /* Set to true if gadget states need to be corrected */
  697.     BOOL rethinkp = FALSE;
  698.     BOOL rethinkc = FALSE;
  699.  
  700.     switch ( gad->GadgetID )
  701.     {
  702.     case GAD_PARENT_OPEN:
  703.         if ( !code )    /* request to close */
  704.         {
  705.         /* Only close parent if child still around */
  706.         if ( ( parent_sc ) && ( child_sc ) )
  707.         {
  708.             parent_desc.sd_Open = FALSE;
  709.             rethinkp = TRUE;
  710.         }
  711.         else
  712.         {
  713.             undo = TRUE;
  714.         }
  715.         }
  716.         else        /* request to open */
  717.         {
  718.         if ( !parent_sc )
  719.         {
  720.             parent_desc.sd_Open = TRUE;
  721.             rethinkp = TRUE;
  722.         }
  723.         }
  724.         break;
  725.  
  726.     case GAD_PARENT_LACE:
  727.         parent_desc.sd_Lace = code;
  728.         rethinkp = TRUE;
  729.         break;
  730.  
  731.     case GAD_PARENT_SIZE:
  732.         parent_desc.sd_Size = code;
  733.         rethinkp = TRUE;
  734.         break;
  735.  
  736.     case GAD_PARENT_DRAG:
  737.         parent_desc.sd_Drag = code;
  738.         rethinkp = TRUE;
  739.         break;
  740.  
  741.     case GAD_CHILD_OPEN:
  742.         if ( !code )    /* request to close */
  743.         {
  744.         /* Only close child if parent still around */
  745.         if ( ( child_sc ) && ( parent_sc ) )
  746.         {
  747.             child_desc.sd_Open = FALSE;
  748.             rethinkc = TRUE;
  749.         }
  750.         else
  751.         {
  752.             undo = TRUE;
  753.         }
  754.         }
  755.         else        /* request to open */
  756.         {
  757.         if ( !child_sc )
  758.         {
  759.             child_desc.sd_Open = TRUE;
  760.             rethinkc = TRUE;
  761.         }
  762.         }
  763.         break;
  764.  
  765.     case GAD_CHILD_LACE:
  766.         child_desc.sd_Lace = code;
  767.         rethinkc = TRUE;
  768.         break;
  769.  
  770.     case GAD_CHILD_SIZE:
  771.         child_desc.sd_Size = code;
  772.         rethinkc = TRUE;
  773.         break;
  774.  
  775.     case GAD_CHILD_DRAG:
  776.         child_desc.sd_Drag = code;
  777.         rethinkc = TRUE;
  778.         break;
  779.  
  780.     case GAD_FORWARD:
  781.     case GAD_BACK:
  782.     case GAD_CFORWARD:
  783.     case GAD_CBACK:
  784.         if ( child_sc )
  785.         {
  786.         /* The appropriate screen-depth code is in gad->UserData */
  787.         ScreenDepth( child_sc, ( ULONG )gad->UserData, NULL );
  788.         }
  789.         break;
  790.  
  791.     case GAD_MOVECHILD:
  792.     case GAD_FMOVECHILD:
  793.         if ( child_sc )
  794.         {
  795.         jiggleScreen( child_sc, ( gad->GadgetID == GAD_FMOVECHILD ) ?
  796.             SPOS_FORCEDRAG : 0 );
  797.         }
  798.         break;
  799.  
  800.     case GAD_MOVEPARENT:
  801.     case GAD_FMOVEPARENT:
  802.         if ( parent_sc )
  803.         {
  804.         jiggleScreen( parent_sc, ( gad->GadgetID == GAD_FMOVEPARENT ) ?
  805.             SPOS_FORCEDRAG : 0 );
  806.         }
  807.         break;
  808.  
  809.     case GAD_HOMEPARENT:
  810.         if ( parent_sc )
  811.         {
  812.         ScreenPosition( parent_sc, SPOS_ABSOLUTE, 0, 0, 0, 0 );
  813.         }
  814.         break;
  815.  
  816.     case GAD_HOMECHILD:
  817.         if ( child_sc )
  818.         {
  819.         ScreenPosition( child_sc, SPOS_ABSOLUTE, 0, 0, 0, 0 );
  820.         }
  821.         break;
  822.     }
  823.     if ( rethinkp )
  824.     {
  825.     if ( parent_sc )
  826.     {
  827.         parent_desc.sd_Top = parent_sc->TopEdge;
  828.         if ( parent_desc.sd_IsLace )
  829.         {
  830.         parent_desc.sd_Top /= 2;
  831.         }
  832.         parent_sc = closeMyScreen( parent_sc );
  833.     }
  834.     if ( parent_desc.sd_Open )
  835.     {
  836.         parent_sc = openMyScreen( TRUE );
  837.         parent_desc.sd_IsLace = parent_desc.sd_Lace;
  838.     }
  839.     }
  840.  
  841.     if ( rethinkc )
  842.     {
  843.     if ( child_sc )
  844.     {
  845.         child_desc.sd_Top = child_sc->TopEdge;
  846.         if ( child_desc.sd_IsLace )
  847.         {
  848.         child_desc.sd_Top /= 2;
  849.         }
  850.         child_sc = closeMyScreen( child_sc );
  851.     }
  852.     if ( child_desc.sd_Open )
  853.     {
  854.         child_sc = openMyScreen( FALSE );
  855.         child_desc.sd_IsLace = child_desc.sd_Lace;
  856.     }
  857.     }
  858.  
  859.     if ( undo && panel_win )
  860.     {
  861.     int i;
  862.     for ( i = 0; i < NUM_SETTABLE; i++ )
  863.     {
  864.         LONG *longptr;
  865.         if ( longptr = mygad[ i ]->UserData )
  866.         {
  867.         GT_SetGadgetAttrs( mygad[ i ], panel_win, NULL,
  868.             GTCY_Active, *longptr,
  869.             TAG_DONE );
  870.         }
  871.     }
  872.     }
  873.  
  874.     if ( ( !panel_win ) || ( panel_win->WScreen != findPanelScreen() ) )
  875.     {
  876.     closePanel();
  877.     openPanel();
  878.     }
  879. }
  880.  
  881. /*----------------------------------------------------------------------*/
  882.  
  883. void jiggleScreen( struct Screen *sc, ULONG flags )
  884. {
  885.     LONG i, step;
  886.  
  887.     step = 2;
  888.     for ( i = 0; i < 40; i++ )
  889.     {
  890.     ScreenPosition( sc, flags, 0, step, 0, 0 );
  891.     if ( i == 9 )
  892.     {
  893.         step = -2;
  894.     }
  895.     else if ( i == 29 )
  896.     {
  897.         step = 2;
  898.     }
  899.     }
  900.     step = -2;
  901.     for ( i = 0; i < 40; i++ )
  902.     {
  903.     ScreenPosition( sc, flags, step, 0, 0, 0 );
  904.     if ( i == 19 )
  905.     {
  906.         step = 2;
  907.     }
  908.     }
  909. }
  910.  
  911. /*----------------------------------------------------------------------*/
  912.