home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / FastMacroWindow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  20.0 KB  |  1,033 lines

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