home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Programming / C / OTL-MC7.DMS / in.adf / ansicdemo.lha / ANSI-C / Intuition / attachdemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-30  |  19.1 KB  |  933 lines

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