home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d832 / term.lha / Term / term-3.1-Source.lha / termGadTools.c < prev    next >
C/C++ Source or Header  |  1993-02-20  |  77KB  |  3,667 lines

  1. /*
  2. **    termGadTools.c
  3. **
  4. **    GadTools object management support routines
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10.     /* Some includes for starters. */
  11.  
  12. #include <intuition/intuition.h>
  13. #include <intuition/gadgetclass.h>
  14. #include <libraries/gadtools.h>
  15. #include <intuition/sghooks.h>
  16. #include <utility/tagitem.h>
  17. #include <exec/libraries.h>
  18. #include <exec/memory.h>
  19.  
  20. #include <clib/intuition_protos.h>
  21. /*#include <clib/gadtools_protos.h>*/
  22. #include <clib/diskfont_protos.h>
  23. #include <clib/graphics_protos.h>
  24. #include <clib/utility_protos.h>
  25. #include <clib/exec_protos.h>
  26.  
  27. #include <string.h>
  28. #include <stdarg.h>
  29.  
  30.     /* User interface definitions. */
  31.  
  32. #define SZLV_Display    1        /* Listview includes display */
  33. #define SZLV_String    2        /* Listview includes string */
  34.  
  35. #define FOLDER_KIND    42        /* Folder selection button. */
  36. #define FILE_KIND    43        /* File selection button. */
  37. #define PASSWORD_KIND    44        /* Password entry string gadget. */
  38.  
  39. #define SZ_Adjust    TAG_USER+1    /* Adjust object */
  40. #define SZ_AutoWidth    TAG_USER+2    /* Use default width? */
  41. #define SZ_AlignExtra    TAG_USER+3    /* Add extra space to top edge */
  42. #define SZ_NewColumn    TAG_USER+4    /* Start new column */
  43. #define SZ_Lines    TAG_USER+5    /* Number of lines in object */
  44. #define SZ_Chars    TAG_USER+6    /* Number of chars (width) in object */
  45. #define SZ_AlignLeft    TAG_USER+7    /* Align to left border */
  46. #define SZ_AlignRight    TAG_USER+8    /* Align to right border */
  47. #define SZ_AlignCentre    TAG_USER+9    /* Centre it */
  48. #define SZ_AlignBottom    TAG_USER+10    /* Align to window bottom */
  49. #define SZ_GroupCount    TAG_USER+11    /* Create a group with N objects */
  50. #define SZ_GroupNext    TAG_USER+12    /* Skip to next position */
  51. #define SZ_SaveX    TAG_USER+13    /* Place left to current object, don't touch the left edge position, though. */
  52. #define SZ_SaveY    TAG_USER+14    /* Place below current object, don't touch the top edge position, though. */
  53. #define SZ_UseLeft    TAG_USER+15    /* Use this coordinate as left edge. */
  54. #define SZ_UseTop    TAG_USER+16    /* Use this coordinate as top edge. */
  55. #define SZ_UseWidth    TAG_USER+17    /* Use this gadget width. */
  56. #define SZ_UseHeight    TAG_USER+18    /* Use this gadget height. */
  57. #define SZ_FullWidth    TAG_USER+19    /* Use full window width for gadget. */
  58. #define SZ_FullHeight    TAG_USER+20    /* Use full window height for gadget. */
  59. #define SZ_SmallSpace    TAG_USER+21    /* Provide small alignment space. */
  60. #define SZ_LeaveFolder    TAG_USER+22    /* Leave space for folder icon. */
  61. #define SZ_PlaceLeft    TAG_USER+23    /* Place left to current object, don't modify next object position. */
  62. #define SZ_PlaceBelow    TAG_USER+24    /* Place below current object, don't modify next object position. */
  63. #define SZ_InterHeight    TAG_USER+25    /* Use this inter-object space. */
  64.  
  65.     /* Box information types. */
  66.  
  67. enum    {    BOX_LEFT,BOX_TOP,BOX_WIDTH,BOX_HEIGHT };
  68.  
  69.     /* Use these macros if the corresponding functions are not available. */
  70.  
  71. extern ULONG            (* __regargs ReadAPen)(struct RastPort *RPort);
  72. extern ULONG            (* __regargs ReadBPen)(struct RastPort *RPort);
  73. extern ULONG            (* __regargs ReadDrMd)(struct RastPort *RPort);
  74.  
  75.     /* Image types */
  76.  
  77. enum    {    BUTTONIMAGE_FOLDER, BUTTONIMAGE_FILE };
  78.  
  79.     /* External data. */
  80.  
  81. extern struct Library        *GadToolsBase,
  82.                 *DiskfontBase;
  83. extern struct Gadget        *ActiveGadget;
  84. extern UBYTE             SharedBuffer[];
  85. extern struct TextAttr         UserFont;
  86. extern APTR             VisualInfo;
  87. extern LONG             InterWidth,
  88.                  InterHeight;
  89. extern struct Hook         CommandHook,
  90.                  PasswordHook;
  91. extern struct TextFont        *UserTextFont;
  92.  
  93.     /* This structure will help us to remember the current state of
  94.      * a GadTools object.
  95.      */
  96.  
  97. struct GadgetSupportInfo
  98. {
  99.     STRPTR                 Original,    /* Password string entry, original contents (for undo). */
  100.                      Buffer;    /* Password string entry, current contents. */
  101.  
  102.     struct GadgetSupportInfo    *PointBack;    /* Points back to itself. */
  103.     struct Gadget            *Gadget;    /* Points back to the host. */
  104.  
  105.     struct Image            *Image;        /* Folder images. */
  106.  
  107.     STRPTR                 Title;        /* New gadget title. */
  108.  
  109.     WORD                 Kind;        /* Item type (BUTTON_KIND, STRING_KIND, etc.) */
  110.     UBYTE                 Key;        /* The key to press. */
  111.     BYTE                 ReadOnly;    /* LISTVIEW_KIND only: is this a read-only object? */
  112.     LONG                 Current,    /* Current state or counter. */
  113.                      Min,        /* Minimum value for `Current'. */
  114.                      Max;        /* Maximum value for `Current'. */
  115.     UWORD                 Flags;        /* Miscellaneous flag values. */
  116. };
  117.  
  118.     /* A text box for several lines of text. */
  119.  
  120. struct TextBox
  121. {
  122.     struct TextBox    *NextBox;        /* Next box in chain. */
  123.  
  124.     LONG         Left,Top,        /* Position and size. */
  125.              Width,Height;
  126.  
  127.     LONG         LineWidth,        /* Line width in pixels. */
  128.              LineHeight;        /* Line height in pixels. */
  129.  
  130.     LONG         NumChars,        /* Number of chars per line. */
  131.              NumLines;        /* Number of lines. */
  132.  
  133.     STRPTR        *Title,            /* Line titles. */
  134.             *Text;            /* Line texts. */
  135.  
  136.     LONG         TitleFgPen,
  137.              TitleBgPen,
  138.              TextPen;
  139. };
  140.  
  141.     /* Our home-made tag items. */
  142.  
  143. STATIC Tag PrivateTags[] =
  144. {
  145.     SZ_Adjust,
  146.     SZ_AutoWidth,
  147.     SZ_AlignExtra,
  148.     SZ_NewColumn,
  149.     SZ_Lines,
  150.     SZ_Chars,
  151.     SZ_AlignLeft,
  152.     SZ_AlignRight,
  153.     SZ_AlignCentre,
  154.     SZ_AlignBottom,
  155.     SZ_GroupCount,
  156.     SZ_GroupNext,
  157.     SZ_SaveX,
  158.     SZ_SaveY,
  159.     SZ_UseLeft,
  160.     SZ_UseTop,
  161.     SZ_UseWidth,
  162.     SZ_UseHeight,
  163.     SZ_FullWidth,
  164.     SZ_FullHeight,
  165.     SZ_SmallSpace,
  166.     SZ_LeaveFolder,
  167.     SZ_PlaceLeft,
  168.     SZ_PlaceBelow,
  169.     SZ_InterHeight,
  170.  
  171.     TAG_DONE
  172. };
  173.  
  174.     /* Sizing data. */
  175.  
  176. STATIC struct RastPort    *SZ_RPort;
  177. STATIC struct TextFont    *SZ_TextFont;
  178. STATIC struct Screen    *SZ_Screen;
  179.  
  180. STATIC LONG         SZ_Left,
  181.              SZ_Top,
  182.              SZ_WindowWidth,
  183.              SZ_WindowHeight;
  184.              SZ_CurrentLeft,
  185.              SZ_CurrentTop,
  186.              SZ_CurrentWidth,
  187.              SZ_MaxWidth,
  188.              SZ_GroupDelta,
  189.              SZ_GroupX,
  190.              SZ_WidthMax,
  191.              SZ_TextPen,
  192.  
  193.              SZ_LastLeft,
  194.              SZ_LastTop,
  195.              SZ_LastWidth,
  196.              SZ_LastHeight;
  197.  
  198.     /* Dimensions of the font glyphs. */
  199.  
  200. STATIC ULONG         SZ_AverageGlyphWidth,    /* Average width. */
  201.              SZ_MaxGlyphWidth,    /* Maximum width. */
  202.              SZ_MaxNumericWidth;    /* Maximum numeral width. */
  203.  
  204.     /* AmigaGuide help. */
  205.  
  206. extern VOID            GuideSetup(VOID);
  207.  
  208.     /* Local routines. */
  209.  
  210. struct Gadget *            CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...);
  211. VOID                FreeGadgets(struct Gadget *GadgetList);
  212. VOID                GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...);
  213. VOID                GT_ReplyIMsg(struct IntuiMessage *Message);
  214.  
  215. VOID                KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *IClass,LONG *Code);
  216.  
  217.     /* Sizing routines. */
  218.  
  219. LONG                SZ_GetWindowWidth(VOID);
  220. LONG                SZ_GetWindowHeight(VOID);
  221. LONG                SZ_GetLeftEdge(VOID);
  222. LONG                SZ_GetTopEdge(VOID);
  223. VOID __regargs            SZ_SetTopEdge(LONG Top);
  224. VOID __regargs            SZ_SetLeftEdge(LONG Left);
  225. VOID __regargs            SZ_SetAbsoluteTop(LONG Top);
  226. VOID __regargs            SZ_SetAbsoluteLeft(LONG Left);
  227. VOID __regargs            SZ_SetWidth(LONG Width);
  228. VOID                SZ_InitWidth(VOID);
  229. LONG                SZ_ResetMaxWidth(VOID);
  230. VOID __regargs            SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
  231.  
  232. VOID __regargs            SZ_GetDimension(LONG *Width,LONG *Height);
  233. LONG __regargs            SZ_TextWidth(STRPTR String);
  234. VOID __regargs            SZ_AddLeftOffset(LONG Offset);
  235. LONG __stdargs            SZ_LeftOffsetN(LONG DataArray,...);
  236. LONG __regargs            SZ_LeftOffsetDelta(LONG From,LONG To);
  237. VOID                SZ_SizeCleanup(VOID);
  238. BYTE __regargs            SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title);
  239. ULONG __regargs            SZ_GetNumericLen(STRPTR String);
  240. ULONG __regargs            SZ_GetGlyphLen(STRPTR String);
  241. ULONG __regargs            SZ_GetLen(STRPTR String);
  242. LONG __regargs            SZ_Height(UBYTE Type,LONG Lines,BYTE Display);
  243. LONG __regargs            SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
  244.  
  245.     /* Text box routines. */
  246.  
  247. VOID __regargs            SZ_FreeBox(struct TextBox *Box);
  248. VOID __regargs            SZ_FreeBoxes(struct TextBox *FirstBox);
  249. LONG __regargs            SZ_BoxWidth(LONG Chars);
  250. LONG __regargs            SZ_BoxHeight(LONG Lines);
  251. VOID __regargs            SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen);
  252. struct TextBox * __stdargs    SZ_CreateTextBox(struct TextBox **FirstBox,...);
  253. VOID __stdargs            SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...);
  254. VOID __regargs            SZ_SetLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String);
  255. VOID __stdargs            SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...);
  256. VOID __regargs            SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box);
  257. VOID __regargs            SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox);
  258. VOID __regargs            SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top);
  259. VOID __regargs            SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top);
  260. VOID __regargs            SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top);
  261. VOID __regargs            SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top);
  262. LONG __regargs            SZ_GetBoxInfo(struct TextBox *Box,LONG Type);
  263.  
  264.     /* The original gadtools.library routines. */
  265.  
  266. struct Gadget *            OldCreateGadgetA(ULONG,struct Gadget *,struct NewGadget *,struct TagItem *);
  267. VOID                OldFreeGadgets(struct Gadget *);
  268. VOID                OldGT_SetGadgetAttrsA(struct Gadget *,struct Window *,struct Requester *,struct TagItem *);
  269. VOID                OldGT_ReplyIMsg(struct IntuiMessage *);
  270. VOID                DrawBevelBox(struct RastPort *,LONG,LONG,LONG,LONG,...);
  271.  
  272.     /* Pragma calls: the easy way. */
  273.  
  274. #pragma libcall GadToolsBase OldCreateGadgetA 1E A98004
  275. #pragma libcall GadToolsBase OldFreeGadgets 24 801
  276. #pragma libcall GadToolsBase OldGT_SetGadgetAttrsA 2A BA9804
  277. #pragma libcall GadToolsBase OldGT_ReplyIMsg 4E 901
  278.  
  279.     /* CreateButtonImages():
  280.      *
  281.      *    Create images for the folder and file buttons.
  282.      */
  283.  
  284. STATIC struct Image *
  285. CreateButtonImages(BYTE Type,UWORD Width,UWORD Height,struct Screen *Screen,APTR VisualInfo)
  286. {
  287.     struct Image *Image = NULL;
  288.  
  289.         /* Minimum size required. */
  290.  
  291.     if(Width >= 16 && Height >= 12)
  292.     {
  293.         struct RastPort    *RPort;
  294.  
  295.             /* Allocate local dummy rastport. */
  296.  
  297.         if(RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY))
  298.         {
  299.             struct BitMap    *BitMap[2] = { NULL, NULL };
  300.             BYTE         Success;
  301.             WORD         Depth,
  302.                      i,j;
  303.  
  304.                 /* Determine screen depth. */
  305.  
  306.             Depth = Screen -> RastPort . BitMap -> Depth;
  307.  
  308.                 /* Set up rastport. */
  309.  
  310.             InitRastPort(RPort);
  311.  
  312.                 /* Allocate bitmaps and bitplane data. */
  313.  
  314.             Success = TRUE;
  315.  
  316.             for(i = 0 ; Success && i < 2 ; i++)
  317.             {
  318.                 if(BitMap[i] = (struct BitMap *)AllocVec(sizeof(struct BitMap),MEMF_ANY))
  319.                 {
  320.                     InitBitMap(BitMap[i],Depth,Width,Height);
  321.  
  322.                     if(BitMap[i] -> Planes[0] = (PLANEPTR)AllocVec(BitMap[i] -> BytesPerRow * BitMap[i] -> Rows * BitMap[i] -> Depth,MEMF_CHIP | MEMF_CLEAR))
  323.                     {
  324.                         for(j = 1 ; j < Depth ; j++)
  325.                             BitMap[i] -> Planes[j] = BitMap[i] -> Planes[j - 1] + BitMap[i] -> BytesPerRow * BitMap[i] -> Rows;
  326.                     }
  327.                     else
  328.                         Success = FALSE;
  329.                 }
  330.                 else
  331.                     Success = FALSE;
  332.             }
  333.  
  334.                 /* Did we get what we wanted? */
  335.  
  336.             if(Success)
  337.             {
  338.                 struct DrawInfo *DrawInfo;
  339.  
  340.                     /* Get drawing pen information. */
  341.  
  342.                 if(DrawInfo = GetScreenDrawInfo(Screen))
  343.                 {
  344.                         /* Run-dump of the folder image. */
  345.  
  346.                     STATIC UWORD __chip FolderData[10] =
  347.                     {
  348.                         0x03C0,
  349.                         0x0420,
  350.                         0xF810,
  351.                         0xFC10,
  352.                         0xC3F0,
  353.                         0xC010,
  354.                         0xC010,
  355.                         0xC010,
  356.                         0xC010,
  357.                         0xFFF0
  358.                     };
  359.  
  360.                         /* Run-dump of the file image. */
  361.  
  362.                     STATIC UWORD __chip FileData[10] =
  363.                     {
  364.                                                 0xFF00,
  365.                                                 0xC180,
  366.                                                 0xC140,
  367.                                                 0xC120,
  368.                                                 0xC1F0,
  369.                                                 0xC030,
  370.                                                 0xC030,
  371.                                                 0xC030,
  372.                                                 0xC030,
  373.                                                 0xFFF0
  374.                     };
  375.  
  376.                     struct BitMap __aligned    FolderBitMap;
  377.                     WORD            Left,
  378.                                 Top;
  379.  
  380.                         /* Determine image offsets. */
  381.  
  382.                     Left    = (Width - 12) / 2;
  383.                     Top    = (Height - 10) / 2;
  384.  
  385.                         /* Set up the folder bitmap. */
  386.  
  387.                     InitBitMap(&FolderBitMap,Depth,12,10);
  388.  
  389.                         /* Put the mask into all bitplanes. */
  390.  
  391.                     if(Type == BUTTONIMAGE_FOLDER)
  392.                     {
  393.                         for(i = 0 ; i < Depth ; i++)
  394.                             FolderBitMap . Planes[i] = (PLANEPTR)FolderData;
  395.                     }
  396.                     else
  397.                     {
  398.                         for(i = 0 ; i < Depth ; i++)
  399.                             FolderBitMap . Planes[i] = (PLANEPTR)FileData;
  400.                     }
  401.  
  402.                         /* Manipulate the first bitmap. */
  403.  
  404.                     RPort -> BitMap = BitMap[0];
  405.  
  406.                         /* Clear the bitmap. */
  407.  
  408.                     SetRast(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  409.  
  410.                         /* Draw the button box. */
  411.  
  412.                     DrawBevelBox(RPort,0,0,Width,Height,
  413.                         GT_VisualInfo,    VisualInfo,
  414.                     TAG_DONE);
  415.  
  416.                         /* Clear the folder mask. */
  417.  
  418.                     BltBitMap(&FolderBitMap,0,0,BitMap[0],Left,Top,12,10,0x20,(1 << Depth) - 1,NULL);
  419.  
  420.                         /* Draw the folder mask. */
  421.  
  422.                     BltBitMap(&FolderBitMap,0,0,BitMap[0],Left,Top,12,10,0xE0,DrawInfo -> dri_Pens[TEXTPEN],NULL);
  423.  
  424.                         /* Are we to provide a selecte
  425.                          * image in the new look?
  426.                          */
  427.  
  428.                     if((DrawInfo -> dri_Flags & DRIF_NEWLOOK) && Depth > 1)
  429.                     {
  430.                             /* Manipulate the second bitmap. */
  431.  
  432.                         RPort -> BitMap = BitMap[1];
  433.  
  434.                             /* Set the bitmap to the
  435.                              * selected button colour.
  436.                              */
  437.  
  438.                         SetRast(RPort,DrawInfo -> dri_Pens[FILLPEN]);
  439.  
  440.                             /* Draw the selected button box. */
  441.  
  442.                         DrawBevelBox(RPort,0,0,Width,Height,
  443.                             GTBB_Recessed,    TRUE,
  444.                             GT_VisualInfo,    VisualInfo,
  445.                         TAG_DONE);
  446.  
  447.                             /* Clear the folder mask. */
  448.  
  449.                         BltBitMap(&FolderBitMap,0,0,BitMap[1],Left,Top,12,10,0x20,(1 << Depth) - 1,NULL);
  450.  
  451.                             /* Draw the folder mask. */
  452.  
  453.                         BltBitMap(&FolderBitMap,0,0,BitMap[1],Left,Top,12,10,0xE0,DrawInfo -> dri_Pens[FILLTEXTPEN],NULL);
  454.                     }
  455.                     else
  456.                     {
  457.                             /* Copy the image. */
  458.  
  459.                         BltBitMap(BitMap[0],0,0,BitMap[1],0,0,Width,Height,0xC0,(1 << Depth) - 1,NULL);
  460.  
  461.                             /* Invert the inner area. */
  462.  
  463.                         BltBitMap(BitMap[0],0,0,BitMap[1],2,1,Width - 4,Height - 2,0x50,(1 << Depth) - 1,NULL);
  464.                     }
  465.  
  466.                         /* Allocate space for standard image and selected image. */
  467.  
  468.                     if(Image = (struct Image *)AllocVec(2 * sizeof(struct Image),MEMF_ANY | MEMF_CLEAR))
  469.                     {
  470.                             /* Fill in the standard data. */
  471.  
  472.                         for(i = 0 ; i < 2 ; i++)
  473.                         {
  474.                             Image[i] . Width    = Width;
  475.                             Image[i] . Height    = Height;
  476.                             Image[i] . Depth    = Depth;
  477.                             Image[i] . ImageData    = (UWORD *)BitMap[i] -> Planes[0];
  478.                             Image[i] . PlanePick    = (1 << Depth) - 1;
  479.                         }
  480.                     }
  481.  
  482.                         /* Free the screen drawing pen information. */
  483.  
  484.                     FreeScreenDrawInfo(Screen,DrawInfo);
  485.                 }
  486.             }
  487.  
  488.                 /* Free the bitmaps, but not necessarily the
  489.                  * bitplane data.
  490.                  */
  491.  
  492.             for(i = 0 ; i < 2 ; i++)
  493.             {
  494.                 if(BitMap[i])
  495.                 {
  496.                     if(!Success)
  497.                         FreeVec(BitMap[i] -> Planes[0]);
  498.  
  499.                     FreeVec(BitMap[i]);
  500.                 }
  501.             }
  502.  
  503.                 /* Free the rastport. */
  504.  
  505.             FreeVec(RPort);
  506.         }
  507.     }
  508.  
  509.         /* Return the result. */
  510.  
  511.     return(Image);
  512. }
  513.  
  514.     /* NewTitle(STRPTR Original,LONG Len,LONG *MaxPixelLen,BYTE Create):
  515.      *
  516.      *    Prepare a new slider title, padding the label with spaces.
  517.      */
  518.  
  519. STATIC STRPTR __regargs
  520. NewTitle(STRPTR Original,LONG Len,LONG *MaxPixelLen,BYTE Create)
  521. {
  522.     register LONG i,TotalLen,NumSpaces = 0,Last;
  523.  
  524.         /* Determine length of title text. */
  525.  
  526.     TotalLen = Last = strlen(Original);
  527.  
  528.         /* Count the trailing spaces, look for the
  529.          * last character which is not a space.
  530.          */
  531.  
  532.     for(i = TotalLen - 1 ; i >= 0 ; i--)
  533.     {
  534.             /* Is this a space? */
  535.  
  536.         if(Original[i] == ' ')
  537.         {
  538.                 /* Increment number of spaces. */
  539.  
  540.             NumSpaces++;
  541.  
  542.                 /* Remember last space position. */
  543.  
  544.             Last = i;
  545.         }
  546.         else
  547.             break;
  548.     }
  549.  
  550.         /* No spaces? Return the defaults. */
  551.  
  552.     if(!Len && !NumSpaces)
  553.     {
  554.             /* Reset the information. */
  555.  
  556.         if(MaxPixelLen)
  557.             *MaxPixelLen = 0;
  558.  
  559.             /* Return original buffer. */
  560.  
  561.         return(Original);
  562.     }
  563.     else
  564.     {
  565.             /* If no length is given, use the
  566.              * values we have determined. */
  567.  
  568.         if(!Len)
  569.             Len = NumSpaces + 1;
  570.  
  571. /*        if(MaxPixelLen)
  572.             *MaxPixelLen = Len * SZ_MaxNumericWidth;*/
  573.  
  574.         NumSpaces = ((Len - 1) * SZ_MaxNumericWidth) / TextLength(SZ_RPort," ",1) + 1;
  575.  
  576.             /* Copy the body. */
  577.  
  578.         memcpy(SharedBuffer,Original,Last);
  579.  
  580.             /* Supply the spaces if any. */
  581.  
  582.         if(NumSpaces)
  583.             memset(SharedBuffer + Last,' ',NumSpaces);
  584.  
  585.             /* Provide null-termination. */
  586.  
  587.         SharedBuffer[Last + NumSpaces] = 0;
  588.  
  589.             /* Are we to allocate a buffer to
  590.              * hold the new label?
  591.              */
  592.  
  593.         if(Create)
  594.         {
  595.             STRPTR Buffer;
  596.  
  597.                 /* Allocate and copy the buffer. */
  598.  
  599.             if(Buffer = (STRPTR)AllocVec(Last + NumSpaces + 1,MEMF_ANY))
  600.                 strcpy(Buffer,SharedBuffer);
  601.  
  602.                 /* Return the result. */
  603.  
  604.             return(Buffer);
  605.         }
  606.         else
  607.             return(SharedBuffer);
  608.     }
  609. }
  610.  
  611.     /* CreateGadget():
  612.      *
  613.      *    A frontend to the original routine.
  614.      */
  615.  
  616. struct Gadget *
  617. CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...)
  618. {
  619.     STATIC struct NewGadget         Backup;
  620.  
  621.     va_list                 VarArgs;
  622.     struct TagItem            *TagList,
  623.                     *ThisTag,
  624.                      MoreTags[3];
  625.     struct GadgetSupportInfo    *Info = NULL;
  626.     WORD                 i;
  627.     struct Gadget            *Result;
  628.     UWORD                 Flags = NULL;
  629.     STRPTR                 NewGadgetTitle = NULL;
  630.     LONG                 MaxPixelLen = 0;
  631.  
  632.         /* Get the tag item array. */
  633.  
  634.     va_start(VarArgs,New);
  635.  
  636.         /* Make a backup copy of the original NewGadget structure,
  637.          * we may want to modify it.
  638.          */
  639.  
  640.     CopyMem(New,&Backup,sizeof(struct NewGadget));
  641.  
  642.     New = &Backup;
  643.  
  644.         /* Fill in the defaults if none are present. */
  645.  
  646.     if(!New -> ng_VisualInfo)
  647.         New -> ng_VisualInfo = VisualInfo;
  648.  
  649.     if(!New -> ng_TextAttr)
  650.         New -> ng_TextAttr = &UserFont;
  651.  
  652.         /* Get the tag item list. */
  653.  
  654.     TagList = (struct TagItem *)VarArgs;
  655.  
  656.         /* Is this a slider object? */
  657.  
  658.     if(Kind == SLIDER_KIND && New -> ng_GadgetText)
  659.     {
  660.             /* Is a special label width required? */
  661.  
  662.         if(ThisTag = FindTagItem(GTSL_MaxLevelLen,TagList))
  663.             NewGadgetTitle = NewTitle(New -> ng_GadgetText,ThisTag -> ti_Data + 1,&MaxPixelLen,TRUE);
  664.         else
  665.             NewGadgetTitle = NewTitle(New -> ng_GadgetText,0,&MaxPixelLen,TRUE);
  666.     }
  667.  
  668.         /* Try to find the SZ_Adjust tag item. If found, we are to
  669.          * apply our formatting functions to it.
  670.          */
  671.  
  672.     if(ThisTag = FindTagItem(SZ_Adjust,TagList))
  673.     {
  674.         if(ThisTag -> ti_Data)
  675.         {
  676.             LONG     Width,
  677.                  Height,
  678.                  AddHeight    = InterHeight,
  679.                  Left        = SZ_CurrentLeft,
  680.                  Top        = SZ_CurrentTop;
  681.             BYTE     AutoWidth    = FALSE,
  682.                  MoveDown    = TRUE,
  683.                  SaveWidth    = TRUE,
  684.                  SetLeft    = FALSE,
  685.                  SetBelow    = FALSE,
  686.                  DropLeft    = FALSE,
  687.                  DropTop    = FALSE;
  688.  
  689.                 /* Are we to leave the left edge untouched? */
  690.  
  691.             if(ThisTag = FindTagItem(SZ_SaveX,TagList))
  692.                 SetLeft = ThisTag -> ti_Data;
  693.  
  694.                 /* Are we to leave the top edge untouched? */
  695.  
  696.             if(ThisTag = FindTagItem(SZ_SaveY,TagList))
  697.                 SetBelow = ThisTag -> ti_Data;
  698.  
  699.                 /* Are we to use a special inter-object alignment size? */
  700.  
  701.             if(ThisTag = FindTagItem(SZ_InterHeight,TagList))
  702.                 AddHeight = ThisTag -> ti_Data;
  703.  
  704.                 /* Are we to place the new object to the left
  705.                  * of the previous object?
  706.                  */
  707.  
  708.             if(ThisTag = FindTagItem(SZ_PlaceLeft,TagList))
  709.             {
  710.                 if(ThisTag -> ti_Data)
  711.                 {
  712.                     Top        = SZ_LastTop;
  713.                     Left        = SZ_LastLeft + SZ_LastWidth + 2;
  714.  
  715.                     DropLeft    = TRUE;
  716.                     DropTop        = TRUE;
  717.                 }
  718.             }
  719.  
  720.                 /* Are we to place the new object below
  721.                  * the previous object?
  722.                  */
  723.  
  724.             if(ThisTag = FindTagItem(SZ_PlaceBelow,TagList))
  725.             {
  726.                 if(ThisTag -> ti_Data)
  727.                 {
  728.                     Top = SZ_LastTop + SZ_LastHeight + 1;
  729.  
  730.                     DropLeft = TRUE;
  731.                 }
  732.             }
  733.  
  734.                 /* Are we to align the object to the
  735.                  * window bottom?
  736.                  */
  737.  
  738.             if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
  739.             {
  740.                 if(ThisTag -> ti_Data)
  741.                     Top = SZ_WindowHeight;
  742.             }
  743.  
  744.                 /* Are we to add extra space to the
  745.                  * object top edge?
  746.                  */
  747.  
  748.             if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
  749.             {
  750.                 if(ThisTag -> ti_Data)
  751.                     Top += AddHeight;
  752.             }
  753.  
  754.                 /* Are we to start a new column? */
  755.  
  756.             if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
  757.             {
  758.                 if(ThisTag -> ti_Data)
  759.                 {
  760.                     Top        = SZ_Top;
  761.                     Left        = Left + SZ_MaxWidth;
  762.                     SZ_MaxWidth    = 0;
  763.  
  764.                     if(ThisTag = FindTagItem(SZ_SmallSpace,TagList))
  765.                     {
  766.                         if(ThisTag -> ti_Data)
  767.                             Left += 2;
  768.                         else
  769.                             Left += InterWidth;
  770.                     }
  771.                     else
  772.                         Left += InterWidth;
  773.                 }
  774.             }
  775.  
  776.                 /* Is the object to contain a certain
  777.                  * number of lines?
  778.                  */
  779.  
  780.             if(ThisTag = FindTagItem(SZ_Lines,TagList))
  781.             {
  782.                 LONG Lines = (LONG)ThisTag -> ti_Data;
  783.  
  784.                     /* Is it a listview object? */
  785.  
  786.                 if(Kind == LISTVIEW_KIND)
  787.                 {
  788.                         /* Determine height of object. */
  789.  
  790.                     if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
  791.                     {
  792.                         if(ThisTag -> ti_Data)
  793.                             Height = SZ_Height(Kind,Lines,SZLV_String);
  794.                         else
  795.                             Height = SZ_Height(Kind,Lines,SZLV_Display);
  796.                     }
  797.                     else
  798.                         Height = SZ_Height(Kind,Lines,NULL);
  799.                 }
  800.                 else
  801.                     Height = SZ_Height(Kind,Lines,NULL);
  802.             }
  803.             else
  804.             {
  805.                     /* If this is a MX kind object,
  806.                      * determine the number of lines
  807.                      * by looking at the labels.
  808.                      */
  809.  
  810.                 if(ThisTag = FindTagItem(GTMX_Labels,TagList))
  811.                 {
  812.                     STRPTR    *Choices;
  813.                     LONG     Lines = 0;
  814.  
  815.                     Choices = (STRPTR *)ThisTag -> ti_Data;
  816.  
  817.                     while(*Choices++)
  818.                         Lines++;
  819.  
  820.                     Height = SZ_Height(Kind,Lines,NULL);
  821.                 }
  822.                 else
  823.                     Height = SZ_Height(Kind,0,NULL);
  824.             }
  825.  
  826.                 /* Is the object width derived from
  827.                  * certain magical calculations or
  828.                  * is it as wide as the default width?
  829.                  */
  830.  
  831.             if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  832.                 AutoWidth = ThisTag -> ti_Data;
  833.  
  834.                 /* Determine the width of the object. */
  835.  
  836.             if(!AutoWidth)
  837.             {
  838.                 STRPTR    *Choices    = NULL,
  839.                      Title        = NULL;
  840.                 LONG     Chars        = 0;
  841.  
  842.                     /* Determine number of characters in
  843.                      * this object.
  844.                      */
  845.  
  846.                 if(ThisTag = FindTagItem(SZ_Chars,TagList))
  847.                     Chars = ThisTag -> ti_Data;
  848.  
  849.                     /* If this is a button object,
  850.                      * calculate the width by looking
  851.                      * at the title.
  852.                      */
  853.  
  854.                 if(Kind == BUTTON_KIND && New -> ng_GadgetText)
  855.                     Title = New -> ng_GadgetText;
  856.  
  857.                     /* If this is a cycle object,
  858.                      * take a look at the labels.
  859.                      */
  860.  
  861.                 if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  862.                     Choices = (STRPTR *)ThisTag -> ti_Data;
  863.  
  864.                     /* If this is a listview object,
  865.                      * take a look at the list.
  866.                      */
  867.  
  868.                 if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  869.                 {
  870.                     if(ThisTag -> ti_Data != ~0)
  871.                     {
  872.                         struct List    *List = (struct List *)ThisTag -> ti_Data;
  873.                         struct Node    *Node;
  874.                         LONG         Len;
  875.  
  876.                         Node = List -> lh_Head;
  877.  
  878.                         while(Node -> ln_Succ)
  879.                         {
  880.                             if((Len = strlen(Node -> ln_Name)) > Chars)
  881.                                 Chars = Len;
  882.  
  883.                             Node = Node -> ln_Succ;
  884.                         }
  885.                     }
  886.                 }
  887.  
  888.                     /* Determine object width. */
  889.  
  890.                 Width = SZ_Width(Kind,Title,Chars,Choices);
  891.             }
  892.             else
  893.             {
  894.                     /* Use the default width. */
  895.  
  896.                 Width = SZ_CurrentWidth;
  897.  
  898.                     /* A checkbox object has a
  899.                      * fixed width. We don't want
  900.                      * any other objects to share
  901.                      * it.
  902.                      */
  903.  
  904.                 if(Kind == CHECKBOX_KIND || Kind == FOLDER_KIND || Kind == FILE_KIND)
  905.                 {
  906.                     Width = SZ_Width(Kind,NULL,0,NULL);
  907.  
  908.                     SaveWidth = FALSE;
  909.                 }
  910.             }
  911.  
  912.                 /* Are we to align this object to
  913.                  * the left window edge?
  914.                  */
  915.  
  916.             if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
  917.             {
  918.                 if(ThisTag -> ti_Data)
  919.                 {
  920.                     Left = SZ_Left;
  921.  
  922.                     MoveDown = FALSE;
  923.                 }
  924.             }
  925.  
  926.                 /* Are we to use a specific object width? */
  927.  
  928.             if(ThisTag = FindTagItem(SZ_UseWidth,TagList))
  929.                 Width = ThisTag -> ti_Data;
  930.  
  931.                 /* Are we to use a specific object height? */
  932.  
  933.             if(ThisTag = FindTagItem(SZ_UseHeight,TagList))
  934.                 Height = ThisTag -> ti_Data;
  935.  
  936.                 /* Are we to align this object to the
  937.                  * right window edge?
  938.                  */
  939.  
  940.             if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
  941.             {
  942.                 if(ThisTag -> ti_Data)
  943.                 {
  944.                     Left = SZ_WindowWidth - INTERWIDTH - Width;
  945.  
  946.                     MoveDown = FALSE;
  947.                 }
  948.             }
  949.  
  950.                 /* Are we to centre the object in
  951.                  * the window?
  952.                  */
  953.  
  954.             if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
  955.             {
  956.                 if(ThisTag -> ti_Data)
  957.                 {
  958.                     Left = (SZ_WindowWidth - Width) / 2;
  959.  
  960.                     MoveDown = FALSE;
  961.                 }
  962.             }
  963.  
  964.                 /* Are we to build a horizontal group
  965.                  * using the following objects?
  966.                  */
  967.  
  968.             if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
  969.             {
  970.                 LONG    Count = ThisTag -> ti_Data,
  971.                     Width = SZ_WindowWidth;
  972.  
  973.                 if(!Width)
  974.                     Width = SZ_WindowWidth = SZ_Left + Count * (SZ_CurrentWidth + 2) + InterWidth;
  975.  
  976.                 if(!Top)
  977.                     Top = SZ_Top;
  978.  
  979.                     /* Use a specific left edge? */
  980.  
  981.                 if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  982.                 {
  983.                     Width -= ThisTag -> ti_Data - InterWidth;
  984.  
  985.                     SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  986.                     SZ_GroupX    = Left = ThisTag -> ti_Data;
  987.                 }
  988.                 else
  989.                 {
  990.                     SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  991.                     SZ_GroupX    = Left = SZ_Left;
  992.                 }
  993.  
  994.                 MoveDown = FALSE;
  995.             }
  996.             else
  997.             {
  998.                 if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  999.                     Left = ThisTag -> ti_Data;
  1000.             }
  1001.  
  1002.                 /* Skip to the next group item position? */
  1003.  
  1004.             if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
  1005.             {
  1006.                 if(ThisTag -> ti_Data)
  1007.                 {
  1008.                     SZ_GroupX += SZ_GroupDelta;
  1009.  
  1010.                     Left = SZ_GroupX;
  1011.  
  1012.                     MoveDown = FALSE;
  1013.                 }
  1014.             }
  1015.  
  1016.                 /* Determine default label placement. */
  1017.  
  1018.             switch(Kind)
  1019.             {
  1020.                 case MX_KIND:
  1021.                 case CHECKBOX_KIND:
  1022.  
  1023.                     New -> ng_Flags    = (New -> ng_Flags & ~(PLACETEXT_LEFT|PLACETEXT_RIGHT|PLACETEXT_ABOVE|PLACETEXT_BELOW|PLACETEXT_IN)) | PLACETEXT_LEFT;
  1024.  
  1025.                     SaveWidth = FALSE;
  1026.  
  1027.                     break;
  1028.  
  1029.                 default:
  1030.  
  1031.                     if(New -> ng_Flags & PLACETEXT_ABOVE)
  1032.                         Top += INTERHEIGHT + SZ_TextFont -> tf_YSize;
  1033.  
  1034.                     break;
  1035.             }
  1036.  
  1037.                 /* Use a specific top edge? */
  1038.  
  1039.             if(ThisTag = FindTagItem(SZ_UseTop,TagList))
  1040.                 Top = ThisTag -> ti_Data;
  1041.  
  1042.                 /* Gadget is to be as wide as the entire window? */
  1043.  
  1044.             if(ThisTag = FindTagItem(SZ_FullWidth,TagList))
  1045.             {
  1046.                 if(ThisTag -> ti_Data)
  1047.                     Width = SZ_WindowWidth - (InterWidth + Left);
  1048.             }
  1049.  
  1050.                 /* Gadget is to be as high as the entire window? */
  1051.  
  1052.             if(ThisTag = FindTagItem(SZ_FullHeight,TagList))
  1053.             {
  1054.                 if(ThisTag -> ti_Data)
  1055.                     Height = SZ_WindowHeight - (AddHeight + SZ_Top + Top);
  1056.             }
  1057.  
  1058.                 /* Leave space for folder icon? */
  1059.  
  1060.             if(ThisTag = FindTagItem(SZ_LeaveFolder,TagList))
  1061.             {
  1062.                 if(ThisTag -> ti_Data && (Kind == STRING_KIND || Kind == PASSWORD_KIND))
  1063.                     New -> ng_Width = Width - (2 + SZ_Width(FOLDER_KIND,"",0,0));
  1064.                 else
  1065.                     New -> ng_Width = Width;
  1066.             }
  1067.             else
  1068.                 New -> ng_Width = Width;
  1069.  
  1070.                 /* Fill in the NewGadget. */
  1071.  
  1072.             New -> ng_LeftEdge    = Left;
  1073.             New -> ng_TopEdge    = Top;
  1074.             New -> ng_Height    = Height;
  1075.  
  1076.                 /* Add the default tags. */
  1077.  
  1078.             switch(Kind)
  1079.             {
  1080. /*                case SLIDER_KIND:
  1081.  
  1082.                     MoreTags[0] . ti_Tag    = GTSL_MaxPixelLen;
  1083.                     MoreTags[0] . ti_Data    = MaxPixelLen;
  1084.  
  1085.                     MoreTags[1] . ti_Tag    = GTSL_Justification;
  1086.                     MoreTags[1] . ti_Data    = GTJ_RIGHT;
  1087.  
  1088.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1089.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1090.  
  1091.                     if(MaxPixelLen)
  1092.                         TagList = MoreTags;
  1093.                     else
  1094.                         TagList = MoreTags + 1;
  1095.  
  1096.                     break;*/
  1097.  
  1098.                 case PALETTE_KIND:
  1099.  
  1100.                     MoreTags[0] . ti_Tag    = GTPA_IndicatorWidth;
  1101.                     MoreTags[0] . ti_Data    = Width / 4;
  1102.  
  1103.                     MoreTags[1] . ti_Tag    = GTPA_IndicatorHeight;
  1104.                     MoreTags[1] . ti_Data    = Height;
  1105.  
  1106.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1107.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1108.  
  1109.                     TagList = MoreTags;
  1110.  
  1111.                     break;
  1112.  
  1113.                 case LISTVIEW_KIND:
  1114.  
  1115.                     MoreTags[0] . ti_Tag    = GTLV_ScrollWidth;
  1116.                     MoreTags[0] . ti_Data    = 2 + 2 * SZ_AverageGlyphWidth + 2;
  1117.  
  1118.                     MoreTags[1] . ti_Tag    = TAG_MORE;
  1119.                     MoreTags[1] . ti_Data    = (ULONG)TagList;
  1120.  
  1121.                     TagList = MoreTags;
  1122.  
  1123.                     break;
  1124.  
  1125.                 case CHECKBOX_KIND:
  1126.  
  1127.                     MoreTags[0] . ti_Tag    = GTCB_Scaled;
  1128.                     MoreTags[0] . ti_Data    = TRUE;
  1129.  
  1130.                     MoreTags[1] . ti_Tag    = TAG_MORE;
  1131.                     MoreTags[1] . ti_Data    = (ULONG)TagList;
  1132.  
  1133.                     TagList = MoreTags;
  1134.  
  1135.                     break;
  1136.  
  1137.                 case MX_KIND:
  1138.  
  1139.                     MoreTags[0] . ti_Tag    = GTMX_Scaled;
  1140.                     MoreTags[0] . ti_Data    = TRUE;
  1141.  
  1142.                     MoreTags[1] . ti_Tag    = TAG_MORE;
  1143.                     MoreTags[1] . ti_Data    = (ULONG)TagList;
  1144.  
  1145.                     TagList = MoreTags;
  1146.  
  1147.                     break;
  1148.  
  1149.                 case STRING_KIND:
  1150.  
  1151.                     MoreTags[0] . ti_Tag    = GTST_EditHook;
  1152.                     MoreTags[0] . ti_Data    = (ULONG)&CommandHook;
  1153.  
  1154.                     MoreTags[1] . ti_Tag    = GA_Immediate;
  1155.                     MoreTags[1] . ti_Data    = TRUE;
  1156.  
  1157.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1158.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1159.  
  1160.                     if(!FindTagItem(GTST_EditHook,TagList))
  1161.                         TagList = MoreTags;
  1162.                     else
  1163.                         TagList = MoreTags + 1;
  1164.  
  1165.                     break;
  1166.  
  1167.                 case PASSWORD_KIND:
  1168.  
  1169.                     MoreTags[0] . ti_Tag    = GTST_EditHook;
  1170.                     MoreTags[0] . ti_Data    = (ULONG)&PasswordHook;
  1171.  
  1172.                     MoreTags[1] . ti_Tag    = GA_Immediate;
  1173.                     MoreTags[1] . ti_Data    = TRUE;
  1174.  
  1175.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1176.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1177.  
  1178.                     TagList = MoreTags;
  1179.                     break;
  1180.  
  1181.                 case INTEGER_KIND:
  1182.  
  1183.                     MoreTags[0] . ti_Tag    = GTIN_EditHook;
  1184.                     MoreTags[0] . ti_Data    = (ULONG)&CommandHook;
  1185.  
  1186.                     MoreTags[1] . ti_Tag    = GA_Immediate;
  1187.                     MoreTags[1] . ti_Data    = TRUE;
  1188.  
  1189.                     MoreTags[2] . ti_Tag    = TAG_MORE;
  1190.                     MoreTags[2] . ti_Data    = (ULONG)TagList;
  1191.  
  1192.                     if(!FindTagItem(GTIN_EditHook,TagList))
  1193.                         TagList = MoreTags;
  1194.                     else
  1195.                         TagList = MoreTags + 1;
  1196.  
  1197.                     break;
  1198.  
  1199.                 case FILE_KIND:
  1200.                 case FOLDER_KIND:
  1201.  
  1202.                     New -> ng_GadgetText = "";
  1203.                     break;
  1204.             }
  1205.  
  1206.                 /* Restore default object width if necessary. */
  1207.  
  1208.             if(SaveWidth)
  1209.                 SZ_CurrentWidth    = Width;
  1210.  
  1211.             if(!DropTop)
  1212.             {
  1213.                     /* Are we to leave the top edge untouched? */
  1214.  
  1215.                 if(SetBelow)
  1216.                 {
  1217.                         /* Extend window height if necessary. */
  1218.  
  1219.                     if(Top + Height + AddHeight > SZ_WindowHeight)
  1220.                         SZ_WindowHeight = Top + Height + AddHeight;
  1221.                 }
  1222.                 else
  1223.                 {
  1224.                     SZ_CurrentTop = Top;
  1225.  
  1226.                     if(MoveDown)
  1227.                     {
  1228.                             /* Move down to next object. */
  1229.  
  1230.                         SZ_CurrentTop = SZ_CurrentTop + Height + AddHeight;
  1231.  
  1232.                             /* Extend window height if necessary. */
  1233.  
  1234.                         if(SZ_CurrentTop > SZ_WindowHeight)
  1235.                             SZ_WindowHeight = SZ_CurrentTop;
  1236.                     }
  1237.                     else
  1238.                     {
  1239.                             /* Extend window height if necessary. */
  1240.  
  1241.                         if(SZ_CurrentTop + Height + AddHeight > SZ_WindowHeight)
  1242.                             SZ_WindowHeight = SZ_CurrentTop + Height + AddHeight;
  1243.  
  1244.                         SZ_MaxWidth = 0;
  1245.                     }
  1246.                 }
  1247.             }
  1248.  
  1249.             if(!DropLeft)
  1250.             {
  1251.                     /* Update maximum object width. */
  1252.  
  1253.                 if(Width > SZ_MaxWidth)
  1254.                     SZ_MaxWidth = Width;
  1255.  
  1256.                     /* Extend window width if necessary. */
  1257.  
  1258.                 if(Left + SZ_MaxWidth + InterWidth > SZ_WindowWidth)
  1259.                     SZ_WindowWidth = Left + SZ_MaxWidth + InterWidth;
  1260.  
  1261.                     /* Are we to leave the left edge untouched? */
  1262.  
  1263.                 if(!SetLeft)
  1264.                     SZ_CurrentLeft = Left;
  1265.             }
  1266.  
  1267.                 /* Remember last object position and size. */
  1268.  
  1269.             SZ_LastLeft    = New -> ng_LeftEdge;
  1270.             SZ_LastWidth    = New -> ng_Width;
  1271.             SZ_LastHeight    = New -> ng_Height;
  1272.  
  1273.             if(New -> ng_Flags & PLACETEXT_ABOVE)
  1274.                 SZ_LastTop = New -> ng_TopEdge - (INTERHEIGHT + SZ_TextFont -> tf_YSize);
  1275.             else
  1276.                 SZ_LastTop = New -> ng_TopEdge;
  1277.         }
  1278.     }
  1279.  
  1280.         /* Now for keystroke activation... */
  1281.  
  1282.     switch(Kind)
  1283.     {
  1284.         case STRING_KIND:
  1285.         case INTEGER_KIND:
  1286.         case BUTTON_KIND:
  1287.         case CHECKBOX_KIND:
  1288.         case CYCLE_KIND:
  1289.         case LISTVIEW_KIND:
  1290.         case MX_KIND:
  1291.         case PALETTE_KIND:
  1292.         case SCROLLER_KIND:
  1293.         case SLIDER_KIND:
  1294.         case PASSWORD_KIND:
  1295.  
  1296.                 /* Do we have a gadget label? */
  1297.  
  1298.             if(New -> ng_GadgetText)
  1299.             {
  1300.                     /* Look for the underscore
  1301.                      * character...
  1302.                      */
  1303.  
  1304.                 for(i = 0 ; i < strlen(New -> ng_GadgetText) ; i++)
  1305.                 {
  1306.                     if(New -> ng_GadgetText[i] == '_')
  1307.                     {
  1308.                             /* Is it a printable character? */
  1309.  
  1310.                         if((WORD)(New -> ng_GadgetText[i + 1]) > ' ')
  1311.                         {
  1312.                                 /* Create information buffer. */
  1313.  
  1314.                             if(Info = (struct GadgetSupportInfo *)AllocMem(sizeof(struct GadgetSupportInfo),MEMF_ANY|MEMF_CLEAR))
  1315.                             {
  1316.                                 STATIC struct TagItem EvenMoreTags[2];
  1317.  
  1318.                                 EvenMoreTags[0] . ti_Tag    = GT_Underscore;
  1319.                                 EvenMoreTags[0] . ti_Data    = '_';
  1320.  
  1321.                                 EvenMoreTags[1] . ti_Tag    = TAG_MORE;
  1322.                                 EvenMoreTags[1] . ti_Data    = (ULONG)TagList;
  1323.  
  1324.                                 TagList = EvenMoreTags;
  1325.  
  1326.                                     /* Set up the default data. */
  1327.  
  1328.                                 Info -> PointBack    = Info;
  1329.                                 Info -> Kind        = Kind;
  1330.                                 Info -> Key        = New -> ng_GadgetText[i + 1];
  1331.  
  1332.                                     /* Add object-specific information. */
  1333.  
  1334.                                 if(Info -> Kind == PALETTE_KIND)
  1335.                                 {
  1336.                                     Info -> Current    = 1;
  1337.                                     Info -> Max    = 1;
  1338.                                 }
  1339.  
  1340.                                 if(Info -> Kind == LISTVIEW_KIND)
  1341.                                     Info -> Current    = ~0;
  1342.  
  1343.                                 break;
  1344.                             }
  1345.                         }
  1346.                     }
  1347.                 }
  1348.             }
  1349.  
  1350.             break;
  1351.  
  1352.         default:
  1353.  
  1354.             break;
  1355.     }
  1356.  
  1357.         /* No GadgetInfo supplied yet? Does this object need any? */
  1358.  
  1359.     if(!Info && (Kind == PASSWORD_KIND || Kind == FILE_KIND || Kind == FOLDER_KIND || Flags || NewGadgetTitle))
  1360.     {
  1361.             /* Allocate GadgetInfo. */
  1362.  
  1363.         if(Info = (struct GadgetSupportInfo *)AllocMem(sizeof(struct GadgetSupportInfo),MEMF_ANY|MEMF_CLEAR))
  1364.         {
  1365.             Info -> PointBack    = Info;
  1366.             Info -> Kind        = Kind;
  1367.         }
  1368.     }
  1369.  
  1370.         /* Fill in object info if available. */
  1371.  
  1372.     New -> ng_UserData = Info;
  1373.  
  1374.         /* Fill in the new title if available. */
  1375.  
  1376.     if(NewGadgetTitle)
  1377.         New -> ng_GadgetText = NewGadgetTitle;
  1378.  
  1379.         /* Did we create any object info? */
  1380.  
  1381.     if(Info)
  1382.     {
  1383.         struct Node    *Node;
  1384.         struct List    *List;
  1385.         LONG         Count;
  1386.         STRPTR        *Strings;
  1387.         struct TagItem    *NewTagList;
  1388.  
  1389.             /* The following code takes care of object-specific
  1390.              * characteristics, such as currently selected items,
  1391.              * current value, minimum value, maximum value, etc.
  1392.              * and places them in the gadget info.
  1393.              */
  1394.  
  1395.         switch(Kind)
  1396.         {
  1397.             case CHECKBOX_KIND:
  1398.  
  1399.                 if(ThisTag = FindTagItem(GTCB_Checked,TagList))
  1400.                     Info -> Current = ThisTag -> ti_Data;
  1401.  
  1402.                 break;
  1403.  
  1404.             case CYCLE_KIND:
  1405.  
  1406.                 if(ThisTag = FindTagItem(GTCY_Active,TagList))
  1407.                     Info -> Current = ThisTag -> ti_Data;
  1408.  
  1409.                 if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  1410.                 {
  1411.                     Count = 0;
  1412.  
  1413.                     if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1414.                     {
  1415.                         while(Strings[Count])
  1416.                             Count++;
  1417.                     }
  1418.  
  1419.                     if(Count)
  1420.                         Info -> Max = Count - 1;
  1421.                 }
  1422.  
  1423.                 break;
  1424.  
  1425.             case LISTVIEW_KIND:
  1426.  
  1427.                 if(ThisTag = FindTagItem(GTLV_Selected,TagList))
  1428.                     Info -> Current = ThisTag -> ti_Data;
  1429.  
  1430.                 if(ThisTag = FindTagItem(GTLV_ReadOnly,TagList))
  1431.                 {
  1432.                     if(ThisTag -> ti_Data)
  1433.                         Info -> ReadOnly = TRUE;
  1434.                 }
  1435.  
  1436.                 if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
  1437.                 {
  1438.                     if(ThisTag -> ti_Data)
  1439.                         Info -> ReadOnly = FALSE;
  1440.                 }
  1441.  
  1442.                 if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  1443.                 {
  1444.                     Count = 0;
  1445.  
  1446.                     if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
  1447.                     {
  1448.                         List = (struct List *)ThisTag -> ti_Data;
  1449.  
  1450.                         Node = List -> lh_Head;
  1451.  
  1452.                         while(Node -> ln_Succ)
  1453.                         {
  1454.                             Count++;
  1455.  
  1456.                             Node = Node -> ln_Succ;
  1457.                         }
  1458.                     }
  1459.  
  1460.                     if(Count)
  1461.                         Info -> Max = Count - 1;
  1462.                 }
  1463.  
  1464.                 break;
  1465.  
  1466.             case MX_KIND:
  1467.  
  1468.                 if(ThisTag = FindTagItem(GTMX_Active,TagList))
  1469.                     Info -> Current = ThisTag -> ti_Data;
  1470.  
  1471.                 if(ThisTag = FindTagItem(GTMX_Labels,TagList))
  1472.                 {
  1473.                     Count = 0;
  1474.  
  1475.                     if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1476.                     {
  1477.                         while(Strings[Count])
  1478.                             Count++;
  1479.                     }
  1480.  
  1481.                     if(Count)
  1482.                         Info -> Max = Count - 1;
  1483.                 }
  1484.  
  1485.                 break;
  1486.  
  1487.             case SCROLLER_KIND:
  1488.  
  1489.                 if(ThisTag = FindTagItem(GTSC_Top,TagList))
  1490.                     Info -> Current = ThisTag -> ti_Data;
  1491.  
  1492.                 if(ThisTag = FindTagItem(GTSC_Total,TagList))
  1493.                     Info -> Max = ThisTag -> ti_Data;
  1494.  
  1495.                 break;
  1496.  
  1497.             case SLIDER_KIND:
  1498.  
  1499.                 if(ThisTag = FindTagItem(GTSL_Level,TagList))
  1500.                     Info -> Current = ThisTag -> ti_Data;
  1501.  
  1502.                 if(ThisTag = FindTagItem(GTSL_Min,TagList))
  1503.                     Info -> Min = ThisTag -> ti_Data;
  1504.  
  1505.                 if(ThisTag = FindTagItem(GTSL_Max,TagList))
  1506.                     Info -> Max = ThisTag -> ti_Data;
  1507.  
  1508.                 break;
  1509.  
  1510.             case PALETTE_KIND:
  1511.  
  1512.                 if(ThisTag = FindTagItem(GTPA_Color,TagList))
  1513.                     Info -> Current = ThisTag -> ti_Data;
  1514.  
  1515.                 if(ThisTag = FindTagItem(GTPA_Depth,TagList))
  1516.                     Info -> Max = (1 << ((LONG)ThisTag -> ti_Data)) - 1;
  1517.  
  1518.                 break;
  1519.         }
  1520.  
  1521.             /* In order to avoid collisions with system software tags,
  1522.              * we will clone the current tag item list and filter
  1523.              * our private tags out before surrendering it to
  1524.              * CreateGadget().
  1525.              */
  1526.  
  1527.         if(NewTagList = CloneTagItems(TagList))
  1528.         {
  1529.                 /* Remove the private tags. */
  1530.  
  1531.             FilterTagItems(NewTagList,PrivateTags,TAGFILTER_NOT);
  1532.  
  1533.                 /* Are we to create a custom button object? */
  1534.  
  1535.             if(Kind == FOLDER_KIND || Kind == FILE_KIND)
  1536.             {
  1537.                 BYTE Type;
  1538.  
  1539.                     /* Which kind of object are we to create? */
  1540.  
  1541.                 if(Kind == FOLDER_KIND)
  1542.                     Type = BUTTONIMAGE_FOLDER;
  1543.                 else
  1544.                     Type = BUTTONIMAGE_FILE;
  1545.  
  1546.                     /* Create the images. */
  1547.  
  1548.                 if(Info -> Image = CreateButtonImages(Type,New -> ng_Width,New -> ng_Height,SZ_Screen,VisualInfo))
  1549.                 {
  1550.                         /* Create the object and attach the info to it. */
  1551.  
  1552.                     if(Result = OldCreateGadgetA(GENERIC_KIND,Previous,New,NewTagList))
  1553.                     {
  1554.                         Result -> GadgetType    |= GTYP_BOOLGADGET;
  1555.                         Result -> GadgetRender     = &Info -> Image[0];
  1556.                         Result -> SelectRender     = &Info -> Image[1];
  1557.                         Result -> Flags        |= GFLG_GADGHIMAGE | GFLG_GADGIMAGE;
  1558.                         Result -> Activation    |= GACT_RELVERIFY;
  1559.                     }
  1560.                 }
  1561.                 else
  1562.                     Result = NULL;
  1563.             }
  1564.             else
  1565.             {
  1566.                     /* Are we to create a password entry string gadget? */
  1567.  
  1568.                 if(Kind == PASSWORD_KIND)
  1569.                 {
  1570.                     LONG MaxChars = 0;
  1571.  
  1572.                         /* Determine number of characters
  1573.                          * the gadget is to hold.
  1574.                          */
  1575.  
  1576.                     if(ThisTag = FindTagItem(GTST_MaxChars,NewTagList))
  1577.                         MaxChars = ThisTag -> ti_Data;
  1578.  
  1579.                         /* Any size set? */
  1580.  
  1581.                     if(MaxChars)
  1582.                     {
  1583.                             /* Allocate the auxilary buffers. */
  1584.  
  1585.                         if(Info -> Original = (STRPTR)AllocVec((MaxChars + 2) * 2,MEMF_PUBLIC|MEMF_CLEAR))
  1586.                         {
  1587.                                 /* Set up the text entry buffer. */
  1588.  
  1589.                             Info -> Buffer = Info -> Original + (MaxChars + 2);
  1590.  
  1591.                                 /* If available find the original
  1592.                                  * string this gadget is to be
  1593.                                  * preset with.
  1594.                                  */
  1595.  
  1596.                             if(ThisTag = FindTagItem(GTST_String,NewTagList))
  1597.                             {
  1598.                                 LONG Len;
  1599.  
  1600.                                     /* Remember the original data. */
  1601.  
  1602.                                 strcpy(Info -> Buffer, (STRPTR)ThisTag -> ti_Data);
  1603.                                 strcpy(Info -> Original,(STRPTR)ThisTag -> ti_Data);
  1604.  
  1605.                                     /* Determine length of the original text. */
  1606.  
  1607.                                 Len = strlen(Info -> Original);
  1608.  
  1609.                                     /* Provide fake input. */
  1610.  
  1611.                                 memset(SharedBuffer,'*',Len);
  1612.  
  1613.                                 SharedBuffer[Len] = 0;
  1614.  
  1615.                                     /* This is our own private tag item
  1616.                                      * list, so why bother.
  1617.                                      */
  1618.  
  1619.                                 ThisTag -> ti_Data = (ULONG)SharedBuffer;
  1620.                             }
  1621.  
  1622.                             Result = OldCreateGadgetA(STRING_KIND,Previous,New,NewTagList);
  1623.                         }
  1624.                         else
  1625.                             Result = NULL;
  1626.                     }
  1627.                     else
  1628.                         Result = NULL;
  1629.                 }
  1630.                 else
  1631.                 {
  1632.                         /* Create the object and attach the info to it. */
  1633.  
  1634.                     Result = OldCreateGadgetA(Kind,Previous,New,NewTagList);
  1635.                 }
  1636.             }
  1637.  
  1638.                 /* Successful? */
  1639.  
  1640.             if(Result)
  1641.             {
  1642.                     /* Fill in the data. */
  1643.  
  1644.                 Info -> Gadget    = Result;
  1645.                 Info -> Flags    = Flags;
  1646.                 Info -> Title    = NewGadgetTitle;
  1647.             }
  1648.             else
  1649.             {
  1650.                     /* Free the images. */
  1651.  
  1652.                 if(Info -> Image && (Info -> Kind == FOLDER_KIND || Info -> Kind == FILE_KIND))
  1653.                 {
  1654.                     WORD i;
  1655.  
  1656.                     for(i = 0 ; i < 2 ; i++)
  1657.                         FreeVec(Info -> Image[i] . ImageData);
  1658.  
  1659.                     FreeVec(Info -> Image);
  1660.                 }
  1661.  
  1662.                     /* Free the password gadget buffers. */
  1663.  
  1664.                 if(Info -> Original && Info -> Kind == PASSWORD_KIND)
  1665.                     FreeVec(Info -> Original);
  1666.  
  1667.                     /* Free alternative gadget label. */
  1668.  
  1669.                 if(NewGadgetTitle)
  1670.                     FreeVec(NewGadgetTitle);
  1671.  
  1672.                     /* Free the info buffer itself. */
  1673.  
  1674.                 FreeMem(Info,sizeof(struct GadgetSupportInfo));
  1675.             }
  1676.  
  1677.                 /* Free the private tag item list. */
  1678.  
  1679.             FreeTagItems(NewTagList);
  1680.         }
  1681.         else
  1682.         {
  1683.                 /* Free alternative gadget label. */
  1684.  
  1685.             if(NewGadgetTitle)
  1686.                 FreeVec(NewGadgetTitle);
  1687.  
  1688.                 /* Free the info buffer itself. */
  1689.  
  1690.             FreeMem(Info,sizeof(struct GadgetSupportInfo));
  1691.  
  1692.             Result = NULL;
  1693.         }
  1694.     }
  1695.     else
  1696.     {
  1697.             /* No private objects, please. */
  1698.  
  1699.         if(Kind == FOLDER_KIND || Kind == FILE_KIND || Kind == PASSWORD_KIND)
  1700.             Result = NULL;
  1701.         else
  1702.         {
  1703.             struct TagItem *NewTagList;
  1704.  
  1705.                 /* Copy the tag item list. */
  1706.  
  1707.             if(NewTagList = CloneTagItems(TagList))
  1708.             {
  1709.                     /* Filter out the private tags if any. */
  1710.  
  1711.                 FilterTagItems(NewTagList,PrivateTags,TAGFILTER_NOT);
  1712.  
  1713.                     /* Create the object. */
  1714.  
  1715.                 Result = OldCreateGadgetA(Kind,Previous,New,TagList);
  1716.  
  1717.                     /* Free the private tag item list. */
  1718.  
  1719.                 FreeTagItems(NewTagList);
  1720.             }
  1721.         }
  1722.     }
  1723.  
  1724.     va_end(VarArgs);
  1725.  
  1726.         /* Patch in the GACT_IMMEDIATE flag for string gadget objects under
  1727.          * v37. Although this does not look very clean it is temporarily
  1728.          * permitted for this single release.
  1729.          */
  1730.  
  1731.     if(Result && GadToolsBase -> lib_Version == 37 && (Kind == STRING_KIND || Kind == INTEGER_KIND || Kind == PASSWORD_KIND))
  1732.         Result -> Activation |= GACT_IMMEDIATE;
  1733.  
  1734.     return(Result);
  1735. }
  1736.  
  1737.     /* GT_SetGadgetAttrs():
  1738.      *
  1739.      *    A frontend to the original routine.
  1740.      */
  1741.  
  1742. VOID
  1743. GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...)
  1744. {
  1745.     va_list                 VarArgs;
  1746.     struct TagItem            *TagList,
  1747.                     *ThisTag;
  1748.     struct GadgetSupportInfo    *Info;
  1749.  
  1750.         /* Get the tag item list. */
  1751.  
  1752.     va_start(VarArgs,Requester);
  1753.  
  1754.     TagList = (struct TagItem *)VarArgs;
  1755.  
  1756.         /* Does the object in question have an info structure attached? */
  1757.  
  1758.     if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  1759.     {
  1760.             /* Does the data look sensible? */
  1761.  
  1762.         if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  1763.         {
  1764.             struct Node    *Node;
  1765.             struct List    *List;
  1766.             LONG         Count;
  1767.             STRPTR        *Strings;
  1768.  
  1769.                 /* Update object-specific information. */
  1770.  
  1771.             switch(Info -> Kind)
  1772.             {
  1773.                 case CHECKBOX_KIND:
  1774.  
  1775.                     if(ThisTag = FindTagItem(GTCB_Checked,TagList))
  1776.                         Info -> Current = ThisTag -> ti_Data;
  1777.  
  1778.                     break;
  1779.  
  1780.                 case CYCLE_KIND:
  1781.  
  1782.                     if(ThisTag = FindTagItem(GTCY_Active,TagList))
  1783.                         Info -> Current = ThisTag -> ti_Data;
  1784.  
  1785.                     if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  1786.                     {
  1787.                         Count = 0;
  1788.  
  1789.                         if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1790.                         {
  1791.                             while(Strings[Count])
  1792.                                 Count++;
  1793.                         }
  1794.  
  1795.                         if(Count)
  1796.                             Info -> Max = Count - 1;
  1797.                         else
  1798.                             Info -> Max = 0;
  1799.                     }
  1800.  
  1801.                     break;
  1802.  
  1803.                 case LISTVIEW_KIND:
  1804.  
  1805.                     if(ThisTag = FindTagItem(GTLV_Selected,TagList))
  1806.                         Info -> Current = ThisTag -> ti_Data;
  1807.  
  1808.                     if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  1809.                     {
  1810.                         Count = 0;
  1811.  
  1812.                         if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
  1813.                         {
  1814.                             List = (struct List *)ThisTag -> ti_Data;
  1815.  
  1816.                             Node = List -> lh_Head;
  1817.  
  1818.                             while(Node -> ln_Succ)
  1819.                             {
  1820.                                 Count++;
  1821.  
  1822.                                 Node = Node -> ln_Succ;
  1823.                             }
  1824.                         }
  1825.  
  1826.                         if(Count)
  1827.                             Info -> Max = Count - 1;
  1828.                         else
  1829.                             Info -> Max = 0;
  1830.                     }
  1831.  
  1832.                     break;
  1833.  
  1834.                 case PALETTE_KIND:
  1835.  
  1836.                     if(ThisTag = FindTagItem(GTPA_Color,TagList))
  1837.                         Info -> Current = ThisTag -> ti_Data;
  1838.  
  1839.                     break;
  1840.  
  1841.                 case MX_KIND:
  1842.  
  1843.                     if(ThisTag = FindTagItem(GTMX_Active,TagList))
  1844.                         Info -> Current = ThisTag -> ti_Data;
  1845.  
  1846.                     break;
  1847.  
  1848.                 case SCROLLER_KIND:
  1849.  
  1850.                     if(ThisTag = FindTagItem(GTSC_Top,TagList))
  1851.                         Info -> Current = ThisTag -> ti_Data;
  1852.  
  1853.                     if(ThisTag = FindTagItem(GTSC_Total,TagList))
  1854.                         Info -> Max = ThisTag -> ti_Data;
  1855.  
  1856.                     break;
  1857.  
  1858.                 case SLIDER_KIND:
  1859.  
  1860.                     if(ThisTag = FindTagItem(GTSL_Level,TagList))
  1861.                         Info -> Current = ThisTag -> ti_Data;
  1862.  
  1863.                     if(ThisTag = FindTagItem(GTSL_Min,TagList))
  1864.                         Info -> Min = ThisTag -> ti_Data;
  1865.  
  1866.                     break;
  1867.  
  1868.                 case PASSWORD_KIND:
  1869.  
  1870.                     if(FindTagItem(GTST_String,TagList))
  1871.                     {
  1872.                         struct TagItem *NewTagList;
  1873.  
  1874.                         if(NewTagList = CloneTagItems(TagList))
  1875.                         {
  1876.                             LONG Len;
  1877.  
  1878.                             ThisTag = FindTagItem(GTST_String,NewTagList);
  1879.  
  1880.                             Forbid();
  1881.  
  1882.                             strcpy(Info -> Original,(STRPTR)ThisTag -> ti_Data);
  1883.                             strcpy(Info -> Buffer, (STRPTR)ThisTag -> ti_Data);
  1884.  
  1885.                             Len = strlen(Info -> Buffer);
  1886.  
  1887.                             memset(SharedBuffer,'*',Len);
  1888.  
  1889.                             SharedBuffer[Len] = 0;
  1890.  
  1891.                             ThisTag -> ti_Data = (ULONG)SharedBuffer;
  1892.  
  1893.                             OldGT_SetGadgetAttrsA(Gadget,Window,Requester,NewTagList);
  1894.  
  1895.                             FreeTagItems(NewTagList);
  1896.  
  1897.                             Permit();
  1898.                         }
  1899.  
  1900.                         va_end(VarArgs);
  1901.  
  1902.                         return;
  1903.                     }
  1904.  
  1905.                     break;
  1906.             }
  1907.         }
  1908.     }
  1909.  
  1910.         /* Call the original routine. */
  1911.  
  1912.     OldGT_SetGadgetAttrsA(Gadget,Window,Requester,TagList);
  1913.  
  1914.     va_end(VarArgs);
  1915. }
  1916.  
  1917.     /* FreeGadgets(struct Gadget *GadgetList):
  1918.      *
  1919.      *    A frontend to the original routine.
  1920.      */
  1921.  
  1922. VOID
  1923. FreeGadgets(struct Gadget *GadgetList)
  1924. {
  1925.     struct Gadget            *Gadget = GadgetList;
  1926.     struct GadgetSupportInfo    *Info;
  1927.  
  1928.         /* Run down the gadget list. */
  1929.  
  1930.     while(Gadget)
  1931.     {
  1932.             /* Is this the previously active string gadget? */
  1933.  
  1934.         if(Gadget == ActiveGadget)
  1935.             ActiveGadget = NULL;
  1936.  
  1937.             /* Does it have an info structure attached?*/
  1938.  
  1939.         if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  1940.         {
  1941.                 /* Does the data make sense? */
  1942.  
  1943.             if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  1944.             {
  1945.                 if(Info -> Image && (Info -> Kind == FOLDER_KIND || Info -> Kind == FILE_KIND))
  1946.                 {
  1947.                     WORD i;
  1948.  
  1949.                     for(i = 0 ; i < 2 ; i++)
  1950.                         FreeVec(Info -> Image[i] . ImageData);
  1951.  
  1952.                     FreeVec(Info -> Image);
  1953.                 }
  1954.  
  1955.                 if(Info -> Original && Info -> Kind == PASSWORD_KIND)
  1956.                     FreeVec(Info -> Original);
  1957.  
  1958.                 if(Info -> Title)
  1959.                     FreeVec(Info -> Title);
  1960.  
  1961.                 FreeMem(Info,sizeof(struct GadgetSupportInfo));
  1962.             }
  1963.         }
  1964.  
  1965.             /* Skip to next object. */
  1966.  
  1967.         Gadget = Gadget -> NextGadget;
  1968.     }
  1969.  
  1970.     OldFreeGadgets(GadgetList);
  1971. }
  1972.  
  1973.     /* GT_ReplyIMsg(struct IntuiMessage *Message):
  1974.      *
  1975.      *    A frontend to the original routine.
  1976.      */
  1977.  
  1978. VOID
  1979. GT_ReplyIMsg(struct IntuiMessage *Message)
  1980. {
  1981.         /* Is this really a message? */
  1982.  
  1983.     if(Message)
  1984.     {
  1985.             /* The following input event classes are likely to
  1986.              * affect a gadtools object.
  1987.              */
  1988.  
  1989.         if(Message -> Class == IDCMP_GADGETUP || Message -> Class == IDCMP_GADGETDOWN || Message -> Class == IDCMP_MOUSEMOVE)
  1990.         {
  1991.             struct Gadget *Gadget;
  1992.  
  1993.                 /* Take a look at the item attached. */
  1994.  
  1995.             if(Gadget = (struct Gadget *)Message -> IAddress)
  1996.             {
  1997.                 struct GadgetSupportInfo *Info = Gadget -> UserData;
  1998.  
  1999.                     /* If it's really a gadget, does it
  2000.                      * have an info structure attached?
  2001.                      */
  2002.  
  2003.                 if(Info)
  2004.                 {
  2005.                         /* Does the data make sense? */
  2006.  
  2007.                     if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  2008.                     {
  2009.                         LONG Value = (WORD)Message -> Code;
  2010.  
  2011.                             /* Update the object information. */
  2012.  
  2013.                         switch(Info -> Kind)
  2014.                         {
  2015.                             case CHECKBOX_KIND:
  2016.  
  2017.                                 if(Gadget -> Flags & GFLG_SELECTED)
  2018.                                     Info -> Current = TRUE;
  2019.                                 else
  2020.                                     Info -> Current = FALSE;
  2021.  
  2022.                                 break;
  2023.  
  2024.                             case CYCLE_KIND:
  2025.  
  2026.                                 Info -> Current = Message -> Code;
  2027.  
  2028.                                 break;
  2029.  
  2030.                             case LISTVIEW_KIND:
  2031.  
  2032.                                 Info -> Current = Message -> Code;
  2033.  
  2034.                                 break;
  2035.  
  2036.                             case MX_KIND:
  2037.  
  2038.                                 Info -> Current = Message -> Code;
  2039.  
  2040.                                 break;
  2041.  
  2042.                             case SCROLLER_KIND:
  2043.  
  2044.                                 Info -> Current = Message -> Code;
  2045.  
  2046.                                 break;
  2047.  
  2048.                             case SLIDER_KIND:
  2049.  
  2050.                                 if(Info -> Min >= 0 && Value < 0)
  2051.                                     Info -> Current = Message -> Code;
  2052.                                 else
  2053.                                     Info -> Current = Value;
  2054.  
  2055.                                 break;
  2056.  
  2057.                             case PALETTE_KIND:
  2058.  
  2059.                                 Info -> Current = Message -> Code;
  2060.  
  2061.                                 break;
  2062.  
  2063.                             default:
  2064.  
  2065.                                 break;
  2066.                         }
  2067.                     }
  2068.                 }
  2069.             }
  2070.         }
  2071.     }
  2072.  
  2073.         /* Reply the message correctly. */
  2074.  
  2075.     OldGT_ReplyIMsg(Message);
  2076. }
  2077.  
  2078.     /* KeySelect():
  2079.      *
  2080.      *    Handles gadget keystroke activation.
  2081.      */
  2082.  
  2083. VOID
  2084. KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *IClass,LONG *Code)
  2085. {
  2086.     if(*IClass == IDCMP_VANILLAKEY)
  2087.     {
  2088.             /* If an escape code comes in and the window does in
  2089.              * fact have a close gadget, return a close window
  2090.              * event.
  2091.              */
  2092.  
  2093.         if(Key == '\033' && (Window -> Flags & WFLG_CLOSEGADGET))
  2094.             *IClass = IDCMP_CLOSEWINDOW;
  2095.         else
  2096.         {
  2097.             struct GadgetSupportInfo    *Info;
  2098.             WORD                 i;
  2099.             BYTE                 Forward,
  2100.                              GotIt = FALSE;
  2101.  
  2102.                 /* Run down all the gadgets. */
  2103.  
  2104.             for(i = 0 ; !GotIt && i <= Last ; i++)
  2105.             {
  2106.                     /* Is there a gadget? */
  2107.  
  2108.                 if(GadgetList[i])
  2109.                 {
  2110.                         /* Is this gadget enabled? */
  2111.  
  2112.                     if(!(GadgetList[i] -> Flags & GFLG_DISABLED))
  2113.                     {
  2114.                             /* Does it have an info structure attached? */
  2115.  
  2116.                         if(Info = GadgetList[i] -> UserData)
  2117.                         {
  2118.                                 /* Does it make sense? */
  2119.  
  2120.                             if(Info -> PointBack == Info && Info -> Gadget == GadgetList[i])
  2121.                             {
  2122.                                     /* Do the keys match? */
  2123.  
  2124.                                 if(ToUpper(Info -> Key) == ToUpper(Key))
  2125.                                 {
  2126.                                         /* Are we cycle forward
  2127.                                          * or backwards?
  2128.                                          */
  2129.  
  2130.                                     if(ToUpper(Info -> Key) == Key)
  2131.                                         Forward = FALSE;
  2132.                                     else
  2133.                                         Forward = TRUE;
  2134.  
  2135.                                         /* Update the object information. */
  2136.  
  2137.                                     switch(Info -> Kind)
  2138.                                     {
  2139.                                         case PASSWORD_KIND:
  2140.                                         case STRING_KIND:
  2141.                                         case INTEGER_KIND:
  2142.  
  2143.                                             ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
  2144.  
  2145.                                             *IClass    = IDCMP_GADGETDOWN;
  2146.                                             *Code    = 0;
  2147.                                             *Gadget    = GadgetList[i];
  2148.  
  2149.                                             GotIt = TRUE;
  2150.  
  2151.                                             break;
  2152.  
  2153.                                         case BUTTON_KIND:
  2154.  
  2155.                                             *IClass    = IDCMP_GADGETUP;
  2156.                                             *Code    = 0;
  2157.                                             *Gadget    = GadgetList[i];
  2158.  
  2159.                                             GotIt = TRUE;
  2160.  
  2161.                                             break;
  2162.  
  2163.                                         case CHECKBOX_KIND:
  2164.  
  2165.                                             GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2166.                                                 GTCB_Checked,    Info -> Current ? FALSE : TRUE,
  2167.                                             TAG_DONE);
  2168.  
  2169.                                             *IClass    = IDCMP_GADGETUP;
  2170.                                             *Code    = Info -> Current;
  2171.                                             *Gadget    = GadgetList[i];
  2172.  
  2173.                                             GotIt = TRUE;
  2174.  
  2175.                                             break;
  2176.  
  2177.                                         case CYCLE_KIND:
  2178.  
  2179.                                             if(Forward)
  2180.                                             {
  2181.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2182.                                                     GTCY_Active,    (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
  2183.                                                 TAG_DONE);
  2184.                                             }
  2185.                                             else
  2186.                                             {
  2187.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2188.                                                     GTCY_Active,    Info -> Current ? Info -> Current - 1 : Info -> Max,
  2189.                                                 TAG_DONE);
  2190.                                             }
  2191.  
  2192.                                             *IClass    = IDCMP_GADGETUP;
  2193.                                             *Code    = Info -> Current;
  2194.                                             *Gadget    = GadgetList[i];
  2195.  
  2196.                                             GotIt = TRUE;
  2197.  
  2198.                                             break;
  2199.  
  2200.                                         case LISTVIEW_KIND:
  2201.  
  2202.                                             if(Forward)
  2203.                                             {
  2204.                                                 if(Info -> Current == ~0)
  2205.                                                     Info -> Current = -1;
  2206.  
  2207.                                                 if(Info -> Current < Info -> Max)
  2208.                                                 {
  2209.                                                     if(Info -> ReadOnly)
  2210.                                                     {
  2211.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2212.                                                             GTLV_Top,        Info -> Current + 1,
  2213.                                                             GTLV_MakeVisible,    Info -> Current + 1,
  2214.                                                         TAG_DONE);
  2215.                                                     }
  2216.                                                     else
  2217.                                                     {
  2218.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2219.                                                             GTLV_Selected,        Info -> Current + 1,
  2220.                                                             GTLV_Top,        Info -> Current + 1,
  2221.                                                             GTLV_MakeVisible,    Info -> Current + 1,
  2222.                                                         TAG_DONE);
  2223.                                                     }
  2224.  
  2225.                                                     *IClass    = IDCMP_GADGETUP;
  2226.                                                     *Code    = Info -> Current;
  2227.                                                     *Gadget    = GadgetList[i];
  2228.                                                 }
  2229.                                             }
  2230.                                             else
  2231.                                             {
  2232.                                                 if(Info -> Current == ~0)
  2233.                                                     Info -> Current = Info -> Max + 1;
  2234.  
  2235.                                                 if(Info -> Current > Info -> Min)
  2236.                                                 {
  2237.                                                     if(Info -> ReadOnly)
  2238.                                                     {
  2239.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2240.                                                             GTLV_Top,        Info -> Current - 1,
  2241.                                                             GTLV_MakeVisible,    Info -> Current - 1,
  2242.                                                         TAG_DONE);
  2243.                                                     }
  2244.                                                     else
  2245.                                                     {
  2246.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2247.                                                             GTLV_Selected,        Info -> Current - 1,
  2248.                                                             GTLV_Top,        Info -> Current - 1,
  2249.                                                             GTLV_MakeVisible,    Info -> Current - 1,
  2250.                                                         TAG_DONE);
  2251.                                                     }
  2252.  
  2253.                                                     *IClass    = IDCMP_GADGETUP;
  2254.                                                     *Code    = Info -> Current;
  2255.                                                     *Gadget    = GadgetList[i];
  2256.                                                 }
  2257.                                             }
  2258.  
  2259.                                             GotIt = TRUE;
  2260.  
  2261.                                             break;
  2262.  
  2263.                                         case MX_KIND:
  2264.  
  2265.                                             if(Forward)
  2266.                                             {
  2267.                                                 if(Info -> Current < Info -> Max)
  2268.                                                 {
  2269.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2270.                                                         GTMX_Active,    *Code = Info -> Current + 1,
  2271.                                                     TAG_DONE);
  2272.  
  2273.                                                     *IClass    = IDCMP_GADGETUP;
  2274.                                                     *Code    = Info -> Current;
  2275.                                                     *Gadget    = GadgetList[i];
  2276.                                                 }
  2277.                                             }
  2278.                                             else
  2279.                                             {
  2280.                                                 if(Info -> Current > Info -> Min)
  2281.                                                 {
  2282.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2283.                                                         GTMX_Active,    *Code = Info -> Current - 1,
  2284.                                                     TAG_DONE);
  2285.  
  2286.                                                     *IClass    = IDCMP_GADGETUP;
  2287.                                                     *Code    = Info -> Current;
  2288.                                                     *Gadget    = GadgetList[i];
  2289.                                                 }
  2290.                                             }
  2291.  
  2292.                                             GotIt = TRUE;
  2293.  
  2294.                                             break;
  2295.  
  2296.                                         case PALETTE_KIND:
  2297.  
  2298.                                             if(Forward)
  2299.                                             {
  2300.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2301.                                                     GTPA_Color,    (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
  2302.                                                 TAG_DONE);
  2303.                                             }
  2304.                                             else
  2305.                                             {
  2306.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2307.                                                     GTPA_Color,    Info -> Current ? Info -> Current - 1 : Info -> Max,
  2308.                                                 TAG_DONE);
  2309.                                             }
  2310.  
  2311.                                             *IClass    = IDCMP_GADGETUP;
  2312.                                             *Code    = Info -> Current;
  2313.                                             *Gadget    = GadgetList[i];
  2314.  
  2315.                                             GotIt = TRUE;
  2316.  
  2317.                                             break;
  2318.  
  2319.                                         case SCROLLER_KIND:
  2320.  
  2321.                                             if(Forward)
  2322.                                             {
  2323.                                                 if(Info -> Current < Info -> Max)
  2324.                                                 {
  2325.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2326.                                                         GTSC_Top,    Info -> Current + 1,
  2327.                                                     TAG_DONE);
  2328.  
  2329.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2330.                                                     *Code    = Info -> Current;
  2331.                                                     *Gadget    = GadgetList[i];
  2332.                                                 }
  2333.                                             }
  2334.                                             else
  2335.                                             {
  2336.                                                 if(Info -> Current > Info -> Min)
  2337.                                                 {
  2338.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2339.                                                         GTSC_Top,    Info -> Current - 1,
  2340.                                                     TAG_DONE);
  2341.  
  2342.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2343.                                                     *Code    = Info -> Current;
  2344.                                                     *Gadget    = GadgetList[i];
  2345.                                                 }
  2346.                                             }
  2347.  
  2348.                                             GotIt = TRUE;
  2349.  
  2350.                                             break;
  2351.  
  2352.                                         case SLIDER_KIND:
  2353.  
  2354.                                             if(Forward)
  2355.                                             {
  2356.                                                 if(Info -> Current < Info -> Max)
  2357.                                                 {
  2358.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2359.                                                         GTSL_Level,    Info -> Current + 1,
  2360.                                                     TAG_DONE);
  2361.  
  2362.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2363.                                                     *Code    = Info -> Current;
  2364.                                                     *Gadget    = GadgetList[i];
  2365.                                                 }
  2366.                                             }
  2367.                                             else
  2368.                                             {
  2369.                                                 if(Info -> Current > Info -> Min)
  2370.                                                 {
  2371.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  2372.                                                         GTSL_Level,    Info -> Current - 1,
  2373.                                                     TAG_DONE);
  2374.  
  2375.                                                     *IClass    = IDCMP_MOUSEMOVE;
  2376.                                                     *Code    = Info -> Current;
  2377.                                                     *Gadget    = GadgetList[i];
  2378.                                                 }
  2379.                                             }
  2380.  
  2381.                                             GotIt = TRUE;
  2382.  
  2383.                                             break;
  2384.                                     }
  2385.                                 }
  2386.                             }
  2387.                         }
  2388.                     }
  2389.                 }
  2390.             }
  2391.  
  2392.                 /* If no matching object was found, take a closer look at the types. */
  2393.  
  2394.             if(!GotIt)
  2395.             {
  2396.                 for(i = 0 ; i <= Last ; i++)
  2397.                 {
  2398.                         /* If it's a string object, activate it. */
  2399.  
  2400.                     if(GadgetList[i])
  2401.                     {
  2402.                         if(!(GadgetList[i] -> Flags & GFLG_DISABLED) && (GadgetList[i] -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  2403.                         {
  2404.                             ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
  2405.  
  2406.                             *IClass    = IDCMP_GADGETDOWN;
  2407.                             *Code    = 0;
  2408.                             *Gadget    = GadgetList[i];
  2409.  
  2410.                             break;
  2411.                         }
  2412.                     }
  2413.                 }
  2414.             }
  2415.         }
  2416.     }
  2417.  
  2418.         /* Conjure up the AmigaGuide help window. */
  2419.  
  2420.     if(*IClass == IDCMP_RAWKEY && *Code == 95)
  2421.         GuideSetup();
  2422. }
  2423.  
  2424.     /* SZ_ResetMaxWidth():
  2425.      *
  2426.      *    Reset maximum object width and return current maximum width.
  2427.      */
  2428.  
  2429. LONG
  2430. SZ_ResetMaxWidth()
  2431. {
  2432.     LONG Width = SZ_WidthMax;
  2433.  
  2434.     SZ_WidthMax = 0;
  2435.  
  2436.     return(Width);
  2437. }
  2438.  
  2439.     /* SZ_UpdateMaxWidth():
  2440.      *
  2441.      *    Update current maximum object width.
  2442.      */
  2443.  
  2444. VOID __regargs
  2445. SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
  2446. {
  2447.     LONG Width = SZ_Width(Type,Title,Chars,Choices);
  2448.  
  2449.     if(Width > SZ_WidthMax)
  2450.         SZ_WidthMax = Width;
  2451. }
  2452.  
  2453.     /* SZ_GetWindowWidth():
  2454.      *
  2455.      *    Get the current window width.
  2456.      */
  2457.  
  2458. LONG
  2459. SZ_GetWindowWidth()
  2460. {
  2461.     return(SZ_WindowWidth);
  2462. }
  2463.  
  2464.     /* SZ_GetWindowHeight():
  2465.      *
  2466.      *    Get the current window height.
  2467.      */
  2468.  
  2469. LONG
  2470. SZ_GetWindowHeight()
  2471. {
  2472.     return(SZ_WindowHeight + SZ_Screen -> WBorBottom);
  2473. }
  2474.  
  2475.     /* SZ_GetLeftEdge():
  2476.      *
  2477.      *    Get the current object left edge.
  2478.      */
  2479.  
  2480. LONG
  2481. SZ_GetLeftEdge()
  2482. {
  2483.     return(SZ_CurrentLeft);
  2484. }
  2485.  
  2486.     /* SZ_GetTopEdge():
  2487.      *
  2488.      *    Get the current object top edge.
  2489.      */
  2490.  
  2491. LONG
  2492. SZ_GetTopEdge()
  2493. {
  2494.     return(SZ_CurrentTop);
  2495. }
  2496.  
  2497.     /* SZ_SetTopEdge(LONG Top):
  2498.      *
  2499.      *    Set the current object top edge.
  2500.      */
  2501.  
  2502. VOID __regargs
  2503. SZ_SetTopEdge(LONG Top)
  2504. {
  2505.     SZ_CurrentTop = Top;
  2506. }
  2507.  
  2508.     /* SZ_SetLeftEdge(LONG Left):
  2509.      *
  2510.      *    Set the current object left edge.
  2511.      */
  2512.  
  2513. VOID __regargs
  2514. SZ_SetLeftEdge(LONG Left)
  2515. {
  2516.     SZ_CurrentLeft = Left;
  2517. }
  2518.  
  2519.     /* SZ_SetAbsoluteTop(LONG Top):
  2520.      *
  2521.      *    Set new inner window top edge.
  2522.      */
  2523.  
  2524. VOID __regargs
  2525. SZ_SetAbsoluteTop(LONG Top)
  2526. {
  2527.     SZ_Top = Top;
  2528. }
  2529.  
  2530.     /* SZ_SetAbsoluteLeft(LONG Left):
  2531.      *
  2532.      *    Set new inner window left edge.
  2533.      */
  2534.  
  2535. VOID __regargs
  2536. SZ_SetAbsoluteLeft(LONG Left)
  2537. {
  2538.     SZ_Left = Left;
  2539. }
  2540.  
  2541.     /* SZ_SetWidth(LONG Width):
  2542.      *
  2543.      *    Set current object width.
  2544.      */
  2545.  
  2546. VOID __regargs
  2547. SZ_SetWidth(LONG Width)
  2548. {
  2549.     SZ_CurrentWidth = Width;
  2550. }
  2551.  
  2552. VOID
  2553. SZ_InitWidth()
  2554. {
  2555.     SZ_WindowWidth = SZ_Left + SZ_CurrentWidth + InterWidth;
  2556. }
  2557.  
  2558.     /* SZ_GetDimension(LONG *Width,LONG *Height):
  2559.      *
  2560.      *    Get current window dimensions.
  2561.      */
  2562.  
  2563. VOID __regargs
  2564. SZ_GetDimension(LONG *Width,LONG *Height)
  2565. {
  2566.     *Width    = SZ_WindowWidth;
  2567.     *Height    = SZ_WindowHeight + SZ_Screen -> WBorBottom;
  2568. }
  2569.  
  2570.     /* SZ_GetChecked(struct Gadget *Gadget):
  2571.      *
  2572.      *    Return whether a checkbox gadget is checked or not.
  2573.      */
  2574.  
  2575. BYTE __regargs
  2576. SZ_GetChecked(struct Gadget *Gadget)
  2577. {
  2578.     if(Gadget -> Flags & GFLG_SELECTED)
  2579.         return((BYTE)TRUE);
  2580.     else
  2581.         return((BYTE)FALSE);
  2582. }
  2583.  
  2584.     /* SZ_GetInteger(struct Gadget *Gadget):
  2585.      *
  2586.      *    Return the current settings of an integer gadget.
  2587.      */
  2588.  
  2589. LONG __regargs
  2590. SZ_GetInteger(struct Gadget *Gadget)
  2591. {
  2592.     if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  2593.         return(((struct StringInfo *)(Gadget -> SpecialInfo)) -> LongInt);
  2594.     else
  2595.         return(0);
  2596. }
  2597.  
  2598.     /* SZ_GetString(struct Gadget *Gadget):
  2599.      *
  2600.      *    Returns the contents of a string gadet.
  2601.      */
  2602.  
  2603. STRPTR __regargs
  2604. SZ_GetString(struct Gadget *Gadget)
  2605. {
  2606.     struct GadgetSupportInfo *Info;
  2607.  
  2608.         /* Does the object in question have an info structure attached? */
  2609.  
  2610.     if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  2611.     {
  2612.             /* Does the data look sensible? */
  2613.  
  2614.         if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  2615.         {
  2616.             if(Info -> Kind == PASSWORD_KIND)
  2617.                 return(Info -> Buffer);
  2618.         }
  2619.     }
  2620.  
  2621.     if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  2622.         return(((struct StringInfo *)(Gadget -> SpecialInfo)) -> Buffer);
  2623.     else
  2624.         return("");
  2625. }
  2626.  
  2627.     /* SZ_TextWidth(STRPTR String):
  2628.      *
  2629.      *    Determine string width in pixels.
  2630.      */
  2631.  
  2632. LONG __regargs
  2633. SZ_TextWidth(STRPTR String)
  2634. {
  2635.     UBYTE    TempString[256];
  2636.     WORD    i,j;
  2637.     BYTE    LastSpace = FALSE;
  2638.  
  2639.     for(i = j = 0 ; String[i] ; i++)
  2640.     {
  2641.         if(String[i] == ' ')
  2642.             LastSpace = TRUE;
  2643.         else
  2644.             LastSpace = FALSE;
  2645.  
  2646.         if(String[i] != '_')
  2647.             TempString[j++] = String[i];
  2648.     }
  2649.  
  2650.     if(LastSpace)
  2651.     {
  2652.         TempString[j] = 0;
  2653.  
  2654.         String = NewTitle(TempString,0,NULL,FALSE);
  2655.  
  2656.         j = strlen(String);
  2657.  
  2658.         return(TextLength(SZ_RPort,String,j));
  2659.     }
  2660.     else
  2661.         return(TextLength(SZ_RPort,TempString,j));
  2662. }
  2663.  
  2664.     /* SZ_AddLeftOffset(LONG Offset):
  2665.      *
  2666.      *    Update current object left offset.
  2667.      */
  2668.  
  2669. VOID __regargs
  2670. SZ_AddLeftOffset(LONG Offset)
  2671. {
  2672.     SZ_CurrentLeft += Offset;
  2673. }
  2674.  
  2675.     /* SZ_LeftOffsetN(LONG DataArray,...):
  2676.      *
  2677.      *    Determine the maximum length of a number of
  2678.      *    gadget labels (first, second, third item, -1 terminates
  2679.      *    the array).
  2680.      */
  2681.  
  2682. LONG __stdargs
  2683. SZ_LeftOffsetN(LONG DataArray,...)
  2684. {
  2685.     extern STRPTR __regargs    LocaleString(LONG ID);
  2686.  
  2687.     LONG    *Data = &DataArray,
  2688.          Len,
  2689.          Max = 0;
  2690.  
  2691.     while(*Data != -1)
  2692.     {
  2693.         if((Len = SZ_TextWidth(LocaleString(*Data++))) > Max)
  2694.             Max = Len;
  2695.     }
  2696.  
  2697.     return(Max + INTERWIDTH);
  2698. }
  2699.  
  2700.     /* SZ_LeftOffsetDelta(LONG From,LONG To):
  2701.      *
  2702.      *    Determine the maximum length of a number of
  2703.      *    gadget labels (given as first and last gadget).
  2704.      */
  2705.  
  2706. LONG __regargs
  2707. SZ_LeftOffsetDelta(LONG From,LONG To)
  2708. {
  2709.     extern STRPTR __regargs    LocaleString(LONG ID);
  2710.  
  2711.     LONG    i,
  2712.         Len,
  2713.         Max = 0;
  2714.  
  2715.     for(i = From ; i <= To ; i++)
  2716.     {
  2717.         if((Len = SZ_TextWidth(LocaleString(i))) > Max)
  2718.             Max = Len;
  2719.     }
  2720.  
  2721.     return(Max + INTERWIDTH);
  2722. }
  2723.  
  2724.     /* SZ_SizeCleanup():
  2725.      *
  2726.      *    Free data allocated by SZ_SizeSetup().
  2727.      */
  2728.  
  2729. VOID
  2730. SZ_SizeCleanup()
  2731. {
  2732.     if(SZ_TextFont)
  2733.     {
  2734.         CloseFont(SZ_TextFont);
  2735.  
  2736.         SZ_TextFont = NULL;
  2737.     }
  2738.  
  2739.     if(SZ_RPort)
  2740.     {
  2741.         FreeVec(SZ_RPort);
  2742.  
  2743.         SZ_RPort = NULL;
  2744.     }
  2745. }
  2746.  
  2747.     /* SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title):
  2748.      *
  2749.      *    Perform setups for gadget creation.
  2750.      */
  2751.  
  2752. BYTE __regargs
  2753. SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title)
  2754. {
  2755.     struct DrawInfo *DrawInfo;
  2756.  
  2757.     SZ_SizeCleanup();
  2758.  
  2759.     if(DrawInfo = GetScreenDrawInfo(Screen))
  2760.     {
  2761.         SZ_TextPen = DrawInfo -> dri_Pens[TEXTPEN];
  2762.  
  2763.         FreeScreenDrawInfo(Screen,DrawInfo);
  2764.     }
  2765.  
  2766.     SZ_Screen = Screen;
  2767.  
  2768.     if(SZ_RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY | MEMF_CLEAR))
  2769.     {
  2770.         InitRastPort(SZ_RPort);
  2771.  
  2772.         if(!TextAttr)
  2773.             TextAttr = Screen -> Font;
  2774.  
  2775.         if(DiskfontBase)
  2776.             SZ_TextFont = (struct TextFont *)OpenDiskFont(TextAttr);
  2777.         else
  2778.             SZ_TextFont = (struct TextFont *)OpenFont(TextAttr);
  2779.  
  2780.         if(SZ_TextFont)
  2781.         {
  2782.             UWORD    i,Width;
  2783.             UBYTE    Char;
  2784.  
  2785.             InterWidth = INTERWIDTH;
  2786.  
  2787.             if(SZ_TextFont -> tf_YSize <= 8)
  2788.                 InterHeight = 1;
  2789.             else
  2790.                 InterHeight = SZ_TextFont -> tf_YSize / 4;
  2791.  
  2792.             SetFont(SZ_RPort,SZ_TextFont);
  2793.  
  2794.             SZ_AverageGlyphWidth    = 0;
  2795.             SZ_MaxGlyphWidth    = 0;
  2796.             SZ_MaxNumericWidth    = 0;
  2797.  
  2798.             for(i = 0 ; i < 256 ; i++)
  2799.             {
  2800.                 Char = i;
  2801.  
  2802.                 Width = TextLength(SZ_RPort,&Char,1);
  2803.  
  2804.                 if(Width > SZ_MaxGlyphWidth)
  2805.                     SZ_MaxGlyphWidth = Width;
  2806.  
  2807.                 SZ_AverageGlyphWidth += Width;
  2808.             }
  2809.  
  2810.             SZ_AverageGlyphWidth /= 256;
  2811.  
  2812.             for(i = '0' ; i <= '0' ; i++)
  2813.             {
  2814.                 Char = i;
  2815.  
  2816.                 if((Width = TextLength(SZ_RPort,&Char,1)) > SZ_MaxNumericWidth)
  2817.                     SZ_MaxNumericWidth = Width;
  2818.             }
  2819.  
  2820.             if((Width = TextLength(SZ_RPort," ",1)) > SZ_MaxNumericWidth)
  2821.                 SZ_MaxNumericWidth = Width;
  2822.  
  2823.             if((Width = TextLength(SZ_RPort,",",1)) > SZ_MaxNumericWidth)
  2824.                 SZ_MaxNumericWidth = Width;
  2825.  
  2826.             if((Width = TextLength(SZ_RPort,".",1)) > SZ_MaxNumericWidth)
  2827.                 SZ_MaxNumericWidth = Width;
  2828.  
  2829.             if(SZ_AverageGlyphWidth > SZ_MaxNumericWidth)
  2830.                 SZ_MaxNumericWidth = SZ_AverageGlyphWidth;
  2831.  
  2832.             if(Title)
  2833.                 SZ_Top    = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + InterHeight;
  2834.             else
  2835.                 SZ_Top    = Screen -> WBorTop + InterHeight;
  2836.  
  2837.             SZ_Left        = InterWidth;
  2838.  
  2839.             SZ_CurrentLeft    = InterWidth;
  2840.             SZ_CurrentTop    = SZ_Top;
  2841.  
  2842.             SZ_WindowWidth    = 0;
  2843.             SZ_WindowHeight    = 0;
  2844.  
  2845.             SZ_CurrentWidth    = 0;
  2846.             SZ_MaxWidth    = 0;
  2847.  
  2848.             return(TRUE);
  2849.         }
  2850.     }
  2851.  
  2852.     SZ_SizeCleanup();
  2853.  
  2854.     return(FALSE);
  2855. }
  2856.  
  2857.     /* SZ_GetNumericLen(STRPTR String):
  2858.      *
  2859.      *    Get the string pixel width, measured using the maximum
  2860.      *    numeric glyph width.
  2861.      */
  2862.  
  2863. ULONG __regargs
  2864. SZ_GetNumericLen(STRPTR String)
  2865. {
  2866.     return(strlen(String) * SZ_MaxNumericWidth);
  2867. }
  2868.  
  2869.     /* SZ_GetGlyphLen(STRPTR String):
  2870.      *
  2871.      *    Get the string pixel width, measured using the maximum
  2872.      *    glyph width.
  2873.      */
  2874.  
  2875. ULONG __regargs
  2876. SZ_GetGlyphLen(STRPTR String)
  2877. {
  2878.     return(strlen(String) * SZ_MaxGlyphWidth);
  2879. }
  2880.  
  2881.     /* SZ_GetLen(STRPTR String):
  2882.      *
  2883.      *    Get the string pixel width, measured using the average
  2884.      *    glyph width.
  2885.      */
  2886.  
  2887. ULONG __regargs
  2888. SZ_GetLen(STRPTR String)
  2889. {
  2890.     return(strlen(String) * SZ_AverageGlyphWidth);
  2891. }
  2892.  
  2893.     /* SZ_Height(UBYTE Type,LONG Lines,BYTE Display):
  2894.      *
  2895.      *    Determine the height of an object.
  2896.      */
  2897.  
  2898. LONG __regargs
  2899. SZ_Height(UBYTE Type,LONG Lines,BYTE Display)
  2900. {
  2901.     LONG Height = 0;
  2902.  
  2903.     switch(Type)
  2904.     {
  2905.         case LISTVIEW_KIND:
  2906.  
  2907.             Height = 4 + Lines * SZ_TextFont -> tf_YSize + 4;
  2908.  
  2909.             if(Display == SZLV_Display)
  2910.                 Height += 2 + SZ_TextFont -> tf_YSize + 2;
  2911.  
  2912.             if(Display == SZLV_String)
  2913.                 Height += 3 + SZ_TextFont -> tf_YSize + 3;
  2914.  
  2915.             break;
  2916.  
  2917.         case FILE_KIND:
  2918.         case FOLDER_KIND:
  2919.  
  2920.             if(SZ_TextFont -> tf_YSize < 6)
  2921.                 Height = 12;
  2922.             else
  2923.                 Height = 3 + SZ_TextFont -> tf_YSize + 3;
  2924.  
  2925.             break;
  2926.  
  2927.         case PASSWORD_KIND:
  2928.         case INTEGER_KIND:
  2929.         case STRING_KIND:
  2930.  
  2931.             Height = 3 + SZ_TextFont -> tf_YSize + 3;
  2932.             break;
  2933.  
  2934.         case CYCLE_KIND:
  2935.         case TEXT_KIND:
  2936.         case BUTTON_KIND:
  2937.  
  2938.             Height = 2 + SZ_TextFont -> tf_YSize + 2;
  2939.             break;
  2940.  
  2941.         case CHECKBOX_KIND:
  2942.  
  2943.             if(SZ_TextFont -> tf_YSize < 11)
  2944.                 Height = 11;
  2945.             else
  2946.                 Height = SZ_TextFont -> tf_YSize;
  2947.  
  2948.             break;
  2949.  
  2950.         case SLIDER_KIND:
  2951.  
  2952.             Height = 1 + SZ_TextFont -> tf_YSize + 1;
  2953.             break;
  2954.  
  2955.         case MX_KIND:
  2956.  
  2957.             Height = Lines * (SZ_TextFont -> tf_YSize + 1) - 1;
  2958.             break;
  2959.  
  2960.         case PALETTE_KIND:
  2961.  
  2962.             Height = 2 * SZ_TextFont -> tf_YSize;
  2963.             break;
  2964.     }
  2965.  
  2966.     return(Height);
  2967. }
  2968.  
  2969.     /* SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices):
  2970.      *
  2971.      *    Determine the width of an object.
  2972.      */
  2973.  
  2974. LONG __regargs
  2975. SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
  2976. {
  2977.     LONG    Width = 0,
  2978.         Len,Max = 0,i;
  2979.  
  2980.     switch(Type)
  2981.     {
  2982.         case LISTVIEW_KIND:
  2983.  
  2984.             Width = (4 + Chars * SZ_AverageGlyphWidth + 4) + (2 + 2 * SZ_AverageGlyphWidth + 2) + 4;    /* KLUDGE + 4 */
  2985.             break;
  2986.  
  2987.         case TEXT_KIND:
  2988.         case BUTTON_KIND:
  2989.  
  2990.             if(Title)
  2991.                 Width = 6 + SZ_TextWidth(Title) + 6;
  2992.             else
  2993.                 Width = 6 + Chars * SZ_AverageGlyphWidth + 6;
  2994.  
  2995.             break;
  2996.  
  2997.         case FILE_KIND:
  2998.         case FOLDER_KIND:
  2999.  
  3000.             if(SZ_AverageGlyphWidth <= 10)
  3001.                 Width = 20;
  3002.             else
  3003.                 Width = 2 * SZ_AverageGlyphWidth;
  3004.  
  3005.             if(Chars)
  3006.                 Width = 6 + Chars * SZ_AverageGlyphWidth + 6 - (2 + Width);
  3007.  
  3008.             break;
  3009.  
  3010.         case PASSWORD_KIND:
  3011.         case SLIDER_KIND:
  3012.         case STRING_KIND:
  3013.         case INTEGER_KIND:
  3014.  
  3015.             Width = 6 + Chars * SZ_AverageGlyphWidth + 6;
  3016.             break;
  3017.  
  3018.         case CHECKBOX_KIND:
  3019.  
  3020.             if(SZ_AverageGlyphWidth < 13)
  3021.                 Width = 26;
  3022.             else
  3023.                 Width = 2 * SZ_AverageGlyphWidth;
  3024.  
  3025.             break;
  3026.  
  3027.         case CYCLE_KIND:
  3028.  
  3029.             if(Choices)
  3030.             {
  3031.                 for(i = 0 ; Choices[i] ; i++)
  3032.                 {
  3033.                     if((Len = TextLength(SZ_RPort,Choices[i],strlen(Choices[i]))) > Max)
  3034.                         Max = Len;
  3035.                 }
  3036.  
  3037.                 Width = 24 + Max + 4;
  3038.             }
  3039.             else
  3040.                 Width = 24 + Chars * SZ_AverageGlyphWidth + 4;
  3041.  
  3042.             break;
  3043.  
  3044.         case MX_KIND:
  3045.  
  3046.             if(SZ_AverageGlyphWidth < 8)
  3047.                 Width = 17;
  3048.             else
  3049.                 Width = 2 * SZ_AverageGlyphWidth;
  3050.  
  3051.             break;
  3052.     }
  3053.  
  3054.     return(Width);
  3055. }
  3056.  
  3057.     /* SZ_FreeBox(struct TextBox *Box):
  3058.      *
  3059.      *    Free a text box.
  3060.      */
  3061.  
  3062. VOID __regargs
  3063. SZ_FreeBox(struct TextBox *Box)
  3064. {
  3065.     if(Box)
  3066.     {
  3067.         if(Box -> Text)
  3068.         {
  3069.             LONG i;
  3070.  
  3071.             for(i = 0 ; i < Box -> NumLines ; i++)
  3072.             {
  3073.                 if(Box -> Text[i])
  3074.                     FreeVec(Box -> Text[i]);
  3075.             }
  3076.  
  3077.             FreeVec(Box -> Text);
  3078.         }
  3079.  
  3080.         if(Box -> Title)
  3081.             FreeVec(Box -> Title);
  3082.  
  3083.         FreeVec(Box);
  3084.     }
  3085. }
  3086.  
  3087.     /* SZ_FreeBoxes(struct TextBox *FirstBox):
  3088.      *
  3089.      *    Free a number of text boxes.
  3090.      */
  3091.  
  3092. VOID __regargs
  3093. SZ_FreeBoxes(struct TextBox *FirstBox)
  3094. {
  3095.     if(FirstBox)
  3096.     {
  3097.         struct TextBox *NextBox;
  3098.  
  3099.         do
  3100.         {
  3101.             NextBox = FirstBox -> NextBox;
  3102.  
  3103.             SZ_FreeBox(FirstBox);
  3104.  
  3105.             FirstBox = NextBox;
  3106.         }
  3107.         while(FirstBox);
  3108.     }
  3109. }
  3110.  
  3111.     /* SZ_BoxWidth(LONG Chars):
  3112.      *
  3113.      *    Determine the width of a text box.
  3114.      */
  3115.  
  3116. LONG __regargs
  3117. SZ_BoxWidth(LONG Chars)
  3118. {
  3119.     return((LONG)(4 + SZ_AverageGlyphWidth * Chars + 4));
  3120. }
  3121.  
  3122.     /* SZ_BoxHeight(LONG Lines):
  3123.      *
  3124.      *    Determine the height of a text box.
  3125.      */
  3126.  
  3127. LONG __regargs
  3128. SZ_BoxHeight(LONG Lines)
  3129. {
  3130.     return(2 + SZ_TextFont -> tf_YSize * Lines + 2);
  3131. }
  3132.  
  3133.     /* SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen):
  3134.      *
  3135.      *    Set the text box list title text rendering pens.
  3136.      */
  3137.  
  3138. VOID __regargs
  3139. SZ_SetTitlePen(struct TextBox *Box,LONG FgPen,LONG BgPen)
  3140. {
  3141.     while(Box)
  3142.     {
  3143.         Box -> TitleFgPen = FgPen;
  3144.         Box -> TitleBgPen = BgPen;
  3145.  
  3146.         Box = Box -> NextBox;
  3147.     }
  3148. }
  3149.  
  3150.     /* SZ_CreateTextBox(struct TextBox **FirstBox,...):
  3151.      *
  3152.      *    Create a text box, this routine works similar
  3153.      *    to the CreateGadget() frontend.
  3154.      */
  3155.  
  3156. struct TextBox * __stdargs
  3157. SZ_CreateTextBox(struct TextBox **FirstBox,...)
  3158. {
  3159.     va_list                 VarArgs;
  3160.     struct TagItem            *TagList,
  3161.                     *ThisTag;
  3162.     LONG                 Chars,Lines,
  3163.                      Width,
  3164.                      Height,
  3165.                      Left = SZ_CurrentLeft;
  3166.     BYTE                 AutoWidth    = FALSE,
  3167.                      MoveDown    = TRUE,
  3168.                      SetLeft    = FALSE,
  3169.                      SetBelow    = FALSE;
  3170.  
  3171.     struct TextBox            *Box;
  3172.     LONG                 i;
  3173.  
  3174.     va_start(VarArgs,FirstBox);
  3175.  
  3176.     TagList = (struct TagItem *)VarArgs;
  3177.  
  3178.     if(ThisTag = FindTagItem(SZ_Lines,TagList))
  3179.         Lines = (LONG)ThisTag -> ti_Data;
  3180.     else
  3181.         return(NULL);
  3182.  
  3183.     Height = 2 + SZ_TextFont -> tf_YSize * Lines + 2;
  3184.  
  3185.     if(ThisTag = FindTagItem(SZ_Chars,TagList))
  3186.         Chars = (LONG)ThisTag -> ti_Data;
  3187.     else
  3188.     {
  3189.         if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  3190.             AutoWidth = ThisTag -> ti_Data;
  3191.  
  3192.         if(!AutoWidth)
  3193.             return(NULL);
  3194.         else
  3195.             Chars = (SZ_CurrentWidth - 8) / SZ_AverageGlyphWidth;
  3196.     }
  3197.  
  3198.     if(!(Box = (struct TextBox *)AllocVec(sizeof(struct TextBox),MEMF_ANY | MEMF_CLEAR)))
  3199.         return(NULL);
  3200.  
  3201.     if(ThisTag = FindTagItem(SZ_SaveX,TagList))
  3202.         SetLeft = ThisTag -> ti_Data;
  3203.  
  3204.     if(ThisTag = FindTagItem(SZ_SaveY,TagList))
  3205.         SetBelow = ThisTag -> ti_Data;
  3206.  
  3207.     if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
  3208.     {
  3209.         if(ThisTag -> ti_Data)
  3210.             SZ_CurrentTop = SZ_WindowHeight;
  3211.     }
  3212.  
  3213.     if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
  3214.     {
  3215.         if(ThisTag -> ti_Data)
  3216.             SZ_CurrentTop += InterHeight;
  3217.     }
  3218.  
  3219.     if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
  3220.     {
  3221.         if(ThisTag -> ti_Data)
  3222.         {
  3223.             SZ_CurrentTop    = SZ_Top;
  3224.             Left        = Left + SZ_MaxWidth + InterWidth;
  3225.  
  3226.             SZ_MaxWidth    = 0;
  3227.         }
  3228.     }
  3229.  
  3230.     if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  3231.         AutoWidth = ThisTag -> ti_Data;
  3232.  
  3233.     if(!AutoWidth)
  3234.         Width = SZ_BoxWidth(Chars);
  3235.     else
  3236.         Width = SZ_CurrentWidth;
  3237.  
  3238.     if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
  3239.     {
  3240.         if(ThisTag -> ti_Data)
  3241.         {
  3242.             Left = SZ_Left;
  3243.  
  3244.             MoveDown = FALSE;
  3245.         }
  3246.     }
  3247.  
  3248.     if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
  3249.     {
  3250.         if(ThisTag -> ti_Data)
  3251.         {
  3252.             Left = SZ_WindowWidth - INTERWIDTH - Width;
  3253.  
  3254.             MoveDown = FALSE;
  3255.         }
  3256.     }
  3257.  
  3258.     if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
  3259.     {
  3260.         if(ThisTag -> ti_Data)
  3261.         {
  3262.             Left = (SZ_WindowWidth - Width) / 2;
  3263.  
  3264.             MoveDown = FALSE;
  3265.         }
  3266.     }
  3267.  
  3268.     if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
  3269.     {
  3270.         LONG Count = ThisTag -> ti_Data,Width = SZ_WindowWidth;
  3271.  
  3272.         if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  3273.         {
  3274.             Width -= ThisTag -> ti_Data - InterWidth;
  3275.  
  3276.             SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  3277.             SZ_GroupX    = Left = ThisTag -> ti_Data;
  3278.         }
  3279.         else
  3280.         {
  3281.             SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  3282.             SZ_GroupX    = Left = SZ_Left;
  3283.         }
  3284.  
  3285.         MoveDown = FALSE;
  3286.     }
  3287.     else
  3288.     {
  3289.         if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  3290.             Left = ThisTag -> ti_Data;
  3291.     }
  3292.  
  3293.     if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
  3294.     {
  3295.         if(ThisTag -> ti_Data)
  3296.         {
  3297.             SZ_GroupX += SZ_GroupDelta;
  3298.  
  3299.             Left = SZ_GroupX;
  3300.  
  3301.             MoveDown = FALSE;
  3302.         }
  3303.     }
  3304.  
  3305.     if(ThisTag = FindTagItem(SZ_UseTop,TagList))
  3306.         SZ_CurrentTop = ThisTag -> ti_Data;
  3307.  
  3308.     Box -> Left        = Left;
  3309.     Box -> Top        = SZ_CurrentTop;
  3310.     Box -> Width        = Width;
  3311.     Box -> Height        = Height;
  3312.  
  3313.     Box -> LineWidth    = Chars * SZ_AverageGlyphWidth;
  3314.     Box -> LineHeight    = SZ_TextFont -> tf_YSize;
  3315.  
  3316.     Box -> NumChars        = Chars;
  3317.     Box -> NumLines        = Lines;
  3318.  
  3319.     Box -> TitleFgPen    = SZ_TextPen;
  3320.     Box -> TitleBgPen    = 0;
  3321.     Box -> TextPen        = SZ_TextPen;
  3322.  
  3323.     if(!(Box -> Title = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
  3324.     {
  3325.         SZ_FreeBox(Box);
  3326.  
  3327.         return(NULL);
  3328.     }
  3329.  
  3330.     if(!(Box -> Text = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
  3331.     {
  3332.         SZ_FreeBox(Box);
  3333.  
  3334.         return(NULL);
  3335.     }
  3336.  
  3337.     for(i = 0 ; i < Lines ; i++)
  3338.     {
  3339.         if(!(Box -> Text[i] = (STRPTR)AllocVec(Chars + 1,MEMF_ANY | MEMF_CLEAR)))
  3340.         {
  3341.             SZ_FreeBox(Box);
  3342.  
  3343.             return(NULL);
  3344.         }
  3345.     }
  3346.  
  3347.     if(SetBelow)
  3348.         MoveDown = FALSE;
  3349.  
  3350.     if(MoveDown)
  3351.     {
  3352.         SZ_CurrentTop = SZ_CurrentTop + Height + InterHeight;
  3353.  
  3354.         if(SZ_CurrentTop > SZ_WindowHeight)
  3355.             SZ_WindowHeight = SZ_CurrentTop;
  3356.     }
  3357.     else
  3358.     {
  3359.         if(SZ_CurrentTop + Height + InterHeight > SZ_WindowHeight)
  3360.             SZ_WindowHeight = SZ_CurrentTop + Height + InterHeight;
  3361.  
  3362.         SZ_MaxWidth = 0;
  3363.     }
  3364.  
  3365.     if(Width > SZ_MaxWidth)
  3366.         SZ_MaxWidth = Width;
  3367.  
  3368.     if(Left + SZ_MaxWidth + INTERWIDTH > SZ_WindowWidth)
  3369.         SZ_WindowWidth = Left + SZ_MaxWidth + INTERWIDTH;
  3370.  
  3371.     if(!SetLeft)
  3372.         SZ_CurrentLeft = Left;
  3373.  
  3374.     if(!(*FirstBox))
  3375.         *FirstBox = Box;
  3376.     else
  3377.     {
  3378.         struct TextBox *CurrentBox = *FirstBox;
  3379.  
  3380.         while(CurrentBox -> NextBox)
  3381.             CurrentBox = CurrentBox -> NextBox;
  3382.  
  3383.         CurrentBox -> NextBox = Box;
  3384.     }
  3385.  
  3386.     return(Box);
  3387. }
  3388.  
  3389.     /* SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...):
  3390.      *
  3391.      *    Set the titles displayed in a text box.
  3392.      */
  3393.  
  3394. VOID __stdargs
  3395. SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...)
  3396. {
  3397.     if(Box)
  3398.     {
  3399.         STRPTR    *Data = &Array;
  3400.         LONG     i = 0;
  3401.  
  3402.         while(*Data != NULL)
  3403.         {
  3404.             if(i < Box -> NumLines)
  3405.                 Box -> Title[i++] = *Data;
  3406.  
  3407.             Data++;
  3408.         }
  3409.     }
  3410. }
  3411.  
  3412.     /* SZ_SetLine():
  3413.      *
  3414.      *    Print a string into a text box, plain version.
  3415.      */
  3416.  
  3417. VOID __regargs
  3418. SZ_SetLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String)
  3419. {
  3420.     BYTE         FgPen    = ReadAPen(RPort),
  3421.              BgPen    = ReadBPen(RPort),
  3422.              DrMd    = ReadDrMd(RPort);
  3423.     struct TextFont    *Font    = RPort -> Font;
  3424.  
  3425.     LONG         Width,Len,
  3426.              Left    = Box -> Left + 4,
  3427.              Top    = Box -> Top + 2 + Line * Box -> LineHeight;
  3428.  
  3429.     if(DrMd != JAM2)
  3430.         SetDrMd(RPort,JAM2);
  3431.  
  3432.     if(FgPen != Box -> TextPen)
  3433.         SetAPen(RPort,Box -> TextPen);
  3434.  
  3435.     if(BgPen != 0)
  3436.         SetBPen(RPort,0);
  3437.  
  3438.     if(Font != UserTextFont)
  3439.         SetFont(RPort,UserTextFont);
  3440.  
  3441.     if(Len = strlen(String))
  3442.     {
  3443.         if(Len > Box -> NumChars)
  3444.             Len = Box -> NumChars;
  3445.  
  3446.         Width = TextLength(RPort,String,Len);
  3447.  
  3448.         Move(RPort,Left,Top + RPort -> Font -> tf_Baseline);
  3449.         Text(RPort,String,Len);
  3450.     }
  3451.     else
  3452.         Width = 0;
  3453.  
  3454.     if(Width != Box -> LineWidth)
  3455.     {
  3456.         if(FgPen != 0)
  3457.         {
  3458.             SetAPen(RPort,0);
  3459.  
  3460.             RectFill(RPort,Left + Width,Top,Left + Box -> LineWidth - 1,Top + Box -> LineHeight - 1);
  3461.  
  3462.             SetAPen(RPort,FgPen);
  3463.         }
  3464.         else
  3465.             RectFill(RPort,Left + Width,Top,Left + Box -> LineWidth - 1,Top + Box -> LineHeight - 1);
  3466.     }
  3467.  
  3468.     if(DrMd != JAM2)
  3469.         SetDrMd(RPort,DrMd);
  3470.  
  3471.     if(String != Box -> Text[Line])
  3472.     {
  3473.         if(Len > 0)
  3474.             memcpy(Box -> Text[Line],String,Len);
  3475.  
  3476.         Box -> Text[Line][Len] = 0;
  3477.     }
  3478.  
  3479.     if(Font != UserTextFont)
  3480.         SetFont(RPort,Font);
  3481.  
  3482.     if(BgPen != 0)
  3483.         SetBPen(RPort,BgPen);
  3484.  
  3485.     SetAPen(RPort,FgPen);
  3486. }
  3487.  
  3488.     /* SZ_PrintLine():
  3489.      *
  3490.      *    Print a string into a text box, varargs version.
  3491.      */
  3492.  
  3493. VOID __stdargs
  3494. SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...)
  3495. {
  3496.     extern VOID __stdargs VSPrintf(APTR,STRPTR,va_list);
  3497.  
  3498.     va_list    VarArgs;
  3499.     UBYTE    Buffer[256];
  3500.  
  3501.     va_start(VarArgs,String);
  3502.     VSPrintf(Buffer,String,VarArgs);
  3503.     va_end(VarArgs);
  3504.  
  3505.     SZ_SetLine(RPort,Box,Line,Buffer);
  3506. }
  3507.  
  3508.     /* SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box):
  3509.      *
  3510.      *    (Re-)Draw a text box.
  3511.      */
  3512.  
  3513. VOID __regargs
  3514. SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box)
  3515. {
  3516.     if(Box)
  3517.     {
  3518.         LONG         LineY,i,Len,FgPen = ReadAPen(RPort),BgPen = ReadBPen(RPort),DrMd = ReadDrMd(RPort);
  3519.         struct TextFont    *Font = RPort -> Font;
  3520.  
  3521.         if(Font != UserTextFont)
  3522.             SetFont(RPort,UserTextFont);
  3523.  
  3524.         if(FgPen != 0)
  3525.         {
  3526.             SetAPen(RPort,0);
  3527.  
  3528.             RectFill(RPort,Box -> Left,Box -> Top,Box -> Left + Box -> Width - 1,Box -> Top + Box -> Height - 1);
  3529.  
  3530.             SetAPen(RPort,FgPen);
  3531.         }
  3532.         else
  3533.             RectFill(RPort,Box -> Left,Box -> Top,Box -> Left + Box -> Width - 1,Box -> Top + Box -> Height - 1);
  3534.  
  3535.         DrawBevelBox(RPort,Box -> Left,Box -> Top,Box -> Width,Box -> Height,
  3536.             GT_VisualInfo,    VisualInfo,
  3537.             GTBB_Recessed,    TRUE,
  3538.         TAG_DONE);
  3539.  
  3540.         LineY = Box -> Top + 2 + RPort -> Font -> tf_Baseline;
  3541.  
  3542.         SetAPen(RPort,Box -> TitleFgPen);
  3543.         SetBPen(RPort,Box -> TitleBgPen);
  3544.         SetDrMd(RPort,JAM2);
  3545.  
  3546.         for(i = 0 ; i < Box -> NumLines ; i++)
  3547.         {
  3548.             if(Len = strlen(Box -> Title[i]))
  3549.             {
  3550.                 Move(RPort,Box -> Left - INTERWIDTH - TextLength(RPort,Box -> Title[i],Len),LineY);
  3551.                 Text(RPort,Box -> Title[i],Len);
  3552.             }
  3553.  
  3554.             LineY += Box -> LineHeight;
  3555.         }
  3556.  
  3557.         for(i = 0 ; i < Box -> NumLines ; i++)
  3558.             SZ_PrintLine(RPort,Box,i,Box -> Text[i]);
  3559.  
  3560.         SetAPen(RPort,FgPen);
  3561.         SetBPen(RPort,BgPen);
  3562.  
  3563.         SetDrMd(RPort,DrMd);
  3564.  
  3565.         if(Font != UserTextFont)
  3566.             SetFont(RPort,Font);
  3567.     }
  3568. }
  3569.  
  3570.     /* SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox):
  3571.      *
  3572.      *    (Re-)Draw a number of text boxes.
  3573.      */
  3574.  
  3575. VOID __regargs
  3576. SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox)
  3577. {
  3578.     do
  3579.         SZ_DrawBox(RPort,FirstBox);
  3580.     while(FirstBox = FirstBox -> NextBox);
  3581. }
  3582.  
  3583.     /* SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top):
  3584.      *
  3585.      *    Change the location of a text box.
  3586.      */
  3587.  
  3588. VOID __regargs
  3589. SZ_MoveBox(struct TextBox *Box,LONG Left,LONG Top)
  3590. {
  3591.     Box -> Left    += Left;
  3592.     Box -> Top    += Top;
  3593. }
  3594.  
  3595.     /* SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
  3596.      *
  3597.      *    Change the locations of a number of text boxes.
  3598.      */
  3599.  
  3600. VOID __regargs
  3601. SZ_MoveBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
  3602. {
  3603.     do
  3604.         SZ_MoveBox(FirstBox,Left,Top);
  3605.     while(FirstBox = FirstBox -> NextBox);
  3606. }
  3607.  
  3608.     /* SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top):
  3609.      *
  3610.      *    Set the location of a text box.
  3611.      */
  3612.  
  3613. VOID __regargs
  3614. SZ_SetBox(struct TextBox *Box,LONG Left,LONG Top)
  3615. {
  3616.     if(Left >= 0)
  3617.         Box -> Left = Left;
  3618.  
  3619.     if(Top >= 0)
  3620.         Box -> Top = Top;
  3621. }
  3622.  
  3623.     /* SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top):
  3624.      *
  3625.      *    Set the locations of a number of text boxes.
  3626.      */
  3627.  
  3628. VOID __regargs
  3629. SZ_SetBoxes(struct TextBox *FirstBox,LONG Left,LONG Top)
  3630. {
  3631.     do
  3632.         SZ_SetBox(FirstBox,Left,Top);
  3633.     while(FirstBox = FirstBox -> NextBox);
  3634. }
  3635.  
  3636.     /* SZ_GetBoxInfo(struct TextBox *Box,LONG Type):
  3637.      *
  3638.      *    Query information on a certain text box.
  3639.      */
  3640.  
  3641. LONG __regargs
  3642. SZ_GetBoxInfo(struct TextBox *Box,LONG Type)
  3643. {
  3644.     switch(Type)
  3645.     {
  3646.         case BOX_LEFT:
  3647.  
  3648.             return(Box -> Left);
  3649.  
  3650.         case BOX_TOP:
  3651.  
  3652.             return(Box -> Top);
  3653.  
  3654.         case BOX_WIDTH:
  3655.  
  3656.             return(Box -> Width);
  3657.  
  3658.         case BOX_HEIGHT:
  3659.  
  3660.             return(Box -> Height);
  3661.  
  3662.         default:
  3663.  
  3664.             return(0);
  3665.     }
  3666. }
  3667.