home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Programming / ace_gpl_release / src / lib / c / gadget.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-10-04  |  23.0 KB  |  908 lines

  1. /*
  2. ** ACE linked-library module: Gadgets.
  3. ** Copyright (C) 1998 David Benn
  4. ** 
  5. ** This program is free software; you can redistribute it and/or
  6. ** modify it under the terms of the GNU General Public License
  7. ** as published by the Free Software Foundation; either version 2
  8. ** of the License, or (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. **
  19. ** Author: David J Benn
  20. **   Date: 1st,2nd,4th,6th-9th November 1993,
  21. **       5th,25th December 1993,
  22. **       7th March 1994,
  23. **       30th April 1994,
  24. **       6th May 1994,
  25. **       20th,21st,24th,25th,30th June 1994,
  26. **       6th,7th,10th,12th,24th,29th July 1994,
  27. **       26th-28th August 1994,
  28. **       3rd,10th September 1994,
  29. **       27th February 1995,
  30. **       11th,12th March 1995,
  31. **       6th,7th November 1995
  32. */
  33.  
  34. #include <exec/types.h>
  35. #include <exec/memory.h>
  36. #include <intuition/intuition.h>
  37. #include "intuievent.h"
  38.  
  39. #define CLEARED_ANY_MEM    7L
  40.  
  41. #define    MAXCHARS        1024L
  42.  
  43. #define MAXGADGET        255
  44. #define CLOSEGAD       256L
  45.  
  46. #define FontWidth       (Scrn->RastPort.Font->tf_XSize)
  47. #define FontHeight       (Scrn->RastPort.Font->tf_YSize)
  48.  
  49. #define RAISED            1L
  50. #define STRGADBOX       3L
  51.  
  52. /* type declarations */
  53. typedef    union  gadinfo_type {
  54.             struct    StringInfo stringinfo;
  55.             struct    PropInfo   propinfo;
  56.                } GADINFO;
  57.  
  58. typedef struct gadget_type {
  59.             BOOL    used/*,selected*/;
  60.             ULONG    type,style;
  61.             ULONG    maxval;
  62.             SHORT     gadpairs[10];
  63.             SHORT     bb_x1, bb_y1, bb_x2, bb_y2;
  64.             WORD    render_buffer[4];
  65.             struct    Border       gadborder;
  66.             struct    IntuiText gadtext;
  67.             struct    Gadget      gad;
  68.             GADINFO gadinfo;    
  69.             } GAD;
  70.  
  71. /* globals */
  72. static    BOOL    first_creation=TRUE;
  73. static    GAD     gadlist[MAXGADGET+1];
  74. static    ULONG    gadnum=0;
  75.  
  76. /* external variables */
  77. extern    struct     Screen     *Scrn;
  78. extern    struct     Window     *Wdw;
  79. extern    struct    RastPort *RPort;
  80. extern    struct    Library  *DiskfontBase;
  81.     
  82. /* external functions */
  83. extern     LONG    stringcompare();
  84. extern     LONG    long_from_string();
  85. extern     ULONG    stringlength();
  86. extern    void    stringcopy();
  87. extern    void    *alloc();
  88. extern    void    set_wdw_close_num();
  89. extern    void    BevelBox();
  90.  
  91. /* functions */    
  92. UBYTE *FontOK(fontName,fontSize,textStyle,theText,textLength,fontHeight)
  93. UBYTE *fontName;
  94. ULONG fontSize,textStyle;
  95. UBYTE *theText;
  96. SHORT *textLength,*fontHeight;
  97. {
  98. /*
  99. ** Determine whether requested font can be used. If so,
  100. ** textLength is set to the number of pixels which would
  101. ** be occupied by the specified text, fontHeight is set to
  102. ** the height of the requested font, and a pointer to the 
  103. ** full name of the font is returned.
  104. */
  105. UBYTE *tmp,*font;
  106. ULONG oldStyle;
  107. struct TextAttr theFont;
  108. struct TextFont *oldFont,*newFont;
  109.  
  110.     DiskfontBase = (struct Library *)
  111.             OpenLibrary("diskfont.library",0L);
  112.  
  113.     if (DiskfontBase && fontName != NULL)
  114.     {
  115.         /* append ".font" to name if not present */
  116.         font = (UBYTE *)alloc(CLEARED_ANY_MEM,stringlength(fontName)+6);
  117.                     
  118.         stringcopy(font,fontName);
  119.         tmp = font;
  120.         while (*tmp && *tmp != '.') tmp++;
  121.         if (stringcompare(*tmp,".font") != 0) stringcopy(tmp,".font");
  122.  
  123.         /* set up TextAttr structure */
  124.         theFont.ta_Name     = (STRPTR)font;
  125.         theFont.ta_YSize    = (UWORD)fontSize;
  126.         theFont.ta_Style    = (UBYTE)textStyle;
  127.         theFont.ta_Flags    = FPF_DISKFONT;
  128.  
  129.         /* attempt to open font */
  130.         newFont = (struct TextFont *)OpenDiskFont(&theFont);    
  131.  
  132.         /* 
  133.         ** Set new font, set length and height parameters, 
  134.         ** set old font again, close font under test. Style
  135.         ** may also need to be restored if newFont's differs
  136.         ** from oldFont's.
  137.         */
  138.         if (newFont) 
  139.         {
  140.             oldFont = RPort->Font;
  141.             oldStyle = RPort->AlgoStyle;
  142.             SetFont(RPort,newFont);
  143.  
  144.             *textLength = (WORD)TextLength(RPort,theText,
  145.                                stringlength(theText));
  146.             *fontHeight = RPort->Font->tf_YSize;
  147.  
  148.             SetFont(RPort,oldFont);
  149.             SetSoftStyle(RPort,oldStyle,0xFFFF);
  150.             CloseFont(newFont);
  151.         }
  152.  
  153.         /* cleanup */
  154.         CloseLibrary(DiskfontBase);
  155.  
  156.         /* font is OK */
  157.         return font;
  158.     }
  159.     else
  160.         /* font is not OK */
  161.         return NULL;
  162. }
  163.  
  164. void CreateBoolGadget(textstyle,fontsize,fontname,gadstyle,
  165.               bottom,right,top,left,gadval,status,id)
  166. ULONG textstyle,fontsize;
  167. UBYTE *fontname;
  168. ULONG gadstyle,bottom,right,top,left,gadval,status,id;
  169. {
  170. /* create a boolean gadget */
  171. SHORT width,height,text_left,text_top,gad_center_X,gad_center_Y;
  172. SHORT text_length,font_height;
  173. struct TextAttr theFont;
  174. UBYTE *realName;
  175.  
  176.     /* width and height of gadget */
  177.     width     = right-left;
  178.     height     = bottom-top;
  179.  
  180.     /* text font,style,position */
  181.     gad_center_X      = width/2; 
  182.     gad_center_Y      = height/2; 
  183.     
  184.     if (realName = FontOK(fontname,fontsize,textstyle,(UBYTE *)gadval,
  185.                   &text_length,&font_height))
  186.     {
  187.         /*
  188.         ** Font can be used.
  189.         */
  190.         theFont.ta_Name  = (STRPTR)realName;
  191.         theFont.ta_YSize = (UWORD)fontsize;
  192.         theFont.ta_Style = (UBYTE)textstyle;
  193.         theFont.ta_Flags = FPF_DISKFONT;
  194.  
  195.         gadlist[id].gadtext.ITextFont = &theFont;
  196.     
  197.         text_left = gad_center_X - text_length/2; 
  198.         text_top  = gad_center_Y - font_height/2;
  199.     }
  200.     else
  201.     {
  202.         /*
  203.         ** Font not specified or invalid.
  204.         */
  205.         gadlist[id].gadtext.ITextFont = NULL;
  206.  
  207.         text_left = gad_center_X - (FontWidth*stringlength((UBYTE *)gadval))/2; 
  208.         text_top  = gad_center_Y - FontHeight/2;
  209.     }
  210.  
  211.     /* border point pairs */
  212.     gadlist[id].gadpairs[0] = 0;
  213.     gadlist[id].gadpairs[1] = 0;
  214.     gadlist[id].gadpairs[2] = width;
  215.     gadlist[id].gadpairs[3] = 0;
  216.     gadlist[id].gadpairs[4] = width;
  217.     gadlist[id].gadpairs[5] = height;
  218.     gadlist[id].gadpairs[6] = 0;
  219.     gadlist[id].gadpairs[7] = height;
  220.     gadlist[id].gadpairs[8] = 0;
  221.     gadlist[id].gadpairs[9] = 0;
  222.  
  223.     /* fill border structure */
  224.     gadlist[id].gadborder.LeftEdge     = 0;
  225.     gadlist[id].gadborder.TopEdge     = 0;
  226.     gadlist[id].gadborder.FrontPen     = 1;
  227.     gadlist[id].gadborder.BackPen     = 0;
  228.     gadlist[id].gadborder.DrawMode    = JAM2;
  229.     gadlist[id].gadborder.Count    = 5;
  230.     gadlist[id].gadborder.XY    = gadlist[id].gadpairs;
  231.     gadlist[id].gadborder.NextBorder= NULL;
  232.  
  233.     /* fill intuitext structure */
  234.     gadlist[id].gadtext.FrontPen    = 1;
  235.     gadlist[id].gadtext.BackPen    = 0;
  236.     gadlist[id].gadtext.DrawMode    = JAM2;
  237.     gadlist[id].gadtext.LeftEdge    = text_left;
  238.     gadlist[id].gadtext.TopEdge    = text_top;
  239.  
  240.     gadlist[id].gadtext.IText = (UBYTE *)
  241.                      alloc(CLEARED_ANY_MEM,
  242.                        stringlength((UBYTE *)gadval)+1);
  243.     stringcopy(gadlist[id].gadtext.IText,(UBYTE *)gadval);
  244.     gadlist[id].gadtext.NextText    = NULL;
  245.  
  246.     /* fill gadget structure */
  247.     gadlist[id].gad.NextGadget    = NULL;
  248.     gadlist[id].gad.LeftEdge    = (SHORT)left;
  249.     gadlist[id].gad.TopEdge        = (SHORT)top;
  250.     gadlist[id].gad.Width        = width;
  251.     gadlist[id].gad.Height        = height;
  252.     gadlist[id].gad.Activation    = RELVERIFY;
  253.     gadlist[id].gad.GadgetType    = BOOLGADGET;
  254.     gadlist[id].gad.GadgetRender    = (APTR)&gadlist[id].gadborder;
  255.     gadlist[id].gad.SelectRender    = NULL;
  256.     gadlist[id].gad.GadgetText    = &gadlist[id].gadtext;
  257.     gadlist[id].gad.MutualExclude    = NULL;
  258.     gadlist[id].gad.SpecialInfo    = NULL;
  259.     gadlist[id].gad.GadgetID    = (USHORT)id;
  260.     gadlist[id].gad.UserData    = NULL;
  261.  
  262.     /* 
  263.     ** Set selection style (1=bgnd color fill, 2=bgnd color box,
  264.     ** 3=bgnd color fill+borderless+no text).
  265.     */
  266.  
  267.     gadlist[id].gad.Flags = NULL;  /* Clear flags from last usage. */
  268.  
  269.     switch(gadstyle)
  270.     {
  271.      case 1  : gadlist[id].gad.Flags = GADGHCOMP; 
  272.            break;
  273.  
  274.      case 2  : gadlist[id].gad.Flags = GADGHBOX; 
  275.            break;
  276.  
  277.      case 3  : gadlist[id].gad.Flags = GADGHCOMP;  /* same as 1, but no BB */
  278.            break;
  279.     }
  280.  
  281.     /* disable gadget? */
  282.     if (status == 0) gadlist[id].gad.Flags |= GADGDISABLED;
  283.  
  284.     /* don't render a border - let bevelbox do that. */
  285.     gadlist[id].gad.GadgetRender = NULL;
  286.  
  287.     /* render the gadget! */
  288.     AddGadget(Wdw,&gadlist[id].gad,(UWORD)id);
  289.     RefreshGList(&gadlist[id].gad,Wdw,NULL,1);
  290.     
  291.     /* make gadget beveled if not borderless */
  292.     gadlist[id].bb_x1 = left;
  293.     gadlist[id].bb_y1 = top;
  294.     gadlist[id].bb_x2 = right-1;
  295.     gadlist[id].bb_y2 = bottom-1;
  296.     if (gadstyle != 3) BevelBox(RAISED,bottom-1,right-1,top,left);
  297. }
  298.  
  299. void CreateStringGadget(gadstyle,gadtype,bottom,right,top,left,gadval,status,id)
  300. ULONG gadstyle,gadtype,bottom,right,top,left,gadval,status,id;
  301. {
  302. /* create a string gadget */
  303. SHORT width,height;
  304.  
  305.     /* width and height of gadget */
  306.     width     = right-left;
  307.     height     = bottom-top;
  308.  
  309.     /* how many characters can be accomodated by gadget? */
  310.     gadlist[id].maxval = MAXCHARS;
  311.  
  312.     /* border point pairs */
  313.     gadlist[id].gadpairs[0] = 0;
  314.     gadlist[id].gadpairs[1] = 0;
  315.     gadlist[id].gadpairs[2] = width;
  316.     gadlist[id].gadpairs[3] = 0;
  317.     gadlist[id].gadpairs[4] = width;
  318.     gadlist[id].gadpairs[5] = height;
  319.     gadlist[id].gadpairs[6] = 0;
  320.     gadlist[id].gadpairs[7] = height;
  321.     gadlist[id].gadpairs[8] = 0;
  322.     gadlist[id].gadpairs[9] = 0;
  323.  
  324.     /* fill border structure */
  325.     gadlist[id].gadborder.LeftEdge     = -6;
  326.     gadlist[id].gadborder.TopEdge     = -3;
  327.     gadlist[id].gadborder.FrontPen     = 1;
  328.     gadlist[id].gadborder.BackPen     = 0;
  329.     gadlist[id].gadborder.DrawMode    = JAM2;
  330.     gadlist[id].gadborder.Count    = 5;
  331.     gadlist[id].gadborder.XY    = gadlist[id].gadpairs;
  332.     gadlist[id].gadborder.NextBorder= NULL;
  333.  
  334.     /* fill gadget's gadinfo.stringinfo structure */
  335.     gadlist[id].gadinfo.stringinfo.Buffer = (UBYTE *)
  336.                 AllocMem(MAXCHARS,MEMF_ANY | MEMF_CLEAR);
  337.     gadlist[id].gadinfo.stringinfo.UndoBuffer = (UBYTE *)
  338.                 AllocMem(MAXCHARS,MEMF_ANY | MEMF_CLEAR);
  339.  
  340.     stringcopy(gadlist[id].gadinfo.stringinfo.Buffer,(UBYTE *)gadval);
  341.  
  342.     gadlist[id].gadinfo.stringinfo.BufferPos = 0;
  343.     gadlist[id].gadinfo.stringinfo.MaxChars = (SHORT)MAXCHARS;
  344.     gadlist[id].gadinfo.stringinfo.DispPos = 0;
  345.     gadlist[id].gadinfo.stringinfo.UndoPos = 0;
  346.     gadlist[id].gadinfo.stringinfo.NumChars = 0;
  347.     gadlist[id].gadinfo.stringinfo.DispCount = 0;
  348.     gadlist[id].gadinfo.stringinfo.CLeft = 0;
  349.     gadlist[id].gadinfo.stringinfo.CTop = 0;
  350.  
  351.     if (gadtype == 3)
  352.         gadlist[id].gadinfo.stringinfo.LongInt = long_from_string(gadval);
  353.     else
  354.         gadlist[id].gadinfo.stringinfo.LongInt = 0L;
  355.  
  356.     gadlist[id].gadinfo.stringinfo.AltKeyMap = NULL;
  357.     
  358.     /* fill gadget structure */
  359.     gadlist[id].gad.NextGadget    = NULL;
  360.     gadlist[id].gad.LeftEdge    = (SHORT)left;
  361.     gadlist[id].gad.TopEdge        = (SHORT)top;
  362.     gadlist[id].gad.Width        = width-FontWidth-1;
  363.     gadlist[id].gad.Height        = height;
  364.      gadlist[id].gad.Flags         = GADGHCOMP; 
  365.     gadlist[id].gad.Activation    = RELVERIFY;
  366.     gadlist[id].gad.GadgetType    = STRGADGET;
  367.     gadlist[id].gad.GadgetRender    = (APTR)&gadlist[id].gadborder;
  368.     gadlist[id].gad.SelectRender    = NULL;
  369.     gadlist[id].gad.GadgetText    = NULL;
  370.     gadlist[id].gad.MutualExclude    = NULL;
  371.     gadlist[id].gad.SpecialInfo    = (APTR)&gadlist[id].gadinfo.stringinfo;
  372.     gadlist[id].gad.GadgetID    = (USHORT)id;
  373.     gadlist[id].gad.UserData    = NULL;
  374.  
  375.     /* string or longint gadget type? */
  376.     if (gadtype == 3) gadlist[id].gad.Activation |= LONGINT;
  377.  
  378.     /* set selection style (0=LEFT, 1=CENTER, 2=RIGHT, N=LEFT) */
  379.     switch(gadstyle)
  380.     {
  381.      case 1  : gadlist[id].gad.Activation |= STRINGCENTER;
  382.            break;
  383.  
  384.      case 2  : gadlist[id].gad.Activation |= STRINGRIGHT;
  385.            break;
  386.     }
  387.  
  388.     /* render the gadget! */
  389.     AddGadget(Wdw,&gadlist[id].gad,(UWORD)id);
  390.     RefreshGList(&gadlist[id].gad,Wdw,NULL,1);
  391.  
  392.     /* disable gadget? -> do so after rendering: don't want to see shadow. */
  393.     if (status == 0) gadlist[id].gad.Flags |= GADGDISABLED;
  394.  
  395.     /* make gadget beveled */ 
  396.     gadlist[id].bb_x1 = left-6;
  397.     gadlist[id].bb_y1 = top-3;
  398.     gadlist[id].bb_x2 = right-6;
  399.     gadlist[id].bb_y2 = bottom-3;
  400.     BevelBox(STRGADBOX,bottom-3,right-6,top-3,left-6);
  401. }
  402.  
  403. void CreatePropGadget(gadstyle,gadtype,bottom,right,top,left,gadval,status,id)
  404. ULONG gadstyle,gadtype,bottom,right,top,left,gadval,status,id;
  405. {
  406. /* create a proportional gadget */
  407. SHORT width,height;
  408.  
  409.     /* width and height of gadget */
  410.     width     = right-left;
  411.     height     = bottom-top;
  412.  
  413.     /* record knob increment */
  414.     if (gadval <= 0) gadval=1; 
  415.     gadlist[id].maxval = 0xFFFF / gadval;
  416.  
  417.     /* fill gadinfo.propinfo structure */
  418.     gadlist[id].gadinfo.propinfo.Flags = AUTOKNOB;
  419.  
  420.     switch(gadtype)
  421.     {
  422.      case 4 : gadlist[id].gadinfo.propinfo.HorizPot = 0;
  423.           gadlist[id].gadinfo.propinfo.HorizBody = gadlist[id].maxval;
  424.           break;
  425.  
  426.      case 5 : gadlist[id].gadinfo.propinfo.VertPot = 0;
  427.           gadlist[id].gadinfo.propinfo.VertBody = gadlist[id].maxval;
  428.           break;
  429.     }
  430.  
  431.     gadlist[id].gadinfo.propinfo.CWidth     = 0;
  432.     gadlist[id].gadinfo.propinfo.CHeight     = 0;
  433.     gadlist[id].gadinfo.propinfo.HPotRes     = 0;
  434.     gadlist[id].gadinfo.propinfo.VPotRes     = 0;
  435.     gadlist[id].gadinfo.propinfo.LeftBorder    = 0;
  436.     gadlist[id].gadinfo.propinfo.TopBorder     = 0;
  437.  
  438.     /* fill gadget structure */
  439.     gadlist[id].gad.NextGadget    = NULL;
  440.     gadlist[id].gad.LeftEdge    = (SHORT)left+4;
  441.     gadlist[id].gad.TopEdge        = (SHORT)top+2;
  442.     gadlist[id].gad.Width        = width-7;
  443.     gadlist[id].gad.Height        = height-3;
  444.     gadlist[id].gad.Flags        = GADGHCOMP;
  445.     gadlist[id].gad.Activation    = RELVERIFY;
  446.     gadlist[id].gad.GadgetType    = PROPGADGET;
  447.     gadlist[id].gad.GadgetRender    = (APTR)gadlist[id].render_buffer;
  448.     gadlist[id].gad.SelectRender    = NULL;
  449.     gadlist[id].gad.GadgetText    = NULL;
  450.     gadlist[id].gad.MutualExclude    = NULL;
  451.     gadlist[id].gad.SpecialInfo    = (APTR)&gadlist[id].gadinfo.propinfo;
  452.     gadlist[id].gad.GadgetID    = (USHORT)id;
  453.     gadlist[id].gad.UserData    = NULL;
  454.  
  455.     /* set type (4=horizontal, 5=vertical, N=horizontal) */
  456.     switch(gadtype)
  457.     {
  458.      case 4  : gadlist[id].gadinfo.propinfo.Flags |= FREEHORIZ; 
  459.            break;
  460.  
  461.      case 5  : gadlist[id].gadinfo.propinfo.Flags |= FREEVERT; 
  462.            break;
  463.     }
  464.  
  465.     /* set style */
  466.     if (gadstyle == 1) 
  467.            gadlist[id].gadinfo.propinfo.Flags |= PROPBORDERLESS;
  468.  
  469.     /* disable gadget? */
  470.     if (status == 0) gadlist[id].gad.Flags |= GADGDISABLED;
  471.  
  472.     /* prepare for beveled gadget [if not borderless]? */ 
  473.     if (gadstyle != 1)
  474.        gadlist[id].gadinfo.propinfo.Flags |= PROPBORDERLESS;
  475.  
  476.     /* render the gadget! */
  477.     AddGadget(Wdw,&gadlist[id].gad,(UWORD)id);
  478.     RefreshGList(&gadlist[id].gad,Wdw,NULL,1);
  479.  
  480.     /* make gadget beveled if not borderless */ 
  481.     gadlist[id].bb_x1 = left;
  482.     gadlist[id].bb_y1 = top;
  483.     gadlist[id].bb_x2 = right;
  484.     gadlist[id].bb_y2 = bottom;
  485.     if (gadstyle != 1) BevelBox(RAISED,bottom,right,top,left);
  486. }
  487.  
  488. void CreateGadget(textstyle,fontsize,fontname,gadstyle,gadtype,
  489.           bottom,right,top,left,gadval,status,id)
  490. ULONG textstyle,fontsize;
  491. UBYTE *fontname;
  492. ULONG gadstyle,gadtype,bottom,right,top,left,gadval,status,id;
  493. {
  494. /* create a gadget */
  495. ULONG i;
  496.  
  497.     if (first_creation)
  498.     {
  499.         first_creation=FALSE;
  500.         for (i=1;i<=MAXGADGET;i++) 
  501.         {
  502.             gadlist[i].used=FALSE;            
  503.             /*gadlist[i].selected=FALSE;*/
  504.         }
  505.     }
  506.  
  507.     if (id < 1 || id > MAXGADGET || left > right || top > bottom ||
  508.         gadtype < 1 || gadtype > 5 || gadlist[id].used) return;
  509.  
  510.     /* store essential info' */
  511.     gadlist[id].used=TRUE;
  512.     gadlist[id].type=gadtype;
  513.     gadlist[id].style=gadstyle;
  514.  
  515.     /* create the gadget */
  516.     switch(gadtype)
  517.     {
  518.      /* boolean gadget */
  519.      case 1     : CreateBoolGadget(textstyle,fontsize,fontname,gadstyle,
  520.                     bottom,right,top,left,gadval,status,id);
  521.              break;    
  522.  
  523.      /* string or longint gadget */
  524.      case 2     : 
  525.      case 3  : CreateStringGadget(gadstyle,gadtype,bottom,right,top,left,
  526.                       gadval,status,id);
  527.              break;    
  528.  
  529.      /* horizontal or proportional gadget */
  530.      case 4     : 
  531.      case 5  : CreatePropGadget(gadstyle,gadtype,bottom,right,top,left,
  532.                     gadval,status,id);
  533.              break;    
  534.     }     
  535. }
  536.  
  537. void EraseGadget(id)
  538. ULONG id;
  539. {
  540. /* erase gadget */
  541. SHORT x1,y1,x2,y2;
  542. UBYTE FgPen;
  543.  
  544.     x1 = gadlist[id].bb_x1;
  545.     y1 = gadlist[id].bb_y1;
  546.     x2 = gadlist[id].bb_x2;
  547.     y2 = gadlist[id].bb_y2;
  548.  
  549.     /* erase gadget imagery */
  550.     FgPen = RPort->FgPen;
  551.     SetAPen(RPort,RPort->BgPen);
  552.     RectFill(RPort,x1,y1,x2,y2);
  553.     SetAPen(RPort,FgPen);
  554. }
  555.  
  556. void ChangeGadgetStatus(status,id)
  557. ULONG status,id;
  558. {
  559. ULONG x1,y1,x2,y2;
  560. /* change status of a gadget */
  561.  
  562.     if (id < 1 || id > MAXGADGET || !gadlist[id].used) return;
  563.  
  564.       /*
  565.     ** If not a string/longint gadget, remove gadget. Don't
  566.     ** want to modify the imagery of these 2 gadget types,
  567.     ** just their status. A disabled string/longint gadget
  568.     ** simply doesn't respond to mouse or keyboard actvity.
  569.     */
  570.     if (gadlist[id].type != 2 && 
  571.         gadlist[id].type != 3) RemoveGadget(Wdw,&gadlist[id].gad);
  572.  
  573.     /* enable or disable gadget */
  574.     switch(status)
  575.     {
  576.      /* disable */
  577.      case 0 : gadlist[id].gad.Flags |= GADGDISABLED;
  578.           break;
  579.  
  580.      /* enable */
  581.      case 1 : if (gadlist[id].gad.Flags & GADGDISABLED)
  582.           {
  583.                   gadlist[id].gad.Flags &= ~GADGDISABLED;
  584.  
  585.             /* remove old gadget imagery, if not string/longint. */
  586.             if (gadlist[id].type != 2 && 
  587.                     gadlist[id].type != 3) EraseGadget(id);
  588.           }
  589.           break;
  590.     }
  591.  
  592.     /* replace modified gadget (if not a string/longint gadget) */
  593.     if (gadlist[id].type != 2 && gadlist[id].type != 3)
  594.     {
  595.         AddGadget(Wdw,&gadlist[id].gad,(UWORD)id);
  596.         RefreshGList(&gadlist[id].gad,Wdw,NULL,1);
  597.     }
  598.  
  599.     /* redraw bevel-box? (if not a string/longint gadget) */
  600.     if (status == 1 && gadlist[id].type != 2 && gadlist[id].type != 3)
  601.     {
  602.         x1 = gadlist[id].bb_x1;
  603.         y1 = gadlist[id].bb_y1;
  604.         x2 = gadlist[id].bb_x2;
  605.         y2 = gadlist[id].bb_y2;
  606.  
  607.         switch(gadlist[id].type)
  608.         {
  609.              /* boolean gadget */
  610.             case 1 : if (gadlist[id].style != 3) 
  611.                     BevelBox(RAISED,y2,x2,y1,x1);
  612.                    break;
  613.  
  614.              /* horizontal or proportional gadget */
  615.             case 4 :
  616.             case 5 : BevelBox(RAISED,y2,x2,y1,x1);
  617.                    break;
  618.         }
  619.     }
  620. }
  621.  
  622. void modify_gad(notches,posn,id)
  623. LONG     notches;
  624. ULONG     posn,id;
  625. {
  626. /*
  627. ** Modify a (proportional) gadget.
  628. */
  629. ULONG     max_notches,vertbody,horizbody,vertpot,horizpot;
  630.  
  631.     /* sanity checks */
  632.  
  633.     if (id < 1 || id > MAXGADGET || !gadlist[id].used) return;
  634.  
  635.     if (gadlist[id].type != 4 && gadlist[id].type != 5) return;
  636.  
  637.     /* determine (new) maximum # of notches */
  638.     if (notches <= 0)
  639.         /* 0xFFFF DIV increment */
  640.         max_notches = 0xFFFF / gadlist[id].maxval;
  641.     else
  642.         max_notches = (ULONG)notches;
  643.  
  644.     /* is requested knob position off the scale? */
  645.     if (posn > max_notches)    return;
  646.  
  647.     /* store (new) info' about max. # of levels in slider */
  648.     gadlist[id].maxval = 0xFFFF / max_notches;
  649.  
  650.     /* calculate position and knob size */
  651.     switch(gadlist[id].type)
  652.     {
  653.         case 4 : horizpot  = posn * gadlist[id].maxval;
  654.              horizbody = gadlist[id].maxval;
  655.              vertpot   = gadlist[id].gadinfo.propinfo.VertPot;
  656.              vertbody  = gadlist[id].gadinfo.propinfo.VertBody;
  657.              break;
  658.  
  659.         case 5 : vertpot   = posn * gadlist[id].maxval;
  660.              vertbody  = gadlist[id].maxval;
  661.              horizpot  = gadlist[id].gadinfo.propinfo.HorizPot;
  662.              horizbody = gadlist[id].gadinfo.propinfo.HorizBody;
  663.              break;
  664.     }
  665.  
  666.     /* modify it! */
  667.     NewModifyProp(&gadlist[id].gad,Wdw,NULL,
  668.               gadlist[id].gadinfo.propinfo.Flags,
  669.               horizpot,vertpot,horizbody,vertbody,1);
  670. }
  671.  
  672. void CloseGadget(id)
  673. ULONG id;
  674. {
  675. /* close a gadget */
  676.  
  677.     if (id < 1 || id > MAXGADGET || !gadlist[id].used) return;
  678.  
  679.     gadlist[id].used=FALSE;
  680.     /*gadlist[id].selected=FALSE;*/
  681.  
  682.     /* free string gadget buffers */
  683.     if (gadlist[id].type == 2 || gadlist[id].type == 3) 
  684.     {
  685.       if (gadlist[id].gadinfo.stringinfo.Buffer)
  686.          FreeMem(gadlist[id].gadinfo.stringinfo.Buffer,
  687.              gadlist[id].maxval);
  688.  
  689.       if (gadlist[id].gadinfo.stringinfo.UndoBuffer)
  690.          FreeMem(gadlist[id].gadinfo.stringinfo.UndoBuffer,
  691.              gadlist[id].maxval);
  692.     }
  693.  
  694.     RemoveGadget(Wdw,&gadlist[id].gad);
  695.     EraseGadget(id);
  696. }
  697.  
  698. void SetCurrentGadget(id)
  699. ULONG id;
  700. {
  701. /*
  702. ** Set the current gadget so that information may
  703. ** be obtained about a gadget via the GADGET(n) 
  704. ** function at times other than when a gadget event 
  705. ** occurs. This only makes sense in conjunction with
  706. ** string, longint and slider gadgets (not buttons).
  707. */    
  708.     if (id < 1 || id > MAXGADGET || !gadlist[id].used) return;
  709.     
  710.     /* if (gadnum >= 1 && gadnum <= MAXGADGET) 
  711.              gadlist[gadnum].selected=FALSE;    necessary??? */
  712.  
  713.     gadnum = id;
  714. }
  715.  
  716. void WaitGadget(id)
  717. ULONG id;
  718. {
  719. /* wait on a specific gadget (id), or any gadget if id=0 */
  720. struct     IntuiMessage *message;
  721. struct    Gadget *GadPtr;
  722. USHORT    GadNum;
  723. ULONG    MsgClass;
  724.  
  725.     if (id < 0 || id > MAXGADGET || 
  726.        (id > 0 && !gadlist[id].used)) return;
  727.  
  728.     /* soak up pending messages first? ** MAY RESULT IN MESSAGE LOSS? **
  729.     while ((message = (struct IntuiMessage *)
  730.               GetMsg(Wdw->UserPort))) ReplyMsg(message); */
  731.  
  732.     do
  733.     {
  734.         /* await a message */
  735.         if ((message = (struct IntuiMessage *)
  736.                 GetMsg(Wdw->UserPort)) == NULL)
  737.         {
  738.             Wait(1L << Wdw->UserPort->mp_SigBit);
  739.             continue;
  740.         }
  741.  
  742.         /* extract info' about Intuition event */
  743.         MsgClass = message->Class;
  744.         GadPtr      = (struct Gadget *)message->IAddress;
  745.         if (MsgClass & GADGETUP) 
  746.            GadNum = GadPtr->GadgetID;
  747.         else
  748.            GadNum = 0;
  749.  
  750.         /* reply to message */
  751.         ReplyMsg(message);
  752.  
  753.         /* since GADGET WAITing will interfere with
  754.             ** CLOSEWINDOW messages, do we have one? 
  755.         */
  756.         if (MsgClass & CLOSEWINDOW) 
  757.         {
  758.             set_wdw_close_num();
  759.             gadnum = CLOSEGAD;
  760.             return;
  761.         }
  762.  
  763.         /* will any gadget do? */
  764.         if (id == 0 && (MsgClass & GADGETUP)) break; 
  765.     }
  766.     while (!(MsgClass & GADGETUP) || GadNum != id);
  767.  
  768.     /*gadlist[(ULONG)GadNum].selected = TRUE;*/
  769.     gadnum = (ULONG)GadNum;
  770. }
  771.  
  772. ULONG gadget_event_test()
  773. {
  774. /* test for the occurrence of a gadget event. */
  775. IntuiInfo *message;
  776. USHORT      GadNum;
  777. ULONG      MsgClass;
  778.  
  779.     /* attempt to get a message */
  780.     if ((message = GetIntuiEvent(Wdw->UserPort)) == NULL) return(0L);
  781.  
  782.     /* extract info' about Intuition event */
  783.     MsgClass = message->Class;
  784.     if (MsgClass & GADGETUP) 
  785.        GadNum = message->GadgetID;
  786.     else
  787.        GadNum = 0;
  788.  
  789.     /* message matched */
  790.     if (MsgClass & GADGETUP) ClearIntuiEvent(); 
  791.  
  792.     /* has a gadget been selected? */
  793.     if ((MsgClass & GADGETUP) && (GadNum >= 1 && GadNum <= MAXGADGET))
  794.     {
  795.             /*gadlist[(ULONG)GadNum].selected=TRUE;*/
  796.         gadnum = (ULONG)GadNum;
  797.         return(1L);
  798.     }
  799.     else
  800.         return(0L);
  801. }
  802.  
  803. ULONG GadFunc(n)
  804. ULONG n;
  805. {
  806. /* 
  807. ** Return information about the
  808. ** currently selected gadget after
  809. ** a gadget event or following a
  810. ** Gadget Output command.
  811. */
  812. ULONG  i;
  813. UBYTE  *s;
  814. USHORT p;
  815.  
  816.     switch(n)
  817.     {
  818.         /* has a gadget been selected since the 
  819.            last call to GadFunc(0)? */
  820.  
  821.         case 0 : if (gadget_event_test())
  822.                 return -1L;
  823.               else
  824.                 return 0L;
  825.  
  826.                /*for (i=1;i<=MAXGADGET;i++)
  827.                  if (gadlist[i].used && 
  828.                     gadlist[i].selected)
  829.                 {
  830.                     gadnum = i;
  831.                     gadlist[i].selected=FALSE;
  832.                     return(-1L);
  833.                 }
  834.  
  835.                 return(0L); */    /* none selected */
  836.  
  837.                 break;
  838.  
  839.  
  840.         /* return ID of last gadget selected */
  841.  
  842.         case 1 : /*if (gadnum >= 1 && gadnum <= MAXGADGET) 
  843.                 gadlist[gadnum].selected=FALSE;*/
  844.  
  845.              return(gadnum);
  846.              break;
  847.  
  848.  
  849.         /* return string or longint value from string gadget */
  850.  
  851.         case 2 : if (gadlist[gadnum].type != 2 &&
  852.                  gadlist[gadnum].type != 3)
  853.              return(0L);
  854.              else
  855.              switch(gadlist[gadnum].type)
  856.              {
  857.               case 2 : 
  858.                   s = gadlist[gadnum].gadinfo.stringinfo.Buffer;
  859.               return((ULONG)s);
  860.               break;
  861.  
  862.               case 3 : 
  863.               return(gadlist[gadnum].gadinfo.stringinfo.LongInt);
  864.               break;                 
  865.              }
  866.              break;
  867.  
  868.  
  869.         /* return horizontal or vertical slider position */
  870.  
  871.         case 3 : if (gadlist[gadnum].type != 4 &&
  872.                  gadlist[gadnum].type != 5)
  873.              return(0L);
  874.              else
  875.              {
  876.               switch(gadlist[gadnum].type)
  877.               {
  878.                  case 4 : 
  879.                  p=gadlist[gadnum].gadinfo.propinfo.HorizPot;
  880.                  break;
  881.  
  882.                  case 5 : 
  883.                  p=gadlist[gadnum].gadinfo.propinfo.VertPot;
  884.                  break;
  885.               }
  886.  
  887.               /* actual-knob-posn DIV knob-size */
  888.                   return((ULONG)(p / gadlist[gadnum].maxval));
  889.              }
  890.              break;
  891.  
  892.  
  893.         /* return address of currently selected gadget */
  894.  
  895.         case 4 : if (gadnum >= 1 && gadnum <= MAXGADGET)
  896.                 return (ULONG)&gadlist[gadnum].gad;
  897.              else
  898.                 return 0L;
  899.              break;
  900.  
  901.  
  902.         /* for any other argument to the GADGET function... */
  903.  
  904.         default : return 0L;
  905.               break;
  906.     }
  907. }
  908.