home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / utility / misc / toolmana.lha / ToolManager / Source / library / dockobj.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-26  |  42.5 KB  |  1,321 lines

  1. /*
  2.  * dockobj.c  V2.0
  3.  *
  4.  * TMObject, Type: Dock
  5.  *
  6.  * (c) 1990-1992 Stefan Becker
  7.  */
  8.  
  9. #include "ToolManagerLib.h"
  10.  
  11. /* node for one tool */
  12. struct DockTool {
  13.                  struct DockTool    *dt_Next;
  14.                  char               *dt_ExecName;
  15.                  struct TMLink      *dt_ExecLink;
  16.                  struct TMLinkImage *dt_ImageLink;
  17.                  struct TMLink      *dt_SoundLink;
  18.                 };
  19.  
  20. /* extended TMObject structure for TMOBJTYPE_Dock objects */
  21. struct TMObjectDock {
  22.                      struct TMObject  do_Object;
  23.                      ULONG            do_Flags;
  24.                      ULONG            do_Columns;
  25.                      struct TextAttr *do_Font;   /* User supplied font */
  26.                      char            *do_HotKey;
  27.                      ULONG            do_LeftEdge;
  28.                      char            *do_PubScreen;
  29.                      char            *do_Title;
  30.                      struct DockTool *do_Tools;
  31.                      ULONG            do_TopEdge;
  32.                      CxObj           *do_CxObj;
  33.                      struct TMLink    do_Link;
  34.                      UWORD            do_Left;   /* Drawing start position */
  35.                      UWORD            do_Top;
  36.                      UWORD            do_Width;  /* Inner Window Width/Height */
  37.                      UWORD            do_Height;
  38.                      UWORD            do_XSize;  /* Image/Gadget box size */
  39.                      UWORD            do_YSize;
  40.                      struct Window   *do_Window;
  41.                      void            *do_AppWindow;
  42.                      struct Gadget    do_DragGadget;
  43.                      UWORD            do_FillPen;
  44.                      UWORD            do_BackPen;
  45.                      struct TextAttr  do_TextAttr;   /* Font for gadgets */
  46.                      struct TextFont *do_TextFont;   /* Screen font (open) */
  47.                      struct TextFont *do_GadgetFont; /* Gadget font (open) */
  48.                      void            *do_VisualInfo;
  49.                      struct Menu     *do_Menu;
  50.                      struct Gadget   *do_GadToolsGadgets;
  51.                      struct DockTool *do_Selected;
  52.                      UWORD            do_SelectX;
  53.                      UWORD            do_SelectY;
  54.                      ULONG            do_Seconds;
  55.                      ULONG            do_Micros;
  56.                     };
  57.  
  58. /* do_Flags */
  59. #define DO_Activated (1L<<0)
  60. #define DO_Centered  (1L<<1)
  61. #define DO_FrontMost (1L<<2)
  62. #define DO_Menu      (1L<<3)
  63. #define DO_Pattern   (1L<<4)
  64. #define DO_PopUp     (1L<<5)
  65. #define DO_Text      (1L<<6)
  66. #define DO_Vertical  (1L<<7)
  67.  
  68. /* Tag to Flag mapping table for PackBoolTags */
  69. static struct TagItem flagmap[]={
  70.                                  TMOP_Activated, DO_Activated,
  71.                                  TMOP_Centered,  DO_Centered,
  72.                                  TMOP_FrontMost, DO_FrontMost,
  73.                                  TMOP_Menu,      DO_Menu,
  74.                                  TMOP_Pattern,   DO_Pattern,
  75.                                  TMOP_PopUp,     DO_PopUp,
  76.                                  TMOP_Text,      DO_Text,
  77.                                  TMOP_Vertical,  DO_Vertical,
  78.                                  TAG_DONE};
  79.  
  80. /* Library bases */
  81. struct Library *DiskfontBase;
  82.  
  83. /* Close a window safely */
  84. static void SafeCloseWindow(struct Window *w)
  85. {
  86.  struct IntuiMessage *msg;
  87.  
  88.  DEBUG_PRINTF("SafeCloseWindow: 0x%08lx\n",w);
  89.  
  90.  /* we forbid here to keep out of race conditions with Intuition */
  91.  Forbid();
  92.  
  93.  /* Remove all messsages for this window */
  94.  msg=GetHead(&w->UserPort->mp_MsgList);
  95.  while (msg)
  96.   /* Does this message point to the window? */
  97.   if (msg->IDCMPWindow==w) {
  98.    struct IntuiMessage *nextmsg=GetSucc(msg);
  99.  
  100.    /* Yes. Remove it from port */
  101.    Remove((struct Node *) msg);
  102.  
  103.    /* Reply it */
  104.    ReplyMsg((struct Message *) msg);
  105.  
  106.    /* Get pointer to next message */
  107.    msg=nextmsg;
  108.   }
  109.    /* No. Get pointer to next message */
  110.   else msg=GetSucc(msg);
  111.  
  112.  /* clear UserPort so Intuition will not free it */
  113.  w->UserPort=NULL;
  114.  
  115.  /* tell Intuition to stop sending more messages */
  116.  ModifyIDCMP(w,0);
  117.  
  118.  /* turn multitasking back on */
  119.  Permit();
  120.  
  121.  DEBUG_PRINTF("Closing window\n");
  122.  
  123.  /* and really close the window */
  124.  CloseWindow(w);
  125.  
  126.  DEBUG_PRINTF("Window closed\n");
  127. }
  128.  
  129. /* Pattern */
  130. static UWORD BackgroundPattern[]={0xaaaa,0x5555};
  131.  
  132. /* Open Dock Window */
  133. static void OpenDockWindow(struct TMObjectDock *tmobj)
  134. {
  135.  struct Screen *pubsc;
  136.  
  137.  /* Open on frontmost public screen? */
  138.  if (tmobj->do_Flags & DO_FrontMost) {
  139.   ULONG lock;
  140.  
  141.   /* Avoid race conditions */
  142.   Forbid();
  143.  
  144.   /* Lock IntuitionBase */
  145.   lock=LockIBase(0);
  146.  
  147.   /* Scan List */
  148.   pubsc=IntuitionBase->FirstScreen;
  149.   while (pubsc) {
  150.    ULONG type=pubsc->Flags & SCREENTYPE;
  151.  
  152.    DEBUG_PRINTF("Screen flags: 0x%08lx",pubsc->Flags);
  153.    DEBUG_PRINTF(" Screen type: 0x%08lx\n",type);
  154.  
  155.    /* Found a public screen? */
  156.    if ((type==WBENCHSCREEN) || (type==PUBLICSCREEN)) break;
  157.  
  158.    /* Get pointer to next screen */
  159.    pubsc=pubsc->NextScreen;
  160.   }
  161.  
  162.   /* Unlock IntuitionBase */
  163.   UnlockIBase(lock);
  164.  
  165.   /* Lock public screen */
  166.   if (pubsc) {
  167.    struct List *pubsclist;
  168.  
  169.    /* Get a pointer to the public screen list */
  170.    if (pubsclist=LockPubScreenList()) {
  171.     struct PubScreenNode *pubscnode=GetHead(pubsclist);
  172.     UBYTE namebuf[MAXPUBSCREENNAME+1];
  173.  
  174.     /* Scan list */
  175.     while (pubscnode) {
  176.      /* Does this node point to our screen? */
  177.      if (pubscnode->psn_Screen==pubsc) {
  178.       /* Yes. Copy screen name */
  179.       strcpy(namebuf,pubscnode->psn_Node.ln_Name);
  180.       break;
  181.      }
  182.  
  183.      /* get a pointer to next node */
  184.      pubscnode=GetSucc(pubscnode);
  185.     }
  186.  
  187.     /* Release public screen list */
  188.     UnlockPubScreenList();
  189.  
  190.     /* Lock screen */
  191.     if (pubscnode)
  192.      pubsc=LockPubScreen(namebuf);
  193.     else
  194.      pubsc=NULL;
  195.    }
  196.    else pubsc=NULL; /* No public screens??? */
  197.   }
  198.  
  199.   /* OK, we have a screen now */
  200.   Permit();
  201.  } else
  202.   /* Lock public screen */
  203.   pubsc=LockPubScreen(tmobj->do_PubScreen);
  204.  
  205.  DEBUG_PRINTF("PubScreen: 0x%08lx\n",pubsc);
  206.  
  207.  /* Got a locked public screen? */
  208.  if (pubsc) {
  209.   struct DrawInfo *dri;
  210.  
  211.   /* Get screen draw info */
  212.   if (dri=GetScreenDrawInfo(pubsc)) {
  213.    void *vi;
  214.  
  215.    /* Get screen visual info */
  216.    if (vi=GetVisualInfo(pubsc,TAG_DONE)) {
  217.     struct TextFont *tf;
  218.  
  219.     /* Open screen font */
  220.     if (tf=OpenFont(pubsc->Font)) {
  221.      struct Window *w;
  222.      struct DockTool *dt=tmobj->do_Tools;
  223.      struct TextFont *gadfont=NULL;
  224.      UWORD wx=0,wy=0;
  225.      BOOL borderless=tmobj->do_Title==NULL;
  226.      BOOL text=(tmobj->do_Flags & DO_Text)!=0;
  227.  
  228.      /* Got ANY tools??? */
  229.      if (dt) {
  230.       /* Calculate box sizes */
  231.       ULONG maxx=0,maxy=0,count=0;
  232.       ULONG fheight;
  233.       struct RastPort tmprp;
  234.  
  235.       /* Init RastPort for text writing */
  236.       InitRastPort(&tmprp);
  237.  
  238.       /* Set default font */
  239.       SetFont(&tmprp,tf);
  240.       fheight=tf->tf_YSize+INTERHEIGHT+1;
  241.  
  242.       /* User specified font? */
  243.       if (tmobj->do_Font &&
  244.           (DiskfontBase=OpenLibrary("diskfont.library",36))) {
  245.        /* OK, load font now */
  246.        if (gadfont=OpenDiskFont(tmobj->do_Font)) {
  247.         /* Set font */
  248.         SetFont(&tmprp,gadfont);
  249.         fheight=gadfont->tf_YSize+INTERHEIGHT+1;
  250.        }
  251.  
  252.        /* Close library again */
  253.        CloseLibrary(DiskfontBase);
  254.       }
  255.  
  256.       DEBUG_PRINTF("TextAttr: 0x%08lx",tmobj->do_Font);
  257.       DEBUG_PRINTF(" Font: 0x%08lx\n",gadfont);
  258.  
  259.       /* Scan tool list */
  260.       while (dt) {
  261.        ULONG valx=0,valy=0;
  262.  
  263.        if (text) {
  264.         /* Gadgets */
  265.         char *s=dt->dt_ExecName;
  266.  
  267.         /* Link and name valid? */
  268.         if (dt->dt_ExecLink && s) {
  269.          valx=TextLength(&tmprp,s,strlen(s))+2*INTERWIDTH+2;
  270.          valy=fheight;
  271.         }
  272.        } else {
  273.         /* Images */
  274.         struct TMLinkImage *tmli=dt->dt_ImageLink;
  275.  
  276.         /* Link to image valid? */
  277.         if (tmli) {
  278.          /* max(width) */
  279.          valx=tmli->tmli_Width;
  280.          valy=tmli->tmli_Height-1;
  281.         }
  282.        }
  283.  
  284.        /* Check maxima */
  285.        if (valx>maxx) maxx=valx;
  286.        if (valy>maxy) maxy=valy;
  287.  
  288.        /* Increment counter & Get pointer to next tool */
  289.        count++;
  290.        dt=dt->dt_Next;
  291.       }
  292.  
  293.       /* Calculate window sizes */
  294.       tmobj->do_Width=tmobj->do_Columns*maxx;
  295.       tmobj->do_Height=((count+tmobj->do_Columns-1)/tmobj->do_Columns)*maxy;
  296.       tmobj->do_XSize=maxx;
  297.       tmobj->do_YSize=maxy;
  298.      }
  299.  
  300.      /* Got valid window sizes? */
  301.      if (((LONG) tmobj->do_XSize>1) && ((LONG) tmobj->do_YSize>1)) {
  302.       BOOL menu=(tmobj->do_Flags & DO_Menu)!=0;
  303.  
  304.       /* Correct window sizes */
  305.       if (borderless) {
  306.        /* Borderless window */
  307.        struct Gadget *g=&tmobj->do_DragGadget;
  308.  
  309.        /* Gadget window */
  310.        if (text) {
  311.         tmobj->do_Width--;
  312.         tmobj->do_Height--;
  313.        }
  314.  
  315.        /* Calculate drag gadget dimensions */
  316.        if (tmobj->do_Flags & DO_Vertical) {
  317.         /* Vertical drag gadget */
  318.         struct RastPort tmprp;
  319.         UWORD gwidth;
  320.  
  321.         /* Init RastPort for text writing */
  322.         InitRastPort(&tmprp);
  323.         SetFont(&tmprp,tf);
  324.         gwidth=TextLength(&tmprp,"A",1);
  325.  
  326.         tmobj->do_Left=gwidth;
  327.         tmobj->do_Top=0;
  328.         tmobj->do_Width+=gwidth;
  329.         g->Width=gwidth;
  330.         g->Height=tmobj->do_Height;
  331.        } else {
  332.         /* Horizontal drag gadget */
  333.         UWORD gheight=(tf->tf_YSize+8)/2;
  334.  
  335.         tmobj->do_Left=0;
  336.         tmobj->do_Top=gheight;
  337.         tmobj->do_Height+=gheight;
  338.         g->Width=tmobj->do_Width;
  339.         g->Height=gheight;
  340.        }
  341.  
  342.        /* Init drag gadget structure */
  343.        g->Flags=GFLG_GADGHNONE;
  344.        g->Activation=GACT_IMMEDIATE;
  345.        g->GadgetType=GTYP_SYSGADGET|GTYP_WDRAGGING;
  346.  
  347.        /* Get pens */
  348.        tmobj->do_FillPen=dri->dri_Pens[FILLPEN];
  349.        tmobj->do_BackPen=dri->dri_Pens[BACKGROUNDPEN];
  350.       } else {
  351.        /* Normal window */
  352.        tmobj->do_Left=pubsc->WBorLeft+1;
  353.        tmobj->do_Top=pubsc->WBorTop+tf->tf_YSize+2;
  354.        if (text) {
  355.         tmobj->do_Width++;
  356.         tmobj->do_Height++;
  357.        } else {
  358.         tmobj->do_Width+=2;
  359.         tmobj->do_Height+=2;
  360.        }
  361.       }
  362.  
  363.       /* Centered window? */
  364.       if (tmobj->do_Flags & DO_Centered) {
  365.        /* Centered */
  366.        /* Borderless window: X = MouseX - (width-left)/2 - left */
  367.        /* Normal window    : X = MouseX -        width/2 - left */
  368.        wx=tmobj->do_Width;
  369.        wy=tmobj->do_Height;
  370.  
  371.        /* Borderless window? */
  372.        if (borderless) {
  373.         wx-=tmobj->do_Left;
  374.         wy-=tmobj->do_Top;
  375.        }
  376.  
  377.        wx=pubsc->MouseX-wx/2-tmobj->do_Left;
  378.        wy=pubsc->MouseY-wy/2-tmobj->do_Top;
  379.       } else {
  380.        /* Not centered */
  381.        wx=tmobj->do_LeftEdge;
  382.        wy=tmobj->do_TopEdge;
  383.       }
  384.  
  385.       /* Dock with menu? */
  386.       if (menu &&
  387.           (tmobj->do_Menu=CreateMenus(DockMenu,GTMN_FullMenu,TRUE,TAG_DONE)) &&
  388.           !LayoutMenus(tmobj->do_Menu,vi,TAG_DONE))
  389.        tmobj->do_Menu=NULL;
  390.  
  391.       DEBUG_PRINTF("Boxes: X %ld",tmobj->do_XSize);
  392.       DEBUG_PRINTF(" Y %ld",tmobj->do_YSize);
  393.       DEBUG_PRINTF(" Window: Width %ld",tmobj->do_Width);
  394.       DEBUG_PRINTF(" Height %ld\n",tmobj->do_Height);
  395.       DEBUG_PRINTF("menu %ld",menu);
  396.       DEBUG_PRINTF(" Menu 0x%08lx\n",tmobj->do_Menu);
  397.  
  398.       /* Open window */
  399.       if ((!menu || tmobj->do_Menu) &&
  400.           (w=OpenWindowTags(NULL,WA_Left,        wx,
  401.                                  WA_Top,         wy,
  402.                                  WA_InnerWidth,  tmobj->do_Width,
  403.                                  WA_InnerHeight, tmobj->do_Height,
  404.                                  WA_Title,       tmobj->do_Title,
  405.                                  WA_DragBar,     !borderless,
  406.                                  WA_CloseGadget, !borderless,
  407.                                  WA_DepthGadget, !borderless,
  408.                                  WA_Borderless,  borderless,
  409.                                  WA_PubScreen,   pubsc,
  410.                                  WA_RMBTrap,     !menu,
  411.                                  WA_AutoAdjust,  TRUE,
  412.                                  WA_IDCMP,       0,
  413.                                  TAG_DONE))) {
  414.        /* Set window pointers */
  415.        w->UserPort=IDCMPPort;
  416.        w->UserData=tmobj;
  417.  
  418.        DEBUG_PRINTF("Window: 0x%08lx\n",w);
  419.  
  420.        /* Set IDCMP flags */
  421.        if (ModifyIDCMP(w,IDCMP_ACTIVEWINDOW|IDCMP_INACTIVEWINDOW|IDCMP_GADGETUP|
  422.                          IDCMP_MOUSEBUTTONS|IDCMP_CLOSEWINDOW|IDCMP_MENUPICK|
  423.                          IDCMP_REFRESHWINDOW)) {
  424.         BOOL wbscreen=(pubsc->Flags & SCREENTYPE)==WBENCHSCREEN;
  425.         BOOL wbopen=FALSE;
  426.  
  427.         /* Try to add the window as application window */
  428.         tmobj->do_AppWindow=NULL;
  429.         if (wbscreen && (wbopen=GetWorkbench()))
  430.          tmobj->do_AppWindow=AddAppWindowA((ULONG) &tmobj->do_Link,NULL,w,
  431.                                            AppMsgPort,NULL);
  432.  
  433.         /* Not on Workbench screen, no Workbench or AddAppWindow successful? */
  434.         if (!wbscreen || !wbopen || tmobj->do_AppWindow) {
  435.          struct Gadget *g;
  436.  
  437.          /* Draw drag gadget */
  438.          if (borderless) {
  439.           struct RastPort *rp=w->RPort;
  440.           UWORD width=tmobj->do_DragGadget.Width-1;
  441.           UWORD height=tmobj->do_DragGadget.Height-1;
  442.  
  443.           /* Draw lighted side */
  444.           SetAPen(rp,dri->dri_Pens[SHINEPEN]);
  445.           Move(rp,0,height);
  446.           Draw(rp,0,0);
  447.           Draw(rp,width,0);
  448.  
  449.           /* Draw shadowed side */
  450.           SetAPen(rp,dri->dri_Pens[SHADOWPEN]);
  451.           Move(rp,width,1);
  452.           Draw(rp,width,height);
  453.           Draw(rp,0,height);
  454.  
  455.           AddGadget(w,&tmobj->do_DragGadget,(UWORD) -1);
  456.           RefreshGList(&tmobj->do_DragGadget,w,NULL,1);
  457.          }
  458.  
  459.          /* Draw initial window state */
  460.          {
  461.           struct RastPort *rp=w->RPort;
  462.           ULONG col=0,lin=0;
  463.           UWORD x=tmobj->do_Left;
  464.           UWORD y=tmobj->do_Top;
  465.           UWORD dw=tmobj->do_XSize;
  466.           UWORD dh=tmobj->do_YSize;
  467.           BOOL pattern=((tmobj->do_Flags & DO_Pattern)!=0 && !text);
  468.           struct NewGadget ng;
  469.  
  470.           /* Set pattern */
  471.           if (pattern) {
  472.            SetAPen(rp,dri->dri_Pens[SHADOWPEN]);
  473.            SetDrMd(rp,JAM2);
  474.            SetAfPt(rp,BackgroundPattern,1);
  475.           }
  476.  
  477.           /* Set pointer to begin of tool list */
  478.           dt=tmobj->do_Tools;
  479.  
  480.           /* Init TextAttr & NewGadget struct, create GadTools context */
  481.           if (text) {
  482.            /* Font set? */
  483.            if (tmobj->do_Font)
  484.             tmobj->do_TextAttr=*(tmobj->do_Font);
  485.            else {
  486.             /* No. Set screen font */
  487.             tmobj->do_TextAttr.ta_Name=tf->tf_Message.mn_Node.ln_Name;
  488.             tmobj->do_TextAttr.ta_YSize=tf->tf_YSize;
  489.             tmobj->do_TextAttr.ta_Style=tf->tf_Style;
  490.             tmobj->do_TextAttr.ta_Flags=tf->tf_Flags;
  491.            }
  492.  
  493.            DEBUG_PRINTF("Font '%s'",tmobj->do_TextAttr.ta_Name);
  494.            DEBUG_PRINTF(" Size %ld\n",tmobj->do_TextAttr.ta_YSize);
  495.  
  496.            ng.ng_Width=dw-1;
  497.            ng.ng_Height=dh-1;
  498.            ng.ng_TextAttr=&tmobj->do_TextAttr;
  499.            ng.ng_Flags=PLACETEXT_IN;
  500.            ng.ng_VisualInfo=vi;
  501.            ng.ng_UserData=0;
  502.            tmobj->do_GadToolsGadgets=NULL;
  503.            if (!(g=CreateContext(&tmobj->do_GadToolsGadgets)))
  504.             dt=NULL; /* Error!!! */
  505.           }
  506.  
  507.           /* Scan tool list */
  508.           while (dt) {
  509.            if (text) {
  510.             /* Gadgets. Link valid? */
  511.             if (dt->dt_ExecLink) {
  512.              /* Init NewGadget values */
  513.              ng.ng_LeftEdge=x;
  514.              ng.ng_TopEdge=y;
  515.              ng.ng_GadgetText=dt->dt_ExecName;
  516.              ng.ng_UserData=dt;
  517.  
  518.              /* Create button gadget */
  519.              if (!(g=CreateGadget(BUTTON_KIND,g,&ng,TAG_DONE)))
  520.               dt=NULL; /* Error!!!! */
  521.             }
  522.            } else {
  523.             /* Images */
  524.             struct TMLinkImage *tmli=dt->dt_ImageLink;
  525.  
  526.             /* Draw pattern? */
  527.             if (pattern) {
  528.              /* Set Pattern color */
  529.              SetBPen(rp,(col+lin)&1 ? dri->dri_Pens[BACKGROUNDPEN] :
  530.                                       dri->dri_Pens[FILLPEN]);
  531.  
  532.              /* Draw pattern */
  533.              RectFill(rp,x,y,x+dw-1,y+dh-1);
  534.             }
  535.  
  536.             /* Link valid? */
  537.             if (tmli) {
  538.              /* Yes. Set Parameters */
  539.              tmli->tmli_LeftEdge=x+(dw - tmli->tmli_Width)/2;
  540.              tmli->tmli_TopEdge=y+(dh + 1 - tmli->tmli_Height)/2;
  541.              tmli->tmli_RastPort=w->RPort;
  542.  
  543.              /* Draw deactivated state */
  544.              CallActivateTMObject((struct TMLink *) tmli,(void *) IOC_DEACTIVE);
  545.             }
  546.            }
  547.  
  548.            /* Next column */
  549.            col++;
  550.  
  551.            /* Increment x,y. Last Column? */
  552.            if (col==tmobj->do_Columns) {
  553.             /* Yes */
  554.             y+=dh;
  555.             x=tmobj->do_Left;
  556.             col=0;
  557.             lin++;
  558.            } else
  559.             /* No */
  560.             x+=dw;
  561.  
  562.            /* Get pointer to next node */
  563.            if (dt) dt=dt->dt_Next;
  564.           }
  565.  
  566.           /* Reset Areafill pattern */
  567.           if (pattern) SetAfPt(rp,NULL,0);
  568.          }
  569.  
  570.          /* All OK. */
  571.          if (!text || g) {
  572.           /* Add GadTools gadgets */
  573.           if (text) {
  574.            AddGList(w,tmobj->do_GadToolsGadgets,(UWORD) -1,(UWORD) -1,NULL);
  575.            RefreshGList(tmobj->do_GadToolsGadgets,w,NULL,(UWORD) -1);
  576.            GT_RefreshWindow(w,NULL);
  577.           }
  578.  
  579.           /* Add menu */
  580.           if (menu) SetMenuStrip(w,tmobj->do_Menu);
  581.  
  582.           /* Free resources */
  583.           FreeScreenDrawInfo(pubsc,dri);
  584.           UnlockPubScreen(NULL,pubsc);
  585.  
  586.           /* Save pointers */
  587.           tmobj->do_VisualInfo=vi;
  588.           tmobj->do_TextFont=tf;
  589.           tmobj->do_GadgetFont=gadfont;
  590.           tmobj->do_Window=w;
  591.           return;
  592.           /* NOT REACHED */
  593.          }
  594.  
  595.          /* Remove drag Gadget */
  596.          if (borderless) RemoveGadget(w,&tmobj->do_DragGadget);
  597.  
  598.          /* Free GadTools gadgets */
  599.          if (text) {
  600.           FreeGadgets(tmobj->do_GadToolsGadgets);
  601.           tmobj->do_GadToolsGadgets=NULL;
  602.          }
  603.  
  604.          /* Remove AppWindow */
  605.          if (tmobj->do_AppWindow)
  606.           SafeRemoveAppWindow(tmobj->do_AppWindow,&tmobj->do_Link);
  607.         }
  608.         if (wbopen) FreeWorkbench();
  609.        }
  610.        SafeCloseWindow(w);
  611.       }
  612.       if (tmobj->do_Menu) {
  613.        FreeMenus(tmobj->do_Menu);
  614.        tmobj->do_Menu=NULL;
  615.       }
  616.      }
  617.      if (gadfont) CloseFont(gadfont);
  618.      CloseFont(tf);
  619.     }
  620.     FreeVisualInfo(vi);
  621.    }
  622.    FreeScreenDrawInfo(pubsc,dri);
  623.   }
  624.   UnlockPubScreen(NULL,pubsc);
  625.  }
  626.  /* Dock couldn't be opened! */
  627.  DisplayBeep(NULL);
  628. }
  629.  
  630. /* Close Dock window */
  631. static void CloseDockWindow(struct TMObjectDock *tmobj)
  632. {
  633.  struct DockTool *dt=tmobj->do_Tools;
  634.  struct Window *w=tmobj->do_Window;
  635.  
  636.  DEBUG_PRINTF("CloseDockWindow: 0x%08lx\n",tmobj);
  637.  
  638.  /* Deactivate all Image objects */
  639.  while (dt) {
  640.   /* Image object active? */
  641.   if (dt->dt_ImageLink && dt->dt_ImageLink->tmli_Link.tml_Active)
  642.    /* Yes. Deactivate it first */
  643.    CallActivateTMObject((struct TMLink *) dt->dt_ImageLink,
  644.                         (void *) IOC_DEACTIVE);
  645.  
  646.   /* Get pointer to next node */
  647.   dt=dt->dt_Next;
  648.  }
  649.  
  650.  /* Remove menu */
  651.  if (tmobj->do_Menu) {
  652.   ClearMenuStrip(w);
  653.   tmobj->do_Menu=NULL;
  654.  }
  655.  
  656.  /* Remove drag gadget */
  657.  if (!tmobj->do_Title) RemoveGadget(w,&tmobj->do_DragGadget);
  658.  
  659.  /* Remove gadtools gadgets */
  660.  if (tmobj->do_GadToolsGadgets) {
  661.   RemoveGList(w,tmobj->do_GadToolsGadgets,(UWORD) -1);
  662.   FreeGadgets(tmobj->do_GadToolsGadgets);
  663.   tmobj->do_GadToolsGadgets=NULL;
  664.  }
  665.  
  666.  /* Remove AppWindow */
  667.  if (tmobj->do_AppWindow) {
  668.   SafeRemoveAppWindow(tmobj->do_AppWindow,&tmobj->do_Link);
  669.   FreeWorkbench();
  670.  }
  671.  
  672.  /* Remember last window position */
  673.  tmobj->do_LeftEdge=w->LeftEdge;
  674.  tmobj->do_TopEdge=w->TopEdge;
  675.  
  676.  /* Close Window */
  677.  SafeCloseWindow(w);
  678.  tmobj->do_Window=NULL;
  679.  
  680.  /* Free resources */
  681.  if (tmobj->do_GadgetFont) CloseFont(tmobj->do_GadgetFont);
  682.  CloseFont(tmobj->do_TextFont);
  683.  FreeVisualInfo(tmobj->do_VisualInfo);
  684. }
  685.  
  686. /* Free tools list */
  687. static void FreeTools(struct TMObjectDock *tmobj)
  688. {
  689.  struct DockTool *dt,*nextdt=tmobj->do_Tools;
  690.  
  691.  /* Scan list */
  692.  while (dt=nextdt) {
  693.   /* Get pointer to next node */
  694.   nextdt=dt->dt_Next;
  695.  
  696.   /* Remove links */
  697.   if (dt->dt_ExecLink) RemLinkTMObject(dt->dt_ExecLink);
  698.   if (dt->dt_ImageLink) RemLinkTMObject((struct TMLink *) dt->dt_ImageLink);
  699.   if (dt->dt_SoundLink) RemLinkTMObject(dt->dt_SoundLink);
  700.  
  701.   /* Free Node */
  702.   FreeMem(dt,sizeof(struct DockTool));
  703.  }
  704. }
  705.  
  706. /* Create a Dock object */
  707. struct TMObject *CreateTMObjectDock(struct TMHandle *handle, char *name,
  708.                                     struct TagItem *tags)
  709. {
  710.  struct TMObjectDock *tmobj;
  711.  
  712.  /* allocate memory for object */
  713.  if (tmobj=AllocateTMObject(sizeof(struct TMObjectDock))) {
  714.   struct TagItem *ti,*tstate;
  715.   struct DockTool *dt=NULL;
  716.  
  717.   /* Set defaults */
  718.   tmobj->do_Columns=1;
  719.  
  720.   /* Scan tag list */
  721.   tstate=tags;
  722.   while (ti=NextTagItem(&tstate)) {
  723.  
  724.    DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  725.  
  726.    switch (ti->ti_Tag) {
  727.     case TMOP_Columns:   if (ti->ti_Data) tmobj->do_Columns=ti->ti_Data;
  728.                          break;
  729.     case TMOP_Font:      {
  730.                           struct TextAttr *ta=(struct TextAttr *) ti->ti_Data;
  731.  
  732.                           if (ta && ta->ta_Name) tmobj->do_Font=ta;
  733.                          }
  734.                          break;
  735.     case TMOP_HotKey:    tmobj->do_HotKey=(char *) ti->ti_Data;
  736.                          break;
  737.     case TMOP_LeftEdge:  tmobj->do_LeftEdge=ti->ti_Data;
  738.                          break;
  739.     case TMOP_PubScreen: tmobj->do_PubScreen=(char *) ti->ti_Data;
  740.                          break;
  741.     case TMOP_Title:     tmobj->do_Title=(char *) ti->ti_Data;
  742.                          break;
  743.     case TMOP_Tool:      if (ti->ti_Data) {
  744.                           struct DockTool *newdt;
  745.  
  746.                           /* Alloc DockTool structure */
  747.                           if (newdt=AllocMem(sizeof(struct DockTool),
  748.                                              MEMF_CLEAR)) {
  749.                            char **names=(char **) ti->ti_Data;
  750.  
  751.                            /* Add link to Exec object */
  752.                            if (names[0] &&
  753.                                (newdt->dt_ExecLink=AddLinkTMObject(handle,
  754.                                                                   names[0],
  755.                                                                 TMOBJTYPE_EXEC,
  756.                                                             (struct TMObject *)
  757.                                                                   tmobj)))
  758.                             /* Get name of exec object. We use names[0]
  759.                                instead of object name, because the link could
  760.                                be deleted while window is still active. */
  761.                             newdt->dt_ExecName=names[0];
  762.  
  763.                            /* Add link to Image object */
  764.                            if (names[1])
  765.                             newdt->dt_ImageLink=AddLinkTMObject(handle,names[1],
  766.                                                                 TMOBJTYPE_IMAGE,
  767.                                                             (struct TMObject *)
  768.                                                                 tmobj);
  769.  
  770.                            /* Add link to Sound object */
  771.                            if (names[2])
  772.                             newdt->dt_SoundLink=AddLinkTMObject(handle,names[2],
  773.                                                                 TMOBJTYPE_SOUND,
  774.                                                             (struct TMObject *)
  775.                                                                 tmobj);
  776.  
  777.                            /* Add node to list. Head of list? */
  778.                            if (dt) {
  779.                             /* No. Add to tail */
  780.                             dt->dt_Next=newdt;
  781.                             dt=newdt;
  782.                            } else {
  783.                             /* Yes. Init list anchor */
  784.                             tmobj->do_Tools=newdt;
  785.                             dt=newdt;
  786.                            }
  787.                           }
  788.                          }
  789.                          break;
  790.     case TMOP_TopEdge:   tmobj->do_TopEdge=ti->ti_Data;
  791.                          break;
  792.    }
  793.   }
  794.  
  795.   {
  796.    BOOL hotkey=tmobj->do_HotKey!=NULL;
  797.  
  798.    /* No HotKey or cannot create CxObject from HotKey description? */
  799.    if (hotkey && (tmobj->do_CxObj=HotKey(tmobj->do_HotKey,BrokerPort,
  800.                                          (ULONG) &tmobj->do_Link))) {
  801.  
  802.     DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->do_CxObj);
  803.  
  804.     /* Attach object to broker */
  805.     AttachCxObj(Broker,tmobj->do_CxObj);
  806.    }
  807.  
  808.    /* No HotKey or Commodities error? */
  809.    if (!hotkey || (tmobj->do_CxObj && !CxObjError(Broker))) {
  810.     /* Set flags */
  811.     tmobj->do_Flags=PackBoolTags(DO_Activated,tags,flagmap);
  812.  
  813.     /* Initialize rest of structure */
  814.     tmobj->do_Link.tml_Linked=tmobj;
  815.  
  816.     /* Active flag set? */
  817.     if (tmobj->do_Flags & DO_Activated)
  818.      /* Yes. Open dock window */
  819.      OpenDockWindow(tmobj);
  820.  
  821.     /* All OK */
  822.     return(tmobj);
  823.    }
  824.  
  825.    /* Free resources */
  826.    if (tmobj->do_CxObj) SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  827.   }
  828.   FreeTools(tmobj);
  829.  }
  830.  
  831.  /* call failed */
  832.  return(NULL);
  833. }
  834.  
  835. /* Delete a Dock object */
  836. BOOL DeleteTMObjectDock(struct TMObjectDock *tmobj)
  837. {
  838.  DEBUG_PRINTF("Delete/Dock (0x%08lx)\n",tmobj);
  839.  
  840.  /* Free resources */
  841.  if (tmobj->do_CxObj) SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  842.  
  843.  /* Close window and free its resources */
  844.  if (tmobj->do_Window) CloseDockWindow(tmobj);
  845.  
  846.  /* Free tool nodes */
  847.  FreeTools(tmobj);
  848.  
  849.  /* Remove object from list */
  850.  Remove((struct Node *) tmobj);
  851.  
  852.  /* Free object */
  853.  FreeMem(tmobj,sizeof(struct TMObjectDock));
  854.  
  855.  /* All OK. */
  856.  return(TRUE);
  857. }
  858.  
  859. /* Change a Dock object */
  860. struct TMObject *ChangeTMObjectDock(struct TMHandle *handle,
  861.                                     struct TMObjectDock *tmobj,
  862.                                     struct TagItem *tags)
  863. {
  864.  struct TagItem *ti,*tstate;
  865.  struct DockTool *dt;
  866.  
  867.  /* Search last dock tool */
  868.  dt=tmobj->do_Tools;
  869.  if (dt)
  870.   while (dt->dt_Next) dt=dt->dt_Next;
  871.  
  872.  /* Close dock */
  873.  if (tmobj->do_Window) CloseDockWindow(tmobj);
  874.  
  875.  /* Scan tag list */
  876.  tstate=tags;
  877.  while (ti=NextTagItem(&tstate)) {
  878.  
  879.   DEBUG_PRINTF("Got Tag (0x%08lx)\n",ti->ti_Tag);
  880.  
  881.   switch (ti->ti_Tag) {
  882.    case TMOP_Columns:   if (ti->ti_Data) tmobj->do_Columns=ti->ti_Data;
  883.                         break;
  884.    case TMOP_Font:      {
  885.                          struct TextAttr *ta=(struct TextAttr *) ti->ti_Data;
  886.  
  887.                          if (ta && ta->ta_Name) tmobj->do_Font=ta;
  888.                         }
  889.                         break;
  890.    case TMOP_HotKey:    if (tmobj->do_CxObj) {
  891.                          SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  892.                          tmobj->do_CxObj=NULL;
  893.                         }
  894.  
  895.                         tmobj->do_HotKey=(char *) ti->ti_Data;
  896.                         break;
  897.    case TMOP_LeftEdge:  tmobj->do_LeftEdge=ti->ti_Data;
  898.                         break;
  899.    case TMOP_PubScreen: tmobj->do_PubScreen=(char *) ti->ti_Data;
  900.                         break;
  901.    case TMOP_Title:     tmobj->do_Title=(char *) ti->ti_Data;
  902.                         break;
  903.    case TMOP_Tool:      if (ti->ti_Data) {
  904.                          struct DockTool *newdt;
  905.  
  906.                          /* Alloc DockTool structure */
  907.                          if (newdt=AllocMem(sizeof(struct DockTool),
  908.                                             MEMF_CLEAR)) {
  909.                           char **names=(char **) ti->ti_Data;
  910.  
  911.                           /* Add link to Exec object */
  912.                           if (names[0] &&
  913.                               (newdt->dt_ExecLink=AddLinkTMObject(handle,
  914.                                                                   names[0],
  915.                                                                 TMOBJTYPE_EXEC,
  916.                                                             (struct TMObject *)
  917.                                                                   tmobj)))
  918.                            /* Get name of exec object. We use names[0]
  919.                               instead of object name, because the link could
  920.                               be deleted while window is still active. */
  921.                            newdt->dt_ExecName=names[0];
  922.  
  923.                           /* Add link to Image object */
  924.                           if (names[1])
  925.                            newdt->dt_ImageLink=AddLinkTMObject(handle,names[1],
  926.                                                                TMOBJTYPE_IMAGE,
  927.                                                            (struct TMObject *)
  928.                                                                tmobj);
  929.  
  930.                           /* Add link to Sound object */
  931.                           if (names[2])
  932.                            newdt->dt_SoundLink=AddLinkTMObject(handle,names[2],
  933.                                                                TMOBJTYPE_SOUND,
  934.                                                            (struct TMObject *)
  935.                                                                tmobj);
  936.  
  937.                           /* Add node to list. Head of list? */
  938.                           if (dt) {
  939.                            /* No. Add to tail */
  940.                            dt->dt_Next=newdt;
  941.                            dt=newdt;
  942.                           } else {
  943.                            /* Yes. Init list anchor */
  944.                            tmobj->do_Tools=newdt;
  945.                            dt=newdt;
  946.                           }
  947.                          }
  948.                         }
  949.                         break;
  950.    case TMOP_TopEdge:   tmobj->do_TopEdge=ti->ti_Data;
  951.                         break;
  952.   }
  953.  }
  954.  
  955.  /* Set new flags */
  956.  tmobj->do_Flags=PackBoolTags(tmobj->do_Flags,tags,flagmap);
  957.  
  958.  /* HotKey set? Create Commodities object from HotKey description */
  959.  if (tmobj->do_HotKey && !tmobj->do_CxObj &&
  960.      (tmobj->do_CxObj=HotKey(tmobj->do_HotKey,BrokerPort,
  961.                              (ULONG) &tmobj->do_Link))) {
  962.  
  963.   DEBUG_PRINTF("Created CxObj (0x%08lx)\n",tmobj->do_CxObj);
  964.  
  965.   /* Attach object to broker */
  966.   AttachCxObj(Broker,tmobj->do_CxObj);
  967.  
  968.   /* Commodities error? */
  969.   if (CxObjError(Broker)) {
  970.    SafeDeleteCxObjAll(tmobj->do_CxObj,&tmobj->do_Link);
  971.    tmobj->do_CxObj=NULL;
  972.   }
  973.  }
  974.  
  975.  /* Active flag set? */
  976.  if (tmobj->do_Flags & DO_Activated)
  977.   /* Yes. Open dock window */
  978.   OpenDockWindow(tmobj);
  979.  
  980.  /* All OK. */
  981.  return(TRUE);
  982. }
  983.  
  984. /* Update link structures */
  985. void DeleteLinkTMObjectDock(struct TMLink *tml)
  986. {
  987.  struct TMObjectDock *tmobj=tml->tml_LinkedTo;
  988.  struct DockTool *dt=tmobj->do_Tools;
  989.  
  990.  /* Scan tool list */
  991.  while (dt) {
  992.   /* Link to Exec object? */
  993.   if (tml==dt->dt_ExecLink) {
  994.    dt->dt_ExecLink=NULL;
  995.    dt->dt_ExecName=NULL;
  996.    break;
  997.   }
  998.   /* Link to Image object? */
  999.   else if (tml==(struct TMLink *) dt->dt_ImageLink) {
  1000.    /* Image object active? */
  1001.    if (tml->tml_Active)
  1002.     /* Yes. Deactivate it */
  1003.     CallActivateTMObject((struct TMLink *) tml,(void *) IOC_DEACTIVE);
  1004.  
  1005.    dt->dt_ImageLink=NULL;
  1006.    break;
  1007.   }
  1008.   /* Link to Sound object? */
  1009.   else if (tml==dt->dt_SoundLink) {
  1010.    dt->dt_SoundLink=NULL;
  1011.    break;
  1012.   }
  1013.  
  1014.   /* Get pointer to next tool */
  1015.   dt=dt->dt_Next;
  1016.  }
  1017. }
  1018.  
  1019. /* Find dock tool that corresponds to X,Y position */
  1020. static struct DockTool *FindDockTool(struct TMObjectDock *tmobj, ULONG x,
  1021.                                      ULONG y)
  1022. {
  1023.  struct DockTool *dt;
  1024.  UWORD dx=tmobj->do_Left;
  1025.  UWORD dy=tmobj->do_Top;
  1026.  UWORD w,h;
  1027.  ULONG col,cols;
  1028.  
  1029.  /* Out of bounds? */
  1030.  if ((x<dx) || (y<dy)) return(NULL); /* Yes! */
  1031.  
  1032.  /* Init variables */
  1033.  dt=tmobj->do_Tools;
  1034.  w=tmobj->do_XSize;
  1035.  h=tmobj->do_YSize;
  1036.  cols=tmobj->do_Columns;
  1037.  col=0;
  1038.  
  1039.  /* Scan dock tool list */
  1040.  while (dt)
  1041.   if ((x>=dx) && (y>=dy) && (x<dx+w) && (y<dy+h)) {
  1042.    /* Tool found */
  1043.    tmobj->do_Selected=dt;
  1044.    tmobj->do_SelectX=dx;
  1045.    tmobj->do_SelectY=dy;
  1046.    return(dt);
  1047.   } else {
  1048.    /* Increment column counter */
  1049.    col++;
  1050.  
  1051.    /* Last column? */
  1052.    if (col==cols) {
  1053.     /* Yes */
  1054.     dx=tmobj->do_Left;
  1055.     dy+=h;
  1056.     col=0;
  1057.    } else
  1058.     /* No */
  1059.     dx+=w;
  1060.  
  1061.    /* Get pointer to next dock tool */
  1062.    dt=dt->dt_Next;
  1063.   }
  1064.  
  1065.  /* Dock tool not found */
  1066.  return(NULL);
  1067. }
  1068.  
  1069. /* Activate a Dock object */
  1070. void ActivateTMObjectDock(struct TMLink *tml, struct AppMessage *msg)
  1071. {
  1072.  struct TMObjectDock *tmobj=tml->tml_Linked;
  1073.  
  1074.  DEBUG_PRINTF("Activate/Dock (0x%08lx)\n",msg);
  1075.  
  1076.  /* Got arguments? */
  1077.  if (msg) {
  1078.   /* Yes. Icons were dropped on the dock */
  1079.   struct DockTool *dt;
  1080.  
  1081.   /* Find Tool */
  1082.   if (dt=FindDockTool(tmobj,msg->am_MouseX,msg->am_MouseY)) {
  1083.    /* Activate Sound object */
  1084.    if (dt->dt_SoundLink) CallActivateTMObject(dt->dt_SoundLink,NULL);
  1085.  
  1086.    /* Activate Image object */
  1087.    if (!(tmobj->do_Flags & DO_Text) && dt->dt_ImageLink)
  1088.     CallActivateTMObject((struct TMLink *) dt->dt_ImageLink,
  1089.                          (void *) IOC_FULLANIM);
  1090.  
  1091.    /* Activate Exec object */
  1092.    if (dt->dt_ExecLink) CallActivateTMObject(dt->dt_ExecLink,msg);
  1093.  
  1094.    /* Clear pointer */
  1095.    tmobj->do_Selected=NULL;
  1096.  
  1097.    /* PopUp dock? Yes, close window */
  1098.    if (tmobj->do_Flags & DO_PopUp) CloseDockWindow(tmobj);
  1099.   }
  1100.  }
  1101.  /* No. User pressed HotKey. Window open? */
  1102.  else if (tmobj->do_Window)
  1103.   /* Close window and free its resources */
  1104.   CloseDockWindow(tmobj);
  1105.  else {
  1106.   /* Window not open. Open it. */
  1107.   OpenDockWindow(tmobj);
  1108.  
  1109.   /* If DO_FrontMost is not set, move screen to front */
  1110.   if (!(tmobj->do_Flags & DO_FrontMost) && tmobj->do_Window)
  1111.    ScreenToFront(tmobj->do_Window->WScreen);
  1112.  }
  1113. }
  1114.  
  1115. /* Handle IDCMP events */
  1116. void HandleIDCMPEvents(void)
  1117. {
  1118.  struct IntuiMessage *msg;
  1119.  
  1120.  /* Scan IDCMP message port */
  1121.  while (msg=GT_GetIMsg(IDCMPPort)) {
  1122.   struct TMObjectDock *tmobj=msg->IDCMPWindow->UserData;
  1123.   BOOL closewindow=FALSE;
  1124.  
  1125.   DEBUG_PRINTF("IDCMP Class: 0x%08lx\n",msg->Class);
  1126.  
  1127.   switch (msg->Class) {
  1128.    case IDCMP_CLOSEWINDOW:    /* Set close flag */
  1129.                               closewindow=TRUE;
  1130.                               break;
  1131.    case IDCMP_REFRESHWINDOW:  {
  1132.                                struct Window *w=tmobj->do_Window;
  1133.  
  1134.                                GT_BeginRefresh(w);
  1135.                                GT_EndRefresh(w,TRUE);
  1136.                               }
  1137.                               break;
  1138.    case IDCMP_MOUSEBUTTONS:   /* Only docks with images need button events */
  1139.                               if (!(tmobj->do_Flags & DO_Text))
  1140.                                switch (msg->Code) {
  1141.                                 case SELECTDOWN: /* Select button pressed */
  1142.                                  {
  1143.                                   struct DockTool *dt;
  1144.  
  1145.                                   if (dt=FindDockTool(tmobj,msg->MouseX,
  1146.                                                             msg->MouseY)) {
  1147.                                    struct TMLinkImage *tmli=dt->dt_ImageLink;
  1148.  
  1149.                                    DEBUG_PRINTF("Dock selected: 0x%08lx\n",dt);
  1150.  
  1151.                                    /* Got a dock tool with image object? */
  1152.                                    if (tmli)
  1153.                                     /* Image object with active anim? */
  1154.                                     if (tmli->tmli_Link.tml_Active)
  1155.                                      /* Yes, clear pointer */
  1156.                                      tmobj->do_Selected=NULL;
  1157.                                     else
  1158.                                      /* No, select it */
  1159.                                      CallActivateTMObject((struct TMLink *)
  1160.                                                           tmli,
  1161.                                                           (void *) IOC_ACTIVE);
  1162.                                   }
  1163.                                  }
  1164.                                  break;
  1165.                                 case SELECTUP:   /* Select button released */
  1166.                                  {
  1167.                                   struct DockTool *dt=tmobj->do_Selected;
  1168.  
  1169.                                   /* Got a selected dock tool? */
  1170.                                   if (dt) {
  1171.                                    struct TMLinkImage *tmli=dt->dt_ImageLink;
  1172.  
  1173.                                    /* Dock tool with image object? */
  1174.                                    if (tmli) {
  1175.                                     UWORD x=msg->MouseX;
  1176.                                     UWORD y=msg->MouseY;
  1177.                                     UWORD dx=tmobj->do_SelectX;
  1178.                                     UWORD dy=tmobj->do_SelectY;
  1179.  
  1180.                                     /* Mouse still on dock tool and no */
  1181.                                     /* double click?                   */
  1182.                                     if ((x>=dx) && (y>=dy) &&
  1183.                                         (x<dx+tmobj->do_XSize) &&
  1184.                                         (y<dy+tmobj->do_YSize) &&
  1185.                                         !DoubleClick(tmobj->do_Seconds,
  1186.                                                      tmobj->do_Micros,
  1187.                                                      msg->Seconds,
  1188.                                                      msg->Micros)) {
  1189.                                      /* Yes. Activate objects */
  1190.                                      /* Activate Sound object */
  1191.                                      if (dt->dt_SoundLink)
  1192.                                       CallActivateTMObject(dt->dt_SoundLink,
  1193.                                                            NULL);
  1194.  
  1195.                                      /* Activate Image object */
  1196.                                      CallActivateTMObject((struct TMLink *)
  1197.                                                           tmli,
  1198.                                                           (void *) IOC_CONTANIM
  1199.                                                           );
  1200.  
  1201.                                      /* Activate Exec object */
  1202.                                      if (dt->dt_ExecLink)
  1203.                                       CallActivateTMObject(dt->dt_ExecLink,
  1204.                                                            NULL);
  1205.  
  1206.                                      /* Save time stamp */
  1207.                                      tmobj->do_Seconds=msg->Seconds;
  1208.                                      tmobj->do_Micros=msg->Micros;
  1209.  
  1210.                                      /* PopUp dock? */
  1211.                                      if (tmobj->do_Flags & DO_PopUp)
  1212.                                       /* Yes. Close window */
  1213.                                       closewindow=TRUE;
  1214.                                     }
  1215.                                     else
  1216.                                      /* No, de-select image */
  1217.                                      CallActivateTMObject((struct TMLink *)
  1218.                                                           dt->dt_ImageLink,
  1219.                                                           (void *) IOC_DEACTIVE
  1220.                                                          );
  1221.                                    }
  1222.  
  1223.                                    /* Clear pointer */
  1224.                                    tmobj->do_Selected=NULL;
  1225.                                   }
  1226.                                  }
  1227.                                  break;
  1228.                                }
  1229.                               break;
  1230.    case IDCMP_GADGETUP:       /* Prevent double clicks */
  1231.                               if (!DoubleClick(tmobj->do_Seconds,
  1232.                                                tmobj->do_Micros,
  1233.                                                msg->Seconds,msg->Micros)) {
  1234.                                struct DockTool *dt=(struct DockTool *)
  1235.                                 ((struct Gadget *) msg->IAddress)->UserData;
  1236.  
  1237.                                /* Activate sound object */
  1238.                                if (dt->dt_SoundLink)
  1239.                                 CallActivateTMObject(dt->dt_SoundLink,NULL);
  1240.  
  1241.                                /* Activate Exec object */
  1242.                                if (dt->dt_ExecLink)
  1243.                                 CallActivateTMObject(dt->dt_ExecLink,NULL);
  1244.  
  1245.                                /* Save time stamp */
  1246.                                tmobj->do_Seconds=msg->Seconds;
  1247.                                tmobj->do_Micros=msg->Micros;
  1248.  
  1249.                                /* PopUp dock? */
  1250.                                if (tmobj->do_Flags & DO_PopUp)
  1251.                                 /* Yes. Close window */
  1252.                                 closewindow=TRUE;
  1253.                               }
  1254.                               break;
  1255.    case IDCMP_MENUPICK:       {
  1256.                                USHORT menunum=msg->Code;
  1257.  
  1258.                                /* Scan all menu events */
  1259.                                while (menunum!=MENUNULL) {
  1260.                                 struct MenuItem *menuitem=
  1261.                                  ItemAddress(tmobj->do_Menu,menunum);
  1262.  
  1263.                                 /* Which menu selected? */
  1264.                                 switch(GTMENUITEM_USERDATA(menuitem)) {
  1265.                                  case MENU_CLOSE: closewindow=TRUE;
  1266.                                                   break;
  1267.                                  case MENU_QUIT:  Closing=TRUE;
  1268.                                                   break;
  1269.                                 }
  1270.  
  1271.                                 /* Get next menu event */
  1272.                                 menunum=menuitem->NextSelect;
  1273.                                }
  1274.                               }
  1275.                               break;
  1276.    case IDCMP_ACTIVEWINDOW:   if (!tmobj->do_Title) {
  1277.                                /* Borderless window */
  1278.                                struct RastPort *rp=tmobj->do_Window->RPort;
  1279.                                struct Gadget *g=&tmobj->do_DragGadget;
  1280.  
  1281.                                SetDrMd(rp,JAM1);
  1282.                                SetAPen(rp,tmobj->do_FillPen);
  1283.                                RectFill(rp,1,1,g->Width-2,g->Height-2);
  1284.                               }
  1285.                               break;
  1286.    case IDCMP_INACTIVEWINDOW: {
  1287.                                struct DockTool *dt=tmobj->do_Selected;
  1288.  
  1289.                                if (!tmobj->do_Title) {
  1290.                                 /* Borderless window */
  1291.                                 struct RastPort *rp=tmobj->do_Window->RPort;
  1292.                                 struct Gadget *g=&tmobj->do_DragGadget;
  1293.  
  1294.                                 SetDrMd(rp,JAM1);
  1295.                                 SetAPen(rp,tmobj->do_BackPen);
  1296.                                 RectFill(rp,1,1,g->Width-2,g->Height-2);
  1297.                                }
  1298.  
  1299.                                /* Missed a selectup??? */
  1300.                                if (dt) {
  1301.                                 struct TMLinkImage *tmli=dt->dt_ImageLink;
  1302.  
  1303.                                 /* Got non-ANIM image object? */
  1304.                                 if (tmli && !tmli->tmli_Link.tml_Active)
  1305.                                  CallActivateTMObject((struct TMLink *) tmli,
  1306.                                                       (void *) IOC_DEACTIVE);
  1307.  
  1308.                                 tmobj->do_Selected=NULL;
  1309.                                }
  1310.                               }
  1311.                               break;
  1312.   }
  1313.  
  1314.   /* Reply message */
  1315.   GT_ReplyIMsg(msg);
  1316.  
  1317.   /* Close window? */
  1318.   if (closewindow) CloseDockWindow(tmobj);
  1319.  }
  1320. }
  1321.