home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / telecomm / terms / term-4.1-source.lha / Extras / Source / term-Source.lha / termFastMacroWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-04  |  20.2 KB  |  1,035 lines

  1. /*
  2. **    termFastMacroWindow.c
  3. **
  4. **    Fast! macro window support routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Window border scroller. */
  13.  
  14. enum    {    GAD_SCROLLER = 10000,GAD_UP,GAD_DOWN };
  15.  
  16.     /* The arrow image height. */
  17.  
  18. #define ARROW_HEIGHT    11
  19.  
  20.     /* Pack two words into a long. */
  21.  
  22. #define PACK_ULONG(a,b)    (((ULONG)(a)) << 16 | b)
  23.  
  24.     /* Gadget extension. */
  25.  
  26. struct ButtonInfo
  27. {
  28.     struct Image    *ButtonImage;
  29.     STRPTR         ButtonCommand;
  30.     LONG         NumChars;
  31. };
  32.  
  33.     /* A private button gadget attribute. */
  34.  
  35. #define BGA_Command    (TAG_USER + 1)
  36.  
  37.     /* Private button gadget class. */
  38.  
  39. STATIC struct IClass        *ButtonClass;
  40.  
  41.     /* Window border scroller. */
  42.  
  43. STATIC struct Gadget        *Scroller,
  44.                 *UpArrow,
  45.                 *DownArrow;
  46.  
  47.     /* Width of the window border scroller. */
  48.  
  49. STATIC UWORD             RightBorderWidth;
  50.  
  51.     /* Scroller arrow imagery. */
  52.  
  53. STATIC struct Image        *UpImage,
  54.                 *DownImage;
  55.  
  56.     /* The window zoom box. */
  57.  
  58. STATIC struct IBox         WindowZoomBox = { -1,-1,-1,-1 };
  59.  
  60.     /* The fast macro buttons. */
  61.  
  62. STATIC struct Gadget        *Buttons;
  63.  
  64.     /* The first visible button and the number buttons
  65.      * visible in total.
  66.      */
  67.  
  68. STATIC LONG             ButtonTop,
  69.                  ButtonCount;
  70.  
  71.     /* RenderText():
  72.      *
  73.      *    Render the button text.
  74.      */
  75.  
  76. STATIC VOID __regargs
  77. RenderText(struct RastPort *RPort,struct GadgetInfo *GadgetInfo,struct Gadget *Gadget,LONG Len)
  78. {
  79.     UWORD    Width    = (GadgetInfo -> gi_Window -> Width - (GadgetInfo -> gi_Window -> BorderLeft + GadgetInfo -> gi_Window -> BorderRight + 4));
  80.     STRPTR    Label    = (STRPTR)Gadget -> GadgetText;
  81.     ULONG    State;
  82.     UWORD    Pen;
  83.  
  84.         /* Which state is the button in? */
  85.  
  86.     if(Gadget -> Flags & GFLG_SELECTED)
  87.     {
  88.         State    = IDS_SELECTED;
  89.         Pen    = GadgetInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN];
  90.     }
  91.     else
  92.     {
  93.         State    = IDS_NORMAL;
  94.         Pen    = GadgetInfo -> gi_DrInfo -> dri_Pens[TEXTPEN];
  95.     }
  96.  
  97.         /* Render the frame. */
  98.  
  99.     DoMethod(Gadget -> GadgetRender,IM_DRAWFRAME,RPort,PACK_ULONG(Gadget -> LeftEdge + 2,Gadget -> TopEdge),State,GadgetInfo -> gi_DrInfo,PACK_ULONG(Width,Gadget -> Height));
  100.  
  101.         /* Set the rendering pens. */
  102.  
  103.     if(Kick30)
  104.         SetABPenDrMd(RPort,Pen,0,JAM1);
  105.     else
  106.     {
  107.         SetDrMd(RPort,JAM1);
  108.         SetAPen(RPort,Pen);
  109.     }
  110.  
  111.         /* Render the button label. */
  112.  
  113.     Move(RPort,Gadget -> LeftEdge + 4,Gadget -> TopEdge + (Gadget -> Height - GadgetInfo -> gi_DrInfo -> dri_Font -> tf_YSize) / 2 + GadgetInfo -> gi_DrInfo -> dri_Font -> tf_Baseline);
  114.     Text(RPort,Label,Len);
  115. }
  116.  
  117.     /* SetButton():
  118.      *
  119.      *    Set an aspect of the button.
  120.      */
  121.  
  122. STATIC ULONG __regargs
  123. SetButton(struct IClass *class,Object *object,struct opSet *SetInfo)
  124. {
  125.     struct ButtonInfo    *ButtonInfo = INST_DATA(class,object);
  126.     struct TagItem        *Tag,*TagList = SetInfo -> ops_AttrList;
  127.     struct RastPort        *RPort;
  128.     STRPTR             Label;
  129.     BOOLEAN             Finished = FALSE;
  130.  
  131.         /* Scan the attribute list. */
  132.  
  133.     while(Tag = NextTagItem(&TagList))
  134.     {
  135.         switch(Tag -> ti_Tag)
  136.         {
  137.                 // New command string?
  138.  
  139.             case BGA_Command:
  140.  
  141.                 ButtonInfo -> ButtonCommand = (STRPTR)Tag -> ti_Data;
  142.                 break;
  143.  
  144.                 // New label text?
  145.  
  146.             case GA_Text:
  147.  
  148.                 Label = (STRPTR)Tag -> ti_Data;
  149.  
  150.                 ((struct Gadget *)object) -> GadgetText = (struct IntuiText *)Label;
  151.  
  152.                 if(RPort = ObtainGIRPort(SetInfo -> ops_GInfo))
  153.                 {
  154.                     struct TextExtent Extent;
  155.  
  156.                     ButtonInfo -> NumChars = TextFit(RPort,Label,strlen(Label),&Extent,NULL,1,((struct Gadget *)object) -> Width - 8,32767);
  157.  
  158.                     RenderText(RPort,SetInfo -> ops_GInfo,(struct Gadget *)object,ButtonInfo -> NumChars);
  159.  
  160.                     ReleaseGIRPort(RPort);
  161.                 }
  162.  
  163.                 Finished = TRUE;
  164.  
  165.                 break;
  166.         }
  167.     }
  168.  
  169.     if(Finished)
  170.         return(TRUE);
  171.     else
  172.         return(DoSuperMethodA(class,object,(Msg)SetInfo));
  173. }
  174.  
  175.     /* RenderButton():
  176.      *
  177.      *    Render the button label.
  178.      */
  179.  
  180. STATIC ULONG __regargs
  181. RenderButton(struct IClass *class,Object *object,struct gpRender *RenderInfo)
  182. {
  183.     struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
  184.  
  185.         /* No label length calculated yet? */
  186.  
  187.     if(!ButtonInfo -> NumChars)
  188.     {
  189.         STRPTR            Label = (STRPTR)((struct Gadget *)object) -> GadgetText;
  190.         struct TextExtent    Extent;
  191.  
  192.         ButtonInfo -> NumChars = TextFit(RenderInfo -> gpr_RPort,Label,strlen(Label),&Extent,NULL,1,((struct Gadget *)object) -> Width - 8,32767);
  193.     }
  194.  
  195.     RenderText(RenderInfo -> gpr_RPort,RenderInfo -> gpr_GInfo,(struct Gadget *)object,ButtonInfo -> NumChars);
  196.  
  197.     return(TRUE);
  198. }
  199.  
  200.     /* FreeButton():
  201.      *
  202.      *    Free a button gadget object.
  203.      */
  204.  
  205. STATIC ULONG __regargs
  206. FreeButton(struct IClass *class,Object *object,Msg msg)
  207. {
  208.     struct ButtonInfo *ButtonInfo = INST_DATA(class,object);
  209.  
  210.     if(ButtonInfo -> ButtonImage)
  211.         DisposeObject(ButtonInfo -> ButtonImage);
  212.  
  213.     return(DoSuperMethodA(class,object,msg));
  214. }
  215.  
  216.     /* NewButton():
  217.      *
  218.      *    Create a new button object.
  219.      */
  220.  
  221. STATIC ULONG __regargs
  222. NewButton(struct IClass *class,Object *object,struct opSet *SetMethod)
  223. {
  224.     LONG         Width,
  225.              Height;
  226.     struct TagItem    *Tag;
  227.     struct Gadget    *NewGadget = NULL;
  228.  
  229.         /* Determine object width. */
  230.  
  231.     if(Tag = FindTagItem(GA_Width,SetMethod -> ops_AttrList))
  232.         Width = Tag -> ti_Data;
  233.     else
  234.         Width = 0;
  235.  
  236.         /* Determine object height. */
  237.  
  238.     if(Tag = FindTagItem(GA_Height,SetMethod -> ops_AttrList))
  239.         Height = Tag -> ti_Data;
  240.     else
  241.         Height = 0;
  242.  
  243.         /* Proper dimensions? */
  244.  
  245.     if(Width && Height)
  246.     {
  247.         struct Image *ButtonImage;
  248.  
  249.             /* Create a button frame. */
  250.  
  251.         if(ButtonImage = NewObject(NULL,"frameiclass",
  252.             IA_Width,    Width,
  253.             IA_Height,    Height,
  254.         TAG_DONE))
  255.         {
  256.             struct TagItem    *OldTags = SetMethod -> ops_AttrList,
  257.                      NewTags[2];
  258.  
  259.                 /* Add new tag values. */
  260.  
  261.             NewTags[0] . ti_Tag    = GA_Image;
  262.             NewTags[0] . ti_Data    = (ULONG)ButtonImage;
  263.             NewTags[1] . ti_Tag    = TAG_MORE;
  264.             NewTags[1] . ti_Data    = (ULONG)OldTags;
  265.  
  266.             SetMethod -> ops_AttrList = NewTags;
  267.  
  268.                 /* Create new object. */
  269.  
  270.             if(NewGadget = (struct Gadget *)DoSuperMethodA(class,object,(Msg)SetMethod))
  271.             {
  272.                 struct ButtonInfo *ButtonInfo = INST_DATA(class,NewGadget);
  273.  
  274.                     /* Clear the number of characters displayed,
  275.                      * the first rendering call will adjust it.
  276.                      */
  277.  
  278.                 ButtonInfo -> NumChars = 0;
  279.  
  280.                     /* Install the corresponding command. */
  281.  
  282.                 if(Tag = FindTagItem(BGA_Command,OldTags))
  283.                     ButtonInfo -> ButtonCommand = (STRPTR)Tag -> ti_Data;
  284.  
  285.                     /* Remember the frame image. */
  286.  
  287.                 ButtonInfo -> ButtonImage = ButtonImage;
  288.  
  289.                     /* Restore the tags. */
  290.  
  291.                 SetMethod -> ops_AttrList = OldTags;
  292.             }
  293.             else
  294.                 DisposeObject(ButtonImage);
  295.         }
  296.     }
  297.  
  298.     return((ULONG)NewGadget);
  299. }
  300.  
  301.     /* HandleButton():
  302.      *
  303.      *    Handle button input.
  304.      */
  305.  
  306. STATIC ULONG __regargs
  307. HandleButton(struct IClass *class,Object *object,struct gpInput *InputInfo)
  308. {
  309.     ULONG             Result        = GMR_MEACTIVE;
  310.     BOOLEAN             Redraw        = FALSE,
  311.                  Final        = FALSE;
  312.     struct ButtonInfo    *ButtonInfo    = INST_DATA(class,object);
  313.     struct Gadget        *Button        = (struct Gadget *)object;
  314.  
  315.         /* Only mouse events trigger actions. */
  316.  
  317.     if(InputInfo -> gpi_IEvent -> ie_Class == IECLASS_RAWMOUSE)
  318.     {
  319.             /* Selection cancelled or no command available? */
  320.  
  321.         if(InputInfo -> gpi_IEvent -> ie_Code == MENUDOWN || !ButtonInfo -> ButtonCommand[0])
  322.         {
  323.             if(Button -> Flags & GFLG_SELECTED)
  324.             {
  325.                 Button -> Flags &= ~GFLG_SELECTED;
  326.  
  327.                 Redraw = TRUE;
  328.             }
  329.  
  330.             Result = GMR_NOREUSE;
  331.  
  332.                 /* No further actions, please. */
  333.  
  334.             Final = TRUE;
  335.         }
  336.         else
  337.         {
  338.                 /* Select button released? */
  339.  
  340.             if(InputInfo -> gpi_IEvent -> ie_Code == SELECTUP)
  341.             {
  342.                 if(Button -> Flags & GFLG_SELECTED)
  343.                 {
  344.                     *InputInfo -> gpi_Termination = 0;
  345.  
  346.                     Button -> Flags &= ~GFLG_SELECTED;
  347.  
  348.                     Redraw = TRUE;
  349.                 }
  350.                 else
  351.                     *InputInfo -> gpi_Termination = 1;
  352.  
  353.                 Result = GMR_REUSE | GMR_VERIFY;
  354.  
  355.                     /* No further actions, please. */
  356.  
  357.                 Final = TRUE;
  358.             }
  359.         }
  360.     }
  361.  
  362.         /* Change highlighting mode? */
  363.  
  364.     if(!Final)
  365.     {
  366.             /* Hit inside the boundaries? */
  367.  
  368.         if(DoMethod((Object *)ButtonInfo -> ButtonImage,IM_HITFRAME,PACK_ULONG(InputInfo -> gpi_Mouse . X,InputInfo -> gpi_Mouse . Y),PACK_ULONG(Button -> Width,Button -> Height)))
  369.         {
  370.             if(!(Button -> Flags & GFLG_SELECTED))
  371.             {
  372.                 Button -> Flags |= GFLG_SELECTED;
  373.  
  374.                 Redraw = TRUE;
  375.             }
  376.         }
  377.         else
  378.         {
  379.             if(Button -> Flags & GFLG_SELECTED)
  380.             {
  381.                 Button -> Flags &= ~GFLG_SELECTED;
  382.  
  383.                 Redraw = TRUE;
  384.             }
  385.         }
  386.     }
  387.  
  388.         /* Redraw the object? */
  389.  
  390.     if(Redraw)
  391.     {
  392.         struct RastPort *RPort;
  393.  
  394.         if(RPort = ObtainGIRPort(InputInfo -> gpi_GInfo))
  395.         {
  396.             RenderText(RPort,InputInfo -> gpi_GInfo,Button,ButtonInfo -> NumChars);
  397.  
  398.             ReleaseGIRPort(RPort);
  399.         }
  400.     }
  401.  
  402.     return(Result);
  403. }
  404.  
  405.     /* ButtonDispatch():
  406.      *
  407.      *    The button gadget class dispatcher.
  408.      */
  409.  
  410. STATIC ULONG __saveds __asm
  411. ButtonDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
  412. {
  413.         /* Select the message method. */
  414.  
  415.     switch(msg -> MethodID)
  416.     {
  417.         case OM_NEW:
  418.  
  419.             return(NewButton(class,object,(struct opSet *)msg));
  420.  
  421.         case OM_UPDATE:
  422.         case OM_SET:
  423.  
  424.             return(SetButton(class,object,(struct opSet *)msg));
  425.  
  426.         case OM_DISPOSE:
  427.  
  428.             return(FreeButton(class,object,msg));
  429.  
  430.         case GM_RENDER:
  431.  
  432.             return(RenderButton(class,object,(struct gpRender *)msg));
  433.  
  434.         case GM_HITTEST:
  435.  
  436.             return(GMR_GADGETHIT);
  437.  
  438.         case GM_GOINACTIVE:
  439.  
  440.             return(0);
  441.  
  442.         case GM_GOACTIVE:
  443.  
  444.             return(GMR_MEACTIVE);
  445.  
  446.         case GM_HANDLEINPUT:
  447.  
  448.             return(HandleButton(class,object,(struct gpInput *)msg));
  449.  
  450.         default:
  451.  
  452.             return(DoSuperMethodA(class,object,msg));
  453.     }
  454. }
  455.  
  456.     /* FreeButtonClass(VOID):
  457.      *
  458.      *    Free private button gadget class.
  459.      */
  460.  
  461. STATIC VOID
  462. FreeButtonClass(VOID)
  463. {
  464.     if(ButtonClass)
  465.     {
  466.         FreeClass(ButtonClass);
  467.  
  468.         ButtonClass = NULL;
  469.     }
  470. }
  471.  
  472.     /* NewButtonClass(VOID):
  473.      *
  474.      *    Create private button gadget class.
  475.      */
  476.  
  477. STATIC BYTE
  478. NewButtonClass(VOID)
  479. {
  480.     if(ButtonClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(struct ButtonInfo),0))
  481.     {
  482.         ButtonClass -> cl_Dispatcher . h_Entry = (HOOKFUNC)ButtonDispatch;
  483.  
  484.         return(TRUE);
  485.     }
  486.     else
  487.         return(FALSE);
  488. }
  489.  
  490.     /* FastDeleteScroller(VOID):
  491.      *
  492.      *    Delete fast! macro window scroller.
  493.      */
  494.  
  495. STATIC VOID
  496. FastDeleteScroller(VOID)
  497. {
  498.     if(Scroller)
  499.     {
  500.         DisposeObject(Scroller);
  501.  
  502.         Scroller = NULL;
  503.     }
  504.  
  505.     if(UpArrow)
  506.     {
  507.         DisposeObject(UpArrow);
  508.  
  509.         UpArrow = NULL;
  510.     }
  511.  
  512.     if(DownArrow)
  513.     {
  514.         DisposeObject(DownArrow);
  515.  
  516.         DownArrow = NULL;
  517.     }
  518.  
  519.     if(UpImage)
  520.     {
  521.         DisposeObject(UpImage);
  522.  
  523.         UpImage = NULL;
  524.     }
  525.  
  526.     if(DownImage)
  527.     {
  528.         DisposeObject(DownImage);
  529.  
  530.         DownImage = NULL;
  531.     }
  532. }
  533.  
  534.     /* FastCreateScroller(struct Screen *Screen):
  535.      *
  536.      *    Create fast! macro window scroller.
  537.      */
  538.  
  539. STATIC BYTE __regargs
  540. FastCreateScroller(struct Screen *Screen)
  541. {
  542.     struct DrawInfo    *DrawInfo;
  543.     BYTE         Result = FALSE;
  544.  
  545.     if(DrawInfo = GetScreenDrawInfo(Screen))
  546.     {
  547.         struct Image    *SizeImage;
  548.         ULONG         SizeWidth,
  549.                  SizeHeight,
  550.                  ArrowHeight;
  551.         UWORD         SizeType;
  552.  
  553.         if(Screen -> Flags & SCREENHIRES)
  554.         {
  555.             SizeWidth    = 18;
  556.             SizeHeight    = 10;
  557.  
  558.             SizeType    = SYSISIZE_MEDRES;
  559.         }
  560.         else
  561.         {
  562.             SizeWidth    = 13;
  563.             SizeHeight    = 11;
  564.  
  565.             SizeType    = SYSISIZE_LOWRES;
  566.         }
  567.  
  568.         if(SizeImage = (struct Image *)NewObject(NULL,"sysiclass",
  569.             SYSIA_Size,    SizeType,
  570.             SYSIA_Which,    SIZEIMAGE,
  571.             SYSIA_DrawInfo,    DrawInfo,
  572.         TAG_DONE))
  573.         {
  574.             GetAttr(IA_Width,    SizeImage,&SizeWidth);
  575.             GetAttr(IA_Height,    SizeImage,&SizeHeight);
  576.  
  577.             DisposeObject(SizeImage);
  578.  
  579.             RightBorderWidth = SizeWidth;
  580.  
  581.             if(UpImage = (struct Image *)NewObject(NULL,"sysiclass",
  582.                 SYSIA_Size,    SizeType,
  583.                 SYSIA_Which,    UPIMAGE,
  584.                 SYSIA_DrawInfo,    DrawInfo,
  585.             TAG_DONE))
  586.             {
  587.                 GetAttr(IA_Height,UpImage,&ArrowHeight);
  588.  
  589.                 if(DownImage = (struct Image *)NewObject(NULL,"sysiclass",
  590.                     SYSIA_Size,    SizeType,
  591.                     SYSIA_Which,    DOWNIMAGE,
  592.                     SYSIA_DrawInfo,    DrawInfo,
  593.                 TAG_DONE))
  594.                 {
  595.                     if(Scroller = NewObject(NULL,"propgclass",
  596.                         GA_ID,        GAD_SCROLLER,
  597.  
  598.                         GA_Top,        Screen -> WBorTop + Screen -> Font -> ta_YSize + 2,
  599.                         GA_RelHeight,    -(Screen -> WBorTop + Screen -> Font -> ta_YSize + 2 + SizeHeight + 1 + 2 * ArrowHeight),
  600.                         GA_Width,    SizeWidth - 8,
  601.                         GA_RelRight,    -(SizeWidth - 5),
  602.  
  603.                         GA_Immediate,    TRUE,
  604.                         GA_FollowMouse,    TRUE,
  605.                         GA_RelVerify,    TRUE,
  606.                         GA_RightBorder,    TRUE,
  607.  
  608.                         PGA_Freedom,    FREEVERT,
  609.                         PGA_NewLook,    TRUE,
  610.                         PGA_Borderless,    TRUE,
  611.  
  612.                         PGA_Visible,    1,
  613.                         PGA_Total,    1,
  614.                     TAG_DONE))
  615.                     {
  616.                         STATIC struct TagItem ArrowMappings[] = { GA_ID,GA_ID,TAG_END };
  617.  
  618.                         if(UpArrow = NewObject(NULL,"buttongclass",
  619.                             GA_ID,        GAD_UP,
  620.  
  621.                             GA_Image,    UpImage,
  622.                             GA_RelRight,    -(SizeWidth - 1),
  623.                             GA_RelBottom,    -(SizeHeight - 1 + 2 * ArrowHeight),
  624.                             GA_Height,    ArrowHeight,
  625.                             GA_Width,    SizeWidth,
  626.                             GA_Immediate,    TRUE,
  627.                             GA_RelVerify,    TRUE,
  628.                             GA_Previous,    Scroller,
  629.                             GA_RightBorder,    TRUE,
  630.  
  631.                             ICA_TARGET,    ICTARGET_IDCMP,
  632.                             ICA_MAP,    ArrowMappings,
  633.                         TAG_DONE))
  634.                         {
  635.                             if(DownArrow = NewObject(NULL,"buttongclass",
  636.                                 GA_ID,        GAD_DOWN,
  637.  
  638.                                 GA_Image,    DownImage,
  639.                                 GA_RelRight,    -(SizeWidth - 1),
  640.                                 GA_RelBottom,    -(SizeHeight - 1 + ArrowHeight),
  641.                                 GA_Height,    ArrowHeight,
  642.                                 GA_Width,    SizeWidth,
  643.                                 GA_Immediate,    TRUE,
  644.                                 GA_RelVerify,    TRUE,
  645.                                 GA_Previous,    UpArrow,
  646.                                 GA_RightBorder,    TRUE,
  647.  
  648.                                 ICA_TARGET,    ICTARGET_IDCMP,
  649.                                 ICA_MAP,    ArrowMappings,
  650.                             TAG_DONE))
  651.                                 Result = TRUE;
  652.                         }
  653.                     }
  654.                 }
  655.             }
  656.         }
  657.  
  658.         FreeScreenDrawInfo(Screen,DrawInfo);
  659.     }
  660.  
  661.     return(Result);
  662. }
  663.  
  664.     /* RefreshFastWindow(WORD FastWindowHeight):
  665.      *
  666.      *    Refresh the contents of the fast! macro window.
  667.      */
  668.  
  669. VOID __regargs
  670. RefreshFastWindow(BYTE FullRefresh)
  671. {
  672.     if(FastWindow)
  673.     {
  674.         LONG Count = (FastWindow -> Height - (FastWindow -> BorderTop + FastWindow -> BorderBottom + 1)) / (2 + UserFontHeight + 2 + 1);
  675.  
  676.         if(FullRefresh)
  677.             ButtonCount = 0;
  678.  
  679.         if(Count == ButtonCount && Buttons)
  680.         {
  681.             LONG NewTop;
  682.  
  683.             if(!GetAttr(PGA_Top,Scroller,(ULONG *)&NewTop))
  684.                 NewTop = 0;
  685.  
  686.             if(NewTop != ButtonTop)
  687.             {
  688.                 ButtonTop = NewTop;
  689.  
  690.                 Count = 0;
  691.  
  692.                 if(FastMacroList . lh_Head -> ln_Succ)
  693.                 {
  694.                     struct DrawInfo *DrawInfo;
  695.  
  696.                     if(DrawInfo = GetScreenDrawInfo(FastWindow -> WScreen))
  697.                     {
  698.                         struct MacroNode    *Node    = (struct MacroNode *)GetListNode(ButtonTop,&FastMacroList);
  699.                         struct Gadget        *Button    = Buttons;
  700.  
  701.                         while(Count < ButtonCount && Node -> mn_Succ)
  702.                         {
  703.                             SetGadgetAttrs(Button,FastWindow,NULL,
  704.                                 GA_Text,    Node -> mn_Macro,
  705.                                 BGA_Command,    Node -> mn_Code,
  706.                             TAG_DONE);
  707.  
  708.                             Count++;
  709.  
  710.                             Button = Button -> NextGadget;
  711.  
  712.                             Node = Node -> mn_Succ;
  713.                         }
  714.  
  715.                         FreeScreenDrawInfo(FastWindow -> WScreen,DrawInfo);
  716.                     }
  717.                 }
  718.             }
  719.         }
  720.         else
  721.         {
  722.             LONG Top = FastWindow -> BorderTop + 1;
  723.  
  724.             if(Buttons)
  725.             {
  726.                 struct Gadget    *Next = Buttons,
  727.                         *Button;
  728.  
  729.                 RemoveGList(FastWindow,Buttons,-1);
  730.  
  731.                 while(Button = Next)
  732.                 {
  733.                     Next = Button -> NextGadget;
  734.  
  735.                     DisposeObject(Button);
  736.                 }
  737.  
  738.                 Buttons = NULL;
  739.             }
  740.  
  741.             ButtonCount = Count;
  742.  
  743.             if(ButtonTop >= FastMacroCount)
  744.                 ButtonTop = FastMacroCount - ButtonCount;
  745.             else
  746.             {
  747.                 if(ButtonTop + ButtonCount > FastMacroCount)
  748.                     ButtonTop = FastMacroCount - ButtonCount;
  749.             }
  750.  
  751.             if(ButtonTop < 0)
  752.                 ButtonTop = 0;
  753.  
  754.             Count = 0;
  755.  
  756.             if(FastMacroList . lh_Head -> ln_Succ)
  757.             {
  758.                 struct DrawInfo *DrawInfo;
  759.  
  760.                 if(DrawInfo = GetScreenDrawInfo(FastWindow -> WScreen))
  761.                 {
  762.                     struct MacroNode    *Node        = (struct MacroNode *)GetListNode(ButtonTop,&FastMacroList);
  763.                     LONG             Width        = FastWindow -> Width - (FastWindow -> BorderLeft + FastWindow -> BorderRight);
  764.                     struct Gadget        *Previous    = NULL,
  765.                                 *Button;
  766.  
  767.                     while(Count < ButtonCount && Node -> mn_Succ)
  768.                     {
  769.                         if(Button = NewObject(ButtonClass,NULL,
  770.                             GA_ID,        Count,
  771.  
  772.                             GA_Top,        Top,
  773.                             GA_Left,    FastWindow -> BorderLeft,
  774.  
  775.                             GA_Width,    Width,
  776.                             GA_Height,    (2 + UserFontHeight + 2),
  777.                             GA_RelVerify,    TRUE,
  778.  
  779.                             GA_DrawInfo,    DrawInfo,
  780.                             GA_Text,    Node -> mn_Macro,
  781.                             BGA_Command,    Node -> mn_Code,
  782.  
  783.                             Previous ? GA_Previous : TAG_IGNORE,Previous,
  784.                         TAG_DONE))
  785.                         {
  786.                             Top += 2 + UserFontHeight + 2 + 1;
  787.  
  788.                             Count++;
  789.  
  790.                             Previous = Button;
  791.  
  792.                             if(!Buttons)
  793.                                 Buttons = Button;
  794.  
  795.                             Node = Node -> mn_Succ;
  796.                         }
  797.                     }
  798.  
  799.                     FreeScreenDrawInfo(FastWindow -> WScreen,DrawInfo);
  800.                 }
  801.             }
  802.  
  803.             if(Count)
  804.             {
  805.                 AddGList(FastWindow,Buttons,-1,-1,NULL);
  806.  
  807.                 RefreshGList(Buttons,FastWindow,NULL,-1);
  808.             }
  809.  
  810.             if(Top < FastWindow -> Height - (FastWindow -> BorderBottom + 1))
  811.             {
  812.                 SetAPen(FastWindow -> RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  813.  
  814.                 RectFill(FastWindow -> RPort,FastWindow -> BorderLeft,Top,FastWindow -> Width - (FastWindow -> BorderRight + 1),FastWindow -> Height - (FastWindow -> BorderBottom + 1));
  815.             }
  816.  
  817.             SetGadgetAttrs(Scroller,FastWindow,NULL,
  818.                 PGA_Top,    ButtonTop,
  819.                 PGA_Visible,    ButtonCount,
  820.                 PGA_Total,    FastMacroCount,
  821.             TAG_DONE);
  822.         }
  823.     }
  824. }
  825.  
  826.     /* CloseFastWindow():
  827.      *
  828.      *    Close the fast! macro window and free the associated resources.
  829.      */
  830.  
  831. VOID
  832. CloseFastWindow()
  833. {
  834.     CheckItem(MEN_FAST_MACROS_WINDOW,FALSE);
  835.  
  836.     if(Buttons)
  837.     {
  838.         struct Gadget    *Next = Buttons,
  839.                 *Button;
  840.  
  841.         RemoveGList(FastWindow,Buttons,-1);
  842.  
  843.         while(Button = Next)
  844.         {
  845.             Next = Button -> NextGadget;
  846.  
  847.             DisposeObject(Button);
  848.         }
  849.  
  850.         Buttons = NULL;
  851.     }
  852.  
  853.     if(FastWindow)
  854.     {
  855.         PutWindowInfo(WINDOW_FAST,FastWindow -> LeftEdge,FastWindow -> TopEdge,FastWindow -> Width,FastWindow -> Height);
  856.  
  857.         ClearMenuStrip(FastWindow);
  858.         CloseWindowSafely(FastWindow);
  859.  
  860.         FastWindow = NULL;
  861.     }
  862.  
  863.     FreeButtonClass();
  864. }
  865.  
  866.     /* OpenFastWindow():
  867.      *
  868.      *    Open the fast! macro window.
  869.      */
  870.  
  871. BYTE
  872. OpenFastWindow()
  873. {
  874.     if(NewButtonClass())
  875.     {
  876.         if(FastCreateScroller(Window -> WScreen))
  877.         {
  878.             LONG    Left    = 0,
  879.                 Top    = 0,
  880.                 Width    = Window -> WScreen -> WBorLeft + 2 + SZ_GetLen("####################") + 2 + RightBorderWidth,
  881.                 Height    = 0;
  882.  
  883.             GetWindowInfo(WINDOW_FAST,&Left,&Top,&Width,&Height,NULL,Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 1 + 10 * (2 + UserFontHeight + 2 + 1) + Window -> WScreen -> WBorBottom);
  884.  
  885.             if(WindowZoomBox . Left == -1)
  886.             {
  887.                 WindowZoomBox . Left    = 0;
  888.                 WindowZoomBox . Top    = 0;
  889.                 WindowZoomBox . Width    = Width;
  890.                 WindowZoomBox . Height    = Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1;
  891.             }
  892.  
  893.             if(FastWindow = OpenWindowTags(NULL,
  894.                 WA_Width,        Width,
  895.                 WA_Height,        Height,
  896.  
  897.                 WA_Left,        Left,
  898.                 WA_Top,            Top,
  899.  
  900.                 WA_DragBar,        TRUE,
  901.                 WA_DepthGadget,        TRUE,
  902.                 WA_CloseGadget,        TRUE,
  903.                 WA_RMBTrap,        TRUE,
  904.                 WA_Zoom,        &WindowZoomBox,
  905.                 WA_NoCareRefresh,    TRUE,
  906.                 WA_BackFill,        &BackfillHook,
  907.                 WA_MenuHelp,        TRUE,
  908.  
  909.                 WA_SizeGadget,        TRUE,
  910.  
  911.                 WA_MinWidth,        Width,
  912.                 WA_MaxWidth,        Width,
  913.  
  914.                 WA_MinHeight,        Window -> WScreen -> WBorTop + Window -> WScreen -> Font -> ta_YSize + 1 + 2 * (2 + UserFontHeight + 2 + 1) + 1 + Window -> WScreen -> WBorBottom,
  915.                 WA_MaxHeight,        Window -> WScreen -> Height,
  916.  
  917.                 WA_Title,        LocaleString(MSG_FASTMACROS_FAST_MACROS_TXT),
  918.  
  919.                 WA_NewLookMenus,    TRUE,
  920.                 WA_Gadgets,        Scroller,
  921.  
  922.                 WA_CustomScreen,    Window -> WScreen,
  923.  
  924.                 AmigaGlyph ? WA_AmigaKey  : TAG_IGNORE, AmigaGlyph,
  925.                 CheckGlyph ? WA_Checkmark : TAG_IGNORE, CheckGlyph,
  926.             TAG_DONE))
  927.             {
  928.                 ButtonTop    = 0;
  929.                 ButtonCount    = -1;
  930.  
  931.                 FastWindow -> UserPort = Window -> UserPort;
  932.  
  933.                 ModifyIDCMP(FastWindow,Window -> IDCMPFlags | IDCMP_IDCMPUPDATE | IDCMP_SIZEVERIFY);
  934.  
  935.                 SetMenuStrip(FastWindow,Menu);
  936.  
  937.                 FastWindow -> Flags &= ~WFLG_RMBTRAP;
  938.  
  939.                 RefreshFastWindow(TRUE);
  940.  
  941.                 CheckItem(MEN_FAST_MACROS_WINDOW,TRUE);
  942.  
  943.                 return(TRUE);
  944.             }
  945.  
  946.             FastDeleteScroller();
  947.         }
  948.  
  949.         FreeButtonClass();
  950.     }
  951.  
  952.     return(FALSE);
  953. }
  954.  
  955.     /* HandleFastWindowGadget(ULONG IClass,LONG ICode,LONG GadgetID):
  956.      *
  957.      *    Process fast! macro window input.
  958.      */
  959.  
  960. VOID __regargs
  961. HandleFastWindowGadget(ULONG IClass,LONG ICode,LONG GadgetID)
  962. {
  963.     STATIC BYTE Scrolling = FALSE;
  964.  
  965.     switch(IClass)
  966.     {
  967.         case IDCMP_GADGETUP:
  968.  
  969.             if(GadgetID == GAD_SCROLLER)
  970.                 Scrolling = FALSE;
  971.             else
  972.             {
  973.                 if(GadgetID < GAD_SCROLLER && !ICode)
  974.                 {
  975.                     struct MacroNode *Node;
  976.  
  977.                     if(Node = (struct MacroNode *)GetListNode(GadgetID + ButtonTop,&FastMacroList))
  978.                     {
  979.                         if(Node -> mn_Code[0])
  980.                             SerialCommand(Node -> mn_Code);
  981.                     }
  982.                 }
  983.             }
  984.  
  985.             break;
  986.  
  987.         case IDCMP_GADGETDOWN:
  988.  
  989.             if(GadgetID == GAD_SCROLLER)
  990.             {
  991.                 Scrolling = TRUE;
  992.  
  993.                 RefreshFastWindow(FALSE);
  994.             }
  995.  
  996.             break;
  997.  
  998.         case IDCMP_MOUSEMOVE:
  999.  
  1000.             if(Scrolling)
  1001.                 RefreshFastWindow(FALSE);
  1002.  
  1003.             break;
  1004.  
  1005.         case IDCMP_IDCMPUPDATE:
  1006.  
  1007.             switch(GadgetID)
  1008.             {
  1009.                 case GAD_UP:    if(ButtonTop)
  1010.                         {
  1011.                             SetGadgetAttrs(Scroller,FastWindow,NULL,
  1012.                                 PGA_Top,ButtonTop - 1,
  1013.                             TAG_DONE);
  1014.  
  1015.                             RefreshFastWindow(FALSE);
  1016.                         }
  1017.  
  1018.                         break;
  1019.  
  1020.                 case GAD_DOWN:    if(ButtonTop + ButtonCount < FastMacroCount)
  1021.                         {
  1022.                             SetGadgetAttrs(Scroller,FastWindow,NULL,
  1023.                                 PGA_Top,ButtonTop + 1,
  1024.                             TAG_DONE);
  1025.  
  1026.                             RefreshFastWindow(FALSE);
  1027.                         }
  1028.  
  1029.                         break;
  1030.             }
  1031.  
  1032.             break;
  1033.     }
  1034. }
  1035.