home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / amiga / comms / comprgs / term232.lha / Source_Code / termSource / termGadTools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-18  |  51.8 KB  |  2,546 lines

  1. /*
  2. **    $Id: termGadTools.c,v 1.3 92/08/15 20:14:05 olsen Sta Locker: olsen $
  3. **    $Revision: 1.3 $
  4. **    $Date: 92/08/15 20:14:05 $
  5. **
  6. **    GadTools object management support routines
  7. **
  8. **    Copyright ⌐ 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12.     /* Some includes for starters. */
  13.  
  14. #include <intuition/intuition.h>
  15. #include <libraries/gadtools.h>
  16. #include <intuition/sghooks.h>
  17. #include <utility/tagitem.h>
  18. #include <exec/memory.h>
  19.  
  20. #include <clib/intuition_protos.h>
  21. #include <clib/utility_protos.h>
  22. #include <clib/exec_protos.h>
  23.  
  24. #include <stdarg.h>
  25.  
  26.     /* User interface definitions. */
  27.  
  28. #define SZLV_Display    1        /* Listview includes display */
  29. #define SZLV_String    2        /* Listview includes string */
  30.  
  31. #define SZ_Adjust    TAG_USER+1    /* Adjust object */
  32. #define SZ_AutoWidth    TAG_USER+2    /* Use default width? */
  33. #define SZ_AlignExtra    TAG_USER+3    /* Add extra space to top edge */
  34. #define SZ_NewColumn    TAG_USER+4    /* Start new column */
  35. #define SZ_Lines    TAG_USER+5    /* Number of lines in object */
  36. #define SZ_Chars    TAG_USER+6    /* Number of chars (width) in object */
  37. #define SZ_AlignLeft    TAG_USER+7    /* Align to left border */
  38. #define SZ_AlignRight    TAG_USER+8    /* Align to right border */
  39. #define SZ_AlignCentre    TAG_USER+9    /* Centre it */
  40. #define SZ_AlignBottom    TAG_USER+10    /* Align to window bottom */
  41. #define SZ_GroupCount    TAG_USER+11    /* Create a group with N objects */
  42. #define SZ_GroupNext    TAG_USER+12    /* Skip to next position */
  43. #define SZ_SetLeft    TAG_USER+13    /* Place left to current object, don't touch the left edge position, though. */
  44. #define SZ_SetBelow    TAG_USER+14    /* Place below current object, don't touch the top edge position, though. */
  45. #define SZ_UseLeft    TAG_USER+15    /* Use this coordinate as left edge. */
  46. #define SZ_UseTop    TAG_USER+16    /* Use this coordinate as top edge. */
  47. #define SZ_UseWidth    TAG_USER+17    /* Use this gadget width. */
  48. #define SZ_UseHeight    TAG_USER+18    /* Use this gadget height. */
  49. #define SZ_FullWidth    TAG_USER+19    /* Use full window width for gadget. */
  50. #define SZ_FullHeight    TAG_USER+20    /* Use full window height for gadget. */
  51.  
  52.     /* Some #define values which may not yet be available in
  53.      * every include file set.
  54.      */
  55.  
  56. #ifndef GTMN_NewLookMenus
  57. #define GTMN_NewLookMenus    (GT_TagBase+67)
  58. #endif    /* GTMN_NewLookMenus */
  59.  
  60. #ifndef WA_NewLookMenus
  61. #define WA_NewLookMenus        (WA_Dummy+0x30)
  62. #endif    /* WA_NewLookMenus */
  63.  
  64. #ifndef GTCB_Scaled
  65. #define GTCB_Scaled        GT_TagBase+68
  66. #endif    /* GTCB_Scaled */
  67.  
  68. #ifndef GTMX_Scaled
  69. #define GTMX_Scaled        GT_TagBase+69
  70. #endif    /* GTMX_Scaled */
  71.  
  72. enum    {    COLOUR_AMIGA,COLOUR_EIGHT,COLOUR_SIXTEEN,COLOUR_MONO };
  73.  
  74.     /* term configuration. */
  75.  
  76. struct Configuration
  77. {
  78.     /* Serial Preferences. */
  79.  
  80.     ULONG    BaudRate;
  81.     BYTE    BitsPerChar;
  82.     BYTE    Parity;
  83.     BYTE    StopBits;
  84.     BYTE    Handshaking;
  85.     BYTE    Duplex;
  86.     BYTE    HighSpeed;
  87.     ULONG    BreakLength;
  88.     UBYTE    SerialDevice[40];
  89.     LONG    UnitNumber;
  90.  
  91.     /* Modem Preferences. */
  92.  
  93.     UBYTE    ModemInit[80];
  94.     UBYTE     ModemExit[80];
  95.     UBYTE     ModemHangup[80];
  96.     UBYTE    DialPrefix[80];
  97.     LONG    RedialDelay;
  98.     LONG    DialRetries;
  99.     LONG    DialTimeout;
  100.     BYTE    ConnectAutoCapture;
  101.     BYTE    ConnectAutoBaud;
  102.     BYTE    LogActions;
  103.     UBYTE    NoCarrier[16];
  104.     UBYTE    Connect[16];
  105.     UBYTE    Voice[16];
  106.     UBYTE    Ring[16];
  107.     UBYTE    Busy[16];
  108.  
  109.     /* Transfer Preferences. */
  110.  
  111.     UBYTE    Protocol[40];
  112.  
  113.     /* Startup macro. */
  114.  
  115.     UBYTE    StartupMacro[256];
  116.  
  117.     /* Macro Preferences. */
  118.  
  119.     UBYTE    MacroFile[256];
  120.  
  121.     /* Screen Preferences. */
  122.  
  123.     ULONG    DisplayMode;
  124.     UWORD    Colours[16];
  125.     BYTE    MakeScreenPublic;
  126.     BYTE    ShanghaiWindows;
  127.  
  128.     /* Terminal Preferences. */
  129.  
  130.     BYTE    CaptureFilter;
  131.     BYTE    DestructiveBackspace;
  132.     BYTE    AudibleBell;
  133.     BYTE    VisibleBell;
  134.     BYTE    EightyColumns;
  135.     BYTE    DisableBlinking;
  136.     BYTE    SendCR;
  137.     BYTE    SendLF;
  138.     BYTE    ColourMode;
  139.     BYTE    Emulation;
  140.     BYTE    Font;
  141.  
  142.     /* Emulation control. */
  143.  
  144.     BYTE    CursorApp;
  145.     BYTE    FontScale;
  146.     BYTE    JumpScroll;
  147.     BYTE    AutoWrap;
  148.     BYTE    CursorWrap;
  149.     BYTE    NewLine;
  150.     BYTE    InsertChar;
  151.     BYTE    NumApp;
  152.  
  153.     /* Path Preferences. */
  154.  
  155.     UBYTE    DefaultStorage[256];
  156.  
  157.     UBYTE    TextUploadPath[256];
  158.     UBYTE    TextDownloadPath[256];
  159.  
  160.     UBYTE    ASCIIUploadPath[256];
  161.     UBYTE    ASCIIDownloadPath[256];
  162.  
  163.     UBYTE    BinaryUploadPath[256];
  164.     UBYTE    BinaryDownloadPath[256];
  165.  
  166.     UBYTE    CapturePath[256];
  167.     UBYTE    LogFile[256];
  168.     UBYTE    Editor[256];
  169.     UBYTE    BeepSound[256];
  170.  
  171.     /* Extension in version 1.9b */
  172.  
  173.     BYTE    SwapBSDelete;
  174.     BYTE    StripBit8;
  175.  
  176.     /* Some more extensions... */
  177.  
  178.     BYTE    RasterEnabled;
  179.  
  180.     UBYTE    EmulationName[256];
  181.  
  182.     /* Up-/Download Macros. */
  183.  
  184.     UBYTE    UploadMacro[256];
  185.     UBYTE    DownloadMacro[256];
  186.  
  187.     /* Default fast! macro file. */
  188.  
  189.     UBYTE    FastMacroFile[256];
  190.  
  191.     /* Program priority. */
  192.  
  193.     BYTE    Priority;
  194.  
  195.     /* Override transfer path. */
  196.  
  197.     BYTE    OverridePath;
  198.  
  199.     /* Backup config between switching to phone entries. */
  200.  
  201.     BYTE    BackupConfig;
  202.  
  203.     /* ZModem auto upload panel enabled? */
  204.  
  205.     BYTE    AutoUpload;
  206.  
  207.     /* No dialtone string. */
  208.  
  209.     UBYTE    NoDialTone[16];
  210.  
  211.     /* Check carrier upon `CARRIER LOST' message. */
  212.  
  213.     BYTE    CheckCarrier;
  214.  
  215.     /* Display the screen title bar? */
  216.  
  217.     BYTE    TitleBar;
  218.  
  219.     /* Display the status lines? */
  220.  
  221.     BYTE    StatusLine;
  222.  
  223.     BYTE    DropDTR;
  224.  
  225.     /* Custom keymap file name. */
  226.  
  227.     UBYTE    KeyMapName[40];
  228.  
  229.     /* Serial buffer size. */
  230.  
  231.     LONG    SerBuffSize;
  232.  
  233.     /* Maximum log book buffer size. */
  234.  
  235.     LONG    MaxLogBuffSize;
  236.  
  237.     /* Is the buffering enabled? */
  238.  
  239.     BYTE    BufferEnabled;
  240.  
  241.     /* Receive CR/LF as... */
  242.  
  243.     BYTE    ReceiveCR;
  244.     BYTE    ReceiveLF;
  245.  
  246.     /* Set `archived' bit on uploaded files. */
  247.  
  248.     BYTE    SetArchivedBit;
  249.  
  250.     /* Open the fast! macro panel on startup? */
  251.  
  252.     BYTE    OpenFastMacroPanel;
  253.  
  254.     /* Pass xON/xOFF through to modem? */
  255.  
  256.     BYTE    PassThrough;
  257.  
  258.     /* Use system DisplayBeep()? */
  259.  
  260.     BYTE    SystemBeep;
  261.     BYTE    Pad;
  262.  
  263.     /* Answerback message. */
  264.  
  265.     UBYTE    AnswerBack[41];
  266.     BYTE    Pad2;
  267.  
  268.     /* Font settings. */
  269.  
  270.     UBYTE    FontName[32];
  271.     WORD    FontHeight;
  272. };
  273.  
  274.     /* External data. */
  275.  
  276. extern struct Library        *GadToolsBase,
  277.                 *DiskfontBase;
  278. extern struct Gadget        *ActiveGadget;
  279. extern struct Configuration     Config;
  280. extern UBYTE             SharedBuffer[];
  281. extern APTR             VisualInfo;
  282. extern LONG             InterWidth,
  283.                  InterHeight;
  284.  
  285.     /* This structure will help us to remember the current state of
  286.      * a GadTools object.
  287.      */
  288.  
  289. struct GadgetSupportInfo
  290. {
  291.     struct GadgetSupportInfo    *PointBack;    /* Points back to itself. */
  292.     struct Gadget            *Gadget;    /* Points back to the host. */
  293.  
  294.     WORD                 Kind;        /* Item type (BUTTON_KIND, STRING_KIND, etc.) */
  295.     UBYTE                 Key;        /* The key to press. */
  296.     BYTE                 ReadOnly;    /* LISTVIEW_KIND only: is this a read-only object? */
  297.     LONG                 Current,    /* Current state or counter. */
  298.                      Min,        /* Minimum value for `Current'. */
  299.                      Max;        /* Maximum value for `Current'. */
  300. };
  301.  
  302.     /* A text box for several lines of text. */
  303.  
  304. struct TextBox
  305. {
  306.     struct TextBox    *NextBox;        /* Next box in chain. */
  307.  
  308.     LONG         Left,Top,        /* Position and size. */
  309.              Width,Height;
  310.  
  311.     LONG         LineWidth,        /* Line width in pixels. */
  312.              LineHeight;        /* Line height in pixels. */
  313.  
  314.     LONG         NumChars,        /* Number of chars per line. */
  315.              NumLines;        /* Number of lines. */
  316.  
  317.     STRPTR        *Title,            /* Line titles. */
  318.             *Text;            /* Line texts. */
  319.  
  320.     WORD         TextPen;
  321. };
  322.  
  323.     /* Sizing data. */
  324.  
  325. STATIC struct RastPort    *SZ_RPort;
  326. STATIC struct TextFont    *SZ_TextFont;
  327. STATIC struct Screen    *SZ_Screen;
  328.  
  329. STATIC LONG         SZ_Left,
  330.              SZ_Top,
  331.              SZ_WindowWidth,
  332.              SZ_WindowHeight;
  333.              SZ_CurrentLeft,
  334.              SZ_CurrentTop,
  335.              SZ_CurrentWidth,
  336.              SZ_MaxWidth,
  337.              SZ_GroupDelta,
  338.              SZ_GroupX,
  339.              SZ_WidthMax,
  340.              SZ_TextPen;
  341.  
  342.     /* Local routines. */
  343.  
  344. struct Gadget *            CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...);
  345. VOID                FreeGadgets(struct Gadget *GadgetList);
  346. VOID                GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...);
  347. VOID                GT_ReplyIMsg(struct IntuiMessage *Message);
  348.  
  349. VOID                KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *Class,LONG *Code);
  350.  
  351.     /* Sizing routines. */
  352.  
  353. LONG                SZ_GetWindowWidth(VOID);
  354. LONG                SZ_GetWindowHeight(VOID);
  355. LONG                SZ_GetLeftEdge(VOID);
  356. LONG                SZ_GetTopEdge(VOID);
  357. VOID __regargs            SZ_SetTopEdge(LONG Top);
  358. VOID __regargs            SZ_SetLeftEdge(LONG Left);
  359. VOID __regargs            SZ_SetAbsoluteTop(LONG Top);
  360. VOID __regargs            SZ_SetAbsoluteLeft(LONG Left);
  361. VOID __regargs            SZ_SetWidth(LONG Width);
  362. LONG                SZ_ResetMaxWidth(VOID);
  363. VOID __regargs            SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
  364.  
  365. VOID __regargs            SZ_GetDimension(LONG *Width,LONG *Height);
  366. LONG __regargs            SZ_TextWidth(STRPTR String);
  367. VOID __regargs            SZ_AddLeftOffset(LONG Offset);
  368. LONG __stdargs            SZ_LeftOffsetN(LONG DataArray,...);
  369. LONG __regargs            SZ_LeftOffsetDelta(LONG From,LONG To);
  370. VOID                SZ_SizeCleanup();
  371. BYTE __regargs            SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title);
  372. LONG __regargs            SZ_Height(UBYTE Type,LONG Lines,BYTE Display);
  373. LONG __regargs            SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices);
  374.  
  375.     /* Text box routines. */
  376.  
  377. VOID __regargs            SZ_FreeBox(struct TextBox *Box);
  378. VOID __regargs            SZ_FreeBoxes(struct TextBox *FirstBox);
  379. LONG __regargs            SZ_BoxWidth(LONG Chars);
  380. LONG __regargs            SZ_BoxHeight(LONG Lines);
  381. struct TextBox * __stdargs    SZ_CreateTextBox(struct TextBox **FirstBox,...);
  382. VOID __stdargs            SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...);
  383. VOID __stdargs            SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...);
  384. VOID __regargs            SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box);
  385. VOID __regargs            SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox);
  386.  
  387.     /* The original gadtools.library routines. */
  388.  
  389. struct Gadget *            OldCreateGadgetA(ULONG,struct Gadget *,struct NewGadget *,struct TagItem *);
  390. VOID                OldFreeGadget(struct Gadget *);
  391. VOID                OldGT_SetGadgetAttrsA(struct Gadget *,struct Window *,struct Requester *,struct TagItem *);
  392. VOID                OldGT_ReplyIMsg(struct IntuiMessage *);
  393.  
  394.     /* Pragma calls: the easy way. */
  395.  
  396. #pragma libcall GadToolsBase OldCreateGadgetA 1E A98004
  397. #pragma libcall GadToolsBase OldFreeGadgets 24 801
  398. #pragma libcall GadToolsBase OldGT_SetGadgetAttrsA 2A BA9804
  399. #pragma libcall GadToolsBase OldGT_ReplyIMsg 4E 901
  400.  
  401.     /* CreateGadget():
  402.      *
  403.      *    A frontend to the original routine.
  404.      */
  405.  
  406. struct Gadget *
  407. CreateGadget(ULONG Kind,struct Gadget *Previous,struct NewGadget *New,...)
  408. {
  409.     STATIC struct NewGadget         Backup;
  410.  
  411.     va_list                 VarArgs;
  412.     struct TagItem            *TagList,
  413.                     *ThisTag,
  414.                      MoreTags[3];
  415.     struct GadgetSupportInfo    *Info = NULL;
  416.     WORD                 i;
  417.     UBYTE                 Underscore = 0;
  418.     struct Gadget            *Result;
  419.  
  420.         /* Get the tag item array. */
  421.  
  422.     va_start(VarArgs,New);
  423.  
  424.         /* Make a backup copy of the original NewGadget structure,
  425.          * we may want to modify it.
  426.          */
  427.  
  428.     CopyMem(New,&Backup,sizeof(struct NewGadget));
  429.  
  430.     New = &Backup;
  431.  
  432.         /* Get the tag item list. */
  433.  
  434.     TagList = (struct TagItem *)VarArgs;
  435.  
  436.         /* Try to find the SZ_Adjust tag item. If found, we are to
  437.          * apply our formatting functions to it.
  438.          */
  439.  
  440.     if(ThisTag = FindTagItem(SZ_Adjust,TagList))
  441.     {
  442.         if(ThisTag -> ti_Data)
  443.         {
  444.             STRPTR    *Labels = NULL;
  445.             LONG     Width,
  446.                  Height,
  447.                  Left = SZ_CurrentLeft;
  448.             BYTE     AutoWidth    = FALSE,
  449.                  MoveDown    = TRUE,
  450.                  SaveWidth    = TRUE,
  451.                  SetLeft    = FALSE,
  452.                  SetBelow    = FALSE;
  453.  
  454.                 /* Are we to leave the left edge untouched? */
  455.  
  456.             if(ThisTag = FindTagItem(SZ_SetLeft,TagList))
  457.                 SetLeft = ThisTag -> ti_Data;
  458.  
  459.                 /* Are we to leave the top edge untouched? */
  460.  
  461.             if(ThisTag = FindTagItem(SZ_SetBelow,TagList))
  462.                 SetBelow = ThisTag -> ti_Data;
  463.  
  464.                 /* Are we to align the object to the
  465.                  * window bottom?
  466.                  */
  467.  
  468.             if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
  469.             {
  470.                 if(ThisTag -> ti_Data)
  471.                     SZ_CurrentTop = SZ_WindowHeight;
  472.             }
  473.  
  474.                 /* Are we to add extra space to the
  475.                  * object top edge?
  476.                  */
  477.  
  478.             if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
  479.             {
  480.                 if(ThisTag -> ti_Data)
  481.                     SZ_CurrentTop += InterHeight;
  482.             }
  483.  
  484.                 /* Are we to start a new column? */
  485.  
  486.             if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
  487.             {
  488.                 if(ThisTag -> ti_Data)
  489.                 {
  490.                     SZ_CurrentTop    = SZ_Top;
  491.                     Left        = Left + SZ_MaxWidth + InterWidth;
  492.  
  493.                     SZ_MaxWidth    = 0;
  494.                 }
  495.             }
  496.  
  497.                 /* Is the object to contain a certain
  498.                  * number of lines?
  499.                  */
  500.  
  501.             if(ThisTag = FindTagItem(SZ_Lines,TagList))
  502.             {
  503.                 LONG Lines = (LONG)ThisTag -> ti_Data;
  504.  
  505.                     /* Is it a listview object? */
  506.  
  507.                 if(Kind == LISTVIEW_KIND)
  508.                 {
  509.                         /* Determine height of object. */
  510.  
  511.                     if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
  512.                     {
  513.                         if(ThisTag -> ti_Data)
  514.                             Height = SZ_Height(Kind,Lines,SZLV_String);
  515.                         else
  516.                             Height = SZ_Height(Kind,Lines,SZLV_Display);
  517.                     }
  518.                     else
  519.                         Height = SZ_Height(Kind,Lines,NULL);
  520.                 }
  521.                 else
  522.                     Height = SZ_Height(Kind,Lines,NULL);
  523.             }
  524.             else
  525.             {
  526.                     /* If this is a MX kind object,
  527.                      * determine the number of lines
  528.                      * by looking at the labels.
  529.                      */
  530.  
  531.                 if(ThisTag = FindTagItem(GTMX_Labels,TagList))
  532.                 {
  533.                     STRPTR    *Choices;
  534.                     LONG     Lines = 0;
  535.  
  536.                     Labels = Choices = (STRPTR *)ThisTag -> ti_Data;
  537.  
  538.                     while(*Choices++)
  539.                         Lines++;
  540.  
  541.                     Height = SZ_Height(Kind,Lines,NULL);
  542.                 }
  543.                 else
  544.                     Height = SZ_Height(Kind,0,NULL);
  545.             }
  546.  
  547.                 /* Is the object width derived from
  548.                  * certain magical calculations or
  549.                  * is it as wide as the default width?
  550.                  */
  551.  
  552.             if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  553.                 AutoWidth = ThisTag -> ti_Data;
  554.  
  555.                 /* Determine the width of the object. */
  556.  
  557.             if(!AutoWidth)
  558.             {
  559.                 STRPTR    *Choices    = NULL,
  560.                      Title        = NULL;
  561.                 LONG     Chars        = 0;
  562.  
  563.                     /* Determine number of characters in
  564.                      * this object.
  565.                      */
  566.  
  567.                 if(ThisTag = FindTagItem(SZ_Chars,TagList))
  568.                     Chars = ThisTag -> ti_Data;
  569.  
  570.                     /* If this is a button object,
  571.                      * calculate the width by looking
  572.                      * at the title.
  573.                      */
  574.  
  575.                 if(Kind == BUTTON_KIND && New -> ng_GadgetText)
  576.                     Title = New -> ng_GadgetText;
  577.  
  578.                     /* If this is a cycle object,
  579.                      * take a look at the labels.
  580.                      */
  581.  
  582.                 if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  583.                     Choices = (STRPTR *)ThisTag -> ti_Data;
  584.  
  585.                     /* If this is a listview object,
  586.                      * take a look at the list.
  587.                      */
  588.  
  589.                 if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  590.                 {
  591.                     if(ThisTag -> ti_Data != ~0)
  592.                     {
  593.                         struct List    *List = (struct List *)ThisTag -> ti_Data;
  594.                         struct Node    *Node;
  595.                         LONG         Len;
  596.  
  597.                         Node = List -> lh_Head;
  598.  
  599.                         while(Node -> ln_Succ)
  600.                         {
  601.                             if((Len = strlen(Node -> ln_Name)) > Chars)
  602.                                 Chars = Len;
  603.  
  604.                             Node = Node -> ln_Succ;
  605.                         }
  606.                     }
  607.                 }
  608.  
  609.                     /* Determine object width. */
  610.  
  611.                 Width = SZ_Width(Kind,Title,Chars,Choices);
  612.             }
  613.             else
  614.             {
  615.                     /* Use the default width. */
  616.  
  617.                 Width = SZ_CurrentWidth;
  618.  
  619.                     /* A checkbox object has a
  620.                      * fixed width. We don't want
  621.                      * any other objects to share
  622.                      * it.
  623.                      */
  624.  
  625.                 if(Kind == CHECKBOX_KIND)
  626.                 {
  627.                     Width = SZ_Width(Kind,NULL,0,NULL);
  628.  
  629.                     SaveWidth = FALSE;
  630.                 }
  631.             }
  632.  
  633.                 /* Are we to align this object to
  634.                  * the left window edge?
  635.                  */
  636.  
  637.             if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
  638.             {
  639.                 if(ThisTag -> ti_Data)
  640.                 {
  641.                     Left = SZ_Left;
  642.  
  643.                     MoveDown = FALSE;
  644.                 }
  645.             }
  646.  
  647.                 /* Are we to use a specific object width? */
  648.  
  649.             if(ThisTag = FindTagItem(SZ_UseWidth,TagList))
  650.                 Width = ThisTag -> ti_Data;
  651.  
  652.                 /* Are we to use a specific object height? */
  653.  
  654.             if(ThisTag = FindTagItem(SZ_UseHeight,TagList))
  655.                 Height = ThisTag -> ti_Data;
  656.  
  657.                 /* Are we to align this object to the
  658.                  * right window edge?
  659.                  */
  660.  
  661.             if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
  662.             {
  663.                 if(ThisTag -> ti_Data)
  664.                 {
  665.                     Left = SZ_WindowWidth - INTERWIDTH - Width;
  666.  
  667.                     MoveDown = FALSE;
  668.                 }
  669.             }
  670.  
  671.                 /* Are we to centre the object in
  672.                  * the window?
  673.                  */
  674.  
  675.             if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
  676.             {
  677.                 if(ThisTag -> ti_Data)
  678.                 {
  679.                     Left = (SZ_WindowWidth - Width) / 2;
  680.  
  681.                     MoveDown = FALSE;
  682.                 }
  683.             }
  684.  
  685.                 /* Are we to build a horizontal group
  686.                  * using the following objects?
  687.                  */
  688.  
  689.             if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
  690.             {
  691.                 LONG    Count = ThisTag -> ti_Data,
  692.                     Width = SZ_WindowWidth;
  693.  
  694.                     /* Use a specific left edge? */
  695.  
  696.                 if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  697.                 {
  698.                     Width -= ThisTag -> ti_Data - InterWidth;
  699.  
  700.                     SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  701.                     SZ_GroupX    = Left = ThisTag -> ti_Data;
  702.                 }
  703.                 else
  704.                 {
  705.                     SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  706.                     SZ_GroupX    = Left = SZ_Left;
  707.                 }
  708.  
  709.                 MoveDown = FALSE;
  710.             }
  711.             else
  712.             {
  713.                 if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  714.                     Left = ThisTag -> ti_Data;
  715.             }
  716.  
  717.                 /* Skip to the next group item position? */
  718.  
  719.             if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
  720.             {
  721.                 if(ThisTag -> ti_Data)
  722.                 {
  723.                     SZ_GroupX += SZ_GroupDelta;
  724.  
  725.                     Left = SZ_GroupX;
  726.  
  727.                     MoveDown = FALSE;
  728.                 }
  729.             }
  730.  
  731.                 /* Determine default label placement. */
  732.  
  733.             switch(Kind)
  734.             {
  735.                 case MX_KIND:
  736.                 case CHECKBOX_KIND:    New -> ng_Flags    = (New -> ng_Flags & ~(PLACETEXT_LEFT|PLACETEXT_RIGHT|PLACETEXT_ABOVE|PLACETEXT_BELOW|PLACETEXT_IN)) | PLACETEXT_LEFT;
  737.  
  738.                             SaveWidth = FALSE;
  739.  
  740.                             break;
  741.  
  742.                 default:        if(New -> ng_Flags & PLACETEXT_ABOVE)
  743.                                 SZ_CurrentTop += INTERHEIGHT + SZ_TextFont -> tf_YSize;
  744.  
  745.                             break;
  746.             }
  747.  
  748.                 /* Gadget is to be as wide as the entire window? */
  749.  
  750.             if(ThisTag = FindTagItem(SZ_FullWidth,TagList))
  751.             {
  752.                 if(ThisTag -> ti_Data)
  753.                     Width = SZ_WindowWidth - 2 * INTERWIDTH;
  754.             }
  755.  
  756.                 /* Gadget is to be as high as the entire window? */
  757.  
  758.             if(ThisTag = FindTagItem(SZ_FullHeight,TagList))
  759.             {
  760.                 if(ThisTag -> ti_Data)
  761.                     Height = SZ_WindowHeight - InterHeight - SZ_Top;
  762.             }
  763.  
  764.                 /* Use a specific top edge? */
  765.  
  766.             if(ThisTag = FindTagItem(SZ_UseTop,TagList))
  767.                 SZ_CurrentTop = ThisTag -> ti_Data;
  768.  
  769.                 /* Fill in the NewGadget. */
  770.  
  771.             New -> ng_LeftEdge    = Left;
  772.             New -> ng_TopEdge    = SZ_CurrentTop;
  773.             New -> ng_Width        = Width;
  774.             New -> ng_Height    = Height;
  775.  
  776.                 /* Add the default tags. */
  777.  
  778.             switch(Kind)
  779.             {
  780.                 case PALETTE_KIND:    MoreTags[0] . ti_Tag    = GTPA_IndicatorWidth;
  781.                             MoreTags[0] . ti_Data    = Width / 4;
  782.  
  783.                             MoreTags[1] . ti_Tag    = GTPA_IndicatorHeight;
  784.                             MoreTags[1] . ti_Data    = Height;
  785.  
  786.                             MoreTags[2] . ti_Tag    = TAG_MORE;
  787.                             MoreTags[2] . ti_Data    = (ULONG)TagList;
  788.  
  789.                             TagList = MoreTags;
  790.  
  791.                             break;
  792.  
  793.                 case LISTVIEW_KIND:    MoreTags[0] . ti_Tag    = GTLV_ScrollWidth;
  794.                             MoreTags[0] . ti_Data    = 2 + 2 * SZ_TextFont -> tf_XSize + 2;
  795.  
  796.                             MoreTags[1] . ti_Tag    = TAG_MORE;
  797.                             MoreTags[1] . ti_Data    = (ULONG)TagList;
  798.  
  799.                             TagList = MoreTags;
  800.  
  801.                             break;
  802.  
  803.                 case CHECKBOX_KIND:    MoreTags[0] . ti_Tag    = GTCB_Scaled;
  804.                             MoreTags[0] . ti_Data    = TRUE;
  805.  
  806.                             MoreTags[1] . ti_Tag    = TAG_MORE;
  807.                             MoreTags[1] . ti_Data    = (ULONG)TagList;
  808.  
  809.                             TagList = MoreTags;
  810.  
  811.                             break;
  812.  
  813.                 case MX_KIND:        MoreTags[0] . ti_Tag    = GTMX_Scaled;
  814.                             MoreTags[0] . ti_Data    = TRUE;
  815.  
  816.                             MoreTags[1] . ti_Tag    = TAG_MORE;
  817.                             MoreTags[1] . ti_Data    = (ULONG)TagList;
  818.  
  819.                             TagList = MoreTags;
  820.  
  821.                             break;
  822.  
  823.                 default:        break;
  824.             }
  825.  
  826.                 /* Restore default object width if necessary. */
  827.  
  828.             if(SaveWidth)
  829.                 SZ_CurrentWidth    = Width;
  830.  
  831.                 /* Are we to leave the top edge untouched? */
  832.  
  833.             if(SetBelow)
  834.                 MoveDown = FALSE;
  835.  
  836.             if(MoveDown)
  837.             {
  838.                     /* Move down to next object. */
  839.  
  840.                 SZ_CurrentTop = SZ_CurrentTop + Height + InterHeight;
  841.  
  842.                     /* Extend window height if necessary. */
  843.  
  844.                 if(SZ_CurrentTop > SZ_WindowHeight)
  845.                     SZ_WindowHeight = SZ_CurrentTop;
  846.             }
  847.             else
  848.             {
  849.                     /* Extend window height if necessary. */
  850.  
  851.                 if(SZ_CurrentTop + Height + InterHeight > SZ_WindowHeight)
  852.                     SZ_WindowHeight = SZ_CurrentTop + Height + InterHeight;
  853.  
  854.                 SZ_MaxWidth = 0;
  855.             }
  856.  
  857.                 /* Update maximum object width. */
  858.  
  859.             if(Width > SZ_MaxWidth)
  860.                 SZ_MaxWidth = Width;
  861.  
  862.                 /* Extend window width if necessary. */
  863.  
  864.             if(Left + SZ_MaxWidth + INTERWIDTH > SZ_WindowWidth)
  865.                 SZ_WindowWidth = Left + SZ_MaxWidth + INTERWIDTH;
  866.  
  867.                 /* Are we to leave the left edge untouched? */
  868.  
  869.             if(!SetLeft)
  870.                 SZ_CurrentLeft = Left;
  871.         }
  872.     }
  873.  
  874.         /* Now for keystroke activation... */
  875.  
  876.     switch(Kind)
  877.     {
  878.         case STRING_KIND:
  879.         case INTEGER_KIND:
  880.         case BUTTON_KIND:
  881.         case CHECKBOX_KIND:
  882.         case CYCLE_KIND:
  883.         case LISTVIEW_KIND:
  884.         case MX_KIND:
  885.         case PALETTE_KIND:
  886.         case SCROLLER_KIND:
  887.         case SLIDER_KIND:
  888.  
  889.                 /* Do we have an underscore character to
  890.                  * play with?
  891.                  */
  892.  
  893.             if(ThisTag = FindTagItem(GT_Underscore,TagList))
  894.                 Underscore = ThisTag -> ti_Data;
  895.  
  896.             if(Underscore)
  897.             {
  898.                     /* Do we have a gadget label? */
  899.  
  900.                 if(New -> ng_GadgetText)
  901.                 {
  902.                         /* Look for the underscore
  903.                          * character...
  904.                          */
  905.  
  906.                     for(i = 0 ; i < strlen(New -> ng_GadgetText) ; i++)
  907.                     {
  908.                         if(New -> ng_GadgetText[i] == Underscore)
  909.                         {
  910.                                 /* Is it a printable character? */
  911.  
  912.                             if(New -> ng_GadgetText[i + 1] > ' ')
  913.                             {
  914.                                     /* Create information buffer. */
  915.  
  916.                                 if(Info = (struct GadgetSupportInfo *)AllocMem(sizeof(struct GadgetSupportInfo),MEMF_ANY|MEMF_CLEAR))
  917.                                 {
  918.                                         /* Set up the default data. */
  919.  
  920.                                     Info -> PointBack    = Info;
  921.                                     Info -> Kind        = Kind;
  922.                                     Info -> Key        = New -> ng_GadgetText[i + 1];
  923.  
  924.                                         /* Add object-specific information. */
  925.  
  926.                                     if(Info -> Kind == PALETTE_KIND)
  927.                                     {
  928.                                         Info -> Current    = 1;
  929.                                         Info -> Max    = 1;
  930.                                     }
  931.  
  932.                                     if(Info -> Kind == LISTVIEW_KIND)
  933.                                         Info -> Current    = ~0;
  934.  
  935.                                     break;
  936.                                 }
  937.                             }
  938.                         }
  939.                     }
  940.                 }
  941.             }
  942.  
  943.             break;
  944.  
  945.         default:
  946.  
  947.             break;
  948.     }
  949.  
  950.         /* Fill in object info if available. */
  951.  
  952.     New -> ng_UserData = Info;
  953.  
  954.         /* Did we create any object info? */
  955.  
  956.     if(Info)
  957.     {
  958.         struct Node    *Node;
  959.         struct List    *List;
  960.         LONG         Count;
  961.         STRPTR        *Strings;
  962.  
  963.             /* The following code takes care of object-specific
  964.              * characteristics, such as currently selected items,
  965.              * current value, minimum value, maximum value, etc.
  966.              * and places them in the gadget info.
  967.              */
  968.  
  969.         switch(Kind)
  970.         {
  971.             case CHECKBOX_KIND:    if(ThisTag = FindTagItem(GTCB_Checked,TagList))
  972.                             Info -> Current = ThisTag -> ti_Data;
  973.  
  974.                         break;
  975.  
  976.             case CYCLE_KIND:    if(ThisTag = FindTagItem(GTCY_Active,TagList))
  977.                             Info -> Current = ThisTag -> ti_Data;
  978.  
  979.                         if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  980.                         {
  981.                             Count = 0;
  982.  
  983.                             if(Strings = (STRPTR *)ThisTag -> ti_Data)
  984.                             {
  985.                                 while(Strings[Count])
  986.                                     Count++;
  987.                             }
  988.  
  989.                             if(Count)
  990.                                 Info -> Max = Count - 1;
  991.                         }
  992.  
  993.                         break;
  994.  
  995.             case LISTVIEW_KIND:    if(ThisTag = FindTagItem(GTLV_Selected,TagList))
  996.                             Info -> Current = ThisTag -> ti_Data;
  997.  
  998.                         if(ThisTag = FindTagItem(GTLV_ReadOnly,TagList))
  999.                         {
  1000.                             if(ThisTag -> ti_Data)
  1001.                                 Info -> ReadOnly = TRUE;
  1002.                         }
  1003.  
  1004.                         if(ThisTag = FindTagItem(GTLV_ShowSelected,TagList))
  1005.                         {
  1006.                             if(ThisTag -> ti_Data)
  1007.                                 Info -> ReadOnly = FALSE;
  1008.                         }
  1009.  
  1010.                         if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  1011.                         {
  1012.                             Count = 0;
  1013.  
  1014.                             if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
  1015.                             {
  1016.                                 List = (struct List *)ThisTag -> ti_Data;
  1017.  
  1018.                                 Node = List -> lh_Head;
  1019.  
  1020.                                 while(Node -> ln_Succ)
  1021.                                 {
  1022.                                     Count++;
  1023.  
  1024.                                     Node = Node -> ln_Succ;
  1025.                                 }
  1026.                             }
  1027.  
  1028.                             if(Count)
  1029.                                 Info -> Max = Count - 1;
  1030.                         }
  1031.  
  1032.                         break;
  1033.  
  1034.             case MX_KIND:        if(ThisTag = FindTagItem(GTMX_Active,TagList))
  1035.                             Info -> Current = ThisTag -> ti_Data;
  1036.  
  1037.                         if(ThisTag = FindTagItem(GTMX_Labels,TagList))
  1038.                         {
  1039.                             Count = 0;
  1040.  
  1041.                             if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1042.                             {
  1043.                                 while(Strings[Count])
  1044.                                     Count++;
  1045.                             }
  1046.  
  1047.                             if(Count)
  1048.                                 Info -> Max = Count - 1;
  1049.                         }
  1050.  
  1051.                         break;
  1052.  
  1053.             case SCROLLER_KIND:    if(ThisTag = FindTagItem(GTSC_Top,TagList))
  1054.                             Info -> Current = ThisTag -> ti_Data;
  1055.  
  1056.                         if(ThisTag = FindTagItem(GTSC_Total,TagList))
  1057.                             Info -> Max = ThisTag -> ti_Data;
  1058.  
  1059.                         break;
  1060.  
  1061.             case SLIDER_KIND:    if(ThisTag = FindTagItem(GTSL_Level,TagList))
  1062.                             Info -> Current = ThisTag -> ti_Data;
  1063.  
  1064.                         if(ThisTag = FindTagItem(GTSL_Min,TagList))
  1065.                             Info -> Min = ThisTag -> ti_Data;
  1066.  
  1067.                         if(ThisTag = FindTagItem(GTSL_Max,TagList))
  1068.                             Info -> Max = ThisTag -> ti_Data;
  1069.  
  1070.                         break;
  1071.  
  1072.             case PALETTE_KIND:    if(ThisTag = FindTagItem(GTPA_Color,TagList))
  1073.                             Info -> Current = ThisTag -> ti_Data;
  1074.  
  1075.                         if(ThisTag = FindTagItem(GTPA_Depth,TagList))
  1076.                             Info -> Max = (1 << ((LONG)ThisTag -> ti_Data)) - 1;
  1077.  
  1078.                         break;
  1079.  
  1080.             default:        break;
  1081.         }
  1082.  
  1083.             /* Create the object and attach the info to it. */
  1084.  
  1085.         if(Result = OldCreateGadgetA(Kind,Previous,New,TagList))
  1086.             Info -> Gadget = Result;
  1087.         else
  1088.             FreeMem(Info,sizeof(struct GadgetSupportInfo));
  1089.     }
  1090.     else
  1091.         Result = OldCreateGadgetA(Kind,Previous,New,TagList);
  1092.  
  1093.     va_end(VarArgs);
  1094.  
  1095.     return(Result);
  1096. }
  1097.  
  1098.     /* GT_SetGadgetAttrs():
  1099.      *
  1100.      *    A frontend to the original routine.
  1101.      */
  1102.  
  1103. VOID
  1104. GT_SetGadgetAttrs(struct Gadget *Gadget,struct Window *Window,struct Requester *Requester,...)
  1105. {
  1106.     va_list                 VarArgs;
  1107.     struct TagItem            *TagList,
  1108.                     *ThisTag;
  1109.     struct GadgetSupportInfo    *Info;
  1110.  
  1111.         /* Get the tag item list. */
  1112.  
  1113.     va_start(VarArgs,Requester);
  1114.  
  1115.     TagList = (struct TagItem *)VarArgs;
  1116.  
  1117.         /* Does the object in question have an info structure attached? */
  1118.  
  1119.     if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  1120.     {
  1121.             /* Does the data look sensible? */
  1122.  
  1123.         if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  1124.         {
  1125.             struct Node    *Node;
  1126.             struct List    *List;
  1127.             LONG         Count;
  1128.             STRPTR        *Strings;
  1129.  
  1130.                 /* Update object-specific information. */
  1131.  
  1132.             switch(Info -> Kind)
  1133.             {
  1134.                 case CHECKBOX_KIND:    if(ThisTag = FindTagItem(GTCB_Checked,TagList))
  1135.                                 Info -> Current = ThisTag -> ti_Data;
  1136.  
  1137.                             break;
  1138.  
  1139.                 case CYCLE_KIND:    if(ThisTag = FindTagItem(GTCY_Active,TagList))
  1140.                                 Info -> Current = ThisTag -> ti_Data;
  1141.  
  1142.                             if(ThisTag = FindTagItem(GTCY_Labels,TagList))
  1143.                             {
  1144.                                 Count = 0;
  1145.  
  1146.                                 if(Strings = (STRPTR *)ThisTag -> ti_Data)
  1147.                                 {
  1148.                                     while(Strings[Count])
  1149.                                         Count++;
  1150.                                 }
  1151.  
  1152.                                 if(Count)
  1153.                                     Info -> Max = Count - 1;
  1154.                                 else
  1155.                                     Info -> Max = 0;
  1156.                             }
  1157.  
  1158.                             break;
  1159.  
  1160.                 case LISTVIEW_KIND:    if(ThisTag = FindTagItem(GTLV_Selected,TagList))
  1161.                                 Info -> Current = ThisTag -> ti_Data;
  1162.  
  1163.                             if(ThisTag = FindTagItem(GTLV_Labels,TagList))
  1164.                             {
  1165.                                 Count = 0;
  1166.  
  1167.                                 if(ThisTag -> ti_Data && ThisTag -> ti_Data != ~0)
  1168.                                 {
  1169.                                     List = (struct List *)ThisTag -> ti_Data;
  1170.  
  1171.                                     Node = List -> lh_Head;
  1172.  
  1173.                                     while(Node -> ln_Succ)
  1174.                                     {
  1175.                                         Count++;
  1176.  
  1177.                                         Node = Node -> ln_Succ;
  1178.                                     }
  1179.                                 }
  1180.  
  1181.                                 if(Count)
  1182.                                     Info -> Max = Count - 1;
  1183.                                 else
  1184.                                     Info -> Max = 0;
  1185.                             }
  1186.  
  1187.                             break;
  1188.  
  1189.                 case PALETTE_KIND:    if(ThisTag = FindTagItem(GTPA_Color,TagList))
  1190.                                 Info -> Current = ThisTag -> ti_Data;
  1191.  
  1192.                             break;
  1193.  
  1194.                 case MX_KIND:        if(ThisTag = FindTagItem(GTMX_Active,TagList))
  1195.                                 Info -> Current = ThisTag -> ti_Data;
  1196.  
  1197.                             break;
  1198.  
  1199.                 case SCROLLER_KIND:    if(ThisTag = FindTagItem(GTSC_Top,TagList))
  1200.                                 Info -> Current = ThisTag -> ti_Data;
  1201.  
  1202.                             if(ThisTag = FindTagItem(GTSC_Total,TagList))
  1203.                                 Info -> Max = ThisTag -> ti_Data;
  1204.  
  1205.                             break;
  1206.  
  1207.                 case SLIDER_KIND:    if(ThisTag = FindTagItem(GTSL_Level,TagList))
  1208.                                 Info -> Current = ThisTag -> ti_Data;
  1209.  
  1210.                             if(ThisTag = FindTagItem(GTSL_Min,TagList))
  1211.                                 Info -> Min = ThisTag -> ti_Data;
  1212.  
  1213.                             break;
  1214.  
  1215.                 default:        break;
  1216.             }
  1217.         }
  1218.     }
  1219.  
  1220.         /* Call the original routine. */
  1221.  
  1222.     OldGT_SetGadgetAttrsA(Gadget,Window,Requester,TagList);
  1223.  
  1224.     va_end(VarArgs);
  1225. }
  1226.  
  1227.     /* FreeGadgets(struct Gadget *GadgetList):
  1228.      *
  1229.      *    A frontend to the original routine.
  1230.      */
  1231.  
  1232. VOID
  1233. FreeGadgets(struct Gadget *GadgetList)
  1234. {
  1235.     struct Gadget            *Gadget = GadgetList;
  1236.     struct GadgetSupportInfo    *Info;
  1237.  
  1238.         /* Run down the gadget list. */
  1239.  
  1240.     while(Gadget)
  1241.     {
  1242.             /* Does it have an info structure attached?*/
  1243.  
  1244.         if(Info = (struct GadgetSupportInfo *)Gadget -> UserData)
  1245.         {
  1246.                 /* Does the data make sense? */
  1247.  
  1248.             if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  1249.                 FreeMem(Info,sizeof(struct GadgetSupportInfo));
  1250.         }
  1251.  
  1252.             /* Skip to next object. */
  1253.  
  1254.         Gadget = Gadget -> NextGadget;
  1255.     }
  1256.  
  1257.     OldFreeGadgets(GadgetList);
  1258. }
  1259.  
  1260.     /* GT_ReplyIMsg(struct IntuiMessage *Message):
  1261.      *
  1262.      *    A frontend to the original routine.
  1263.      */
  1264.  
  1265. VOID
  1266. GT_ReplyIMsg(struct IntuiMessage *Message)
  1267. {
  1268.         /* Is this really a message? */
  1269.  
  1270.     if(Message)
  1271.     {
  1272.             /* The following input event classes are likely to
  1273.              * affect a gadtools object.
  1274.              */
  1275.  
  1276.         if(Message -> Class == IDCMP_GADGETUP || Message -> Class == IDCMP_GADGETDOWN || Message -> Class == IDCMP_MOUSEMOVE)
  1277.         {
  1278.             struct Gadget *Gadget;
  1279.  
  1280.                 /* Take a look at the item attached. */
  1281.  
  1282.             if(Gadget = (struct Gadget *)Message -> IAddress)
  1283.             {
  1284.                 struct GadgetSupportInfo *Info = Gadget -> UserData;
  1285.  
  1286.                     /* If it's really a gadget, does it
  1287.                      * have an info structure attached?
  1288.                      */
  1289.  
  1290.                 if(Info)
  1291.                 {
  1292.                         /* Does the data make sense? */
  1293.  
  1294.                     if(Info -> PointBack == Info && Info -> Gadget == Gadget)
  1295.                     {
  1296.                         LONG Value = (WORD)Message -> Code;
  1297.  
  1298.                             /* Update the object information. */
  1299.  
  1300.                         switch(Info -> Kind)
  1301.                         {
  1302.                             case CHECKBOX_KIND:
  1303.  
  1304.                                 if(Gadget -> Flags & GFLG_SELECTED)
  1305.                                     Info -> Current = TRUE;
  1306.                                 else
  1307.                                     Info -> Current = FALSE;
  1308.  
  1309.                                 break;
  1310.  
  1311.                             case CYCLE_KIND:
  1312.  
  1313.                                 Info -> Current = Message -> Code;
  1314.  
  1315.                                 break;
  1316.  
  1317.                             case LISTVIEW_KIND:
  1318.  
  1319.                                 Info -> Current = Message -> Code;
  1320.  
  1321.                                 break;
  1322.  
  1323.                             case MX_KIND:
  1324.  
  1325.                                 Info -> Current = Message -> Code;
  1326.  
  1327.                                 break;
  1328.  
  1329.                             case SCROLLER_KIND:
  1330.  
  1331.                                 Info -> Current = Message -> Code;
  1332.  
  1333.                                 break;
  1334.  
  1335.                             case SLIDER_KIND:
  1336.  
  1337.                                 if(Info -> Min >= 0 && Value < 0)
  1338.                                     Info -> Current = Message -> Code;
  1339.                                 else
  1340.                                     Info -> Current = Value;
  1341.  
  1342.                                 break;
  1343.  
  1344.                             case PALETTE_KIND:
  1345.  
  1346.                                 Info -> Current = Message -> Code;
  1347.  
  1348.                                 break;
  1349.  
  1350.                             default:
  1351.  
  1352.                                 break;
  1353.                         }
  1354.                     }
  1355.                 }
  1356.             }
  1357.         }
  1358.     }
  1359.  
  1360.         /* Reply the message correctly. */
  1361.  
  1362.     OldGT_ReplyIMsg(Message);
  1363. }
  1364.  
  1365.     /* KeySelect():
  1366.      *
  1367.      *    Handles gadget keystroke activation.
  1368.      */
  1369.  
  1370. VOID
  1371. KeySelect(struct Gadget **GadgetList,WORD Last,UBYTE Key,struct Window *Window,struct Gadget **Gadget,ULONG *Class,LONG *Code)
  1372. {
  1373.         /* If an escape code comes in and the window does in
  1374.          * fact have a close gadget, return a close window
  1375.          * event.
  1376.          */
  1377.  
  1378.     if(Key == '\033' && (Window -> Flags & WFLG_CLOSEGADGET))
  1379.         *Class = IDCMP_CLOSEWINDOW;
  1380.     else
  1381.     {
  1382.         struct GadgetSupportInfo    *Info;
  1383.         WORD                 i;
  1384.         BYTE                 Forward,
  1385.                          GotIt = FALSE;
  1386.  
  1387.             /* Run down all the gadgets. */
  1388.  
  1389.         for(i = 0 ; !GotIt && i <= Last ; i++)
  1390.         {
  1391.                 /* Is this gadget enabled? */
  1392.  
  1393.             if(!(GadgetList[i] -> Flags & GFLG_DISABLED))
  1394.             {
  1395.                     /* Does it have an info structure attached? */
  1396.  
  1397.                 if(Info = GadgetList[i] -> UserData)
  1398.                 {
  1399.                         /* Does it make sense? */
  1400.  
  1401.                     if(Info -> PointBack == Info && Info -> Gadget == GadgetList[i])
  1402.                     {
  1403.                             /* Do the keys match? */
  1404.  
  1405.                         if(ToUpper(Info -> Key) == ToUpper(Key))
  1406.                         {
  1407.                                 /* Are we cycle forward
  1408.                                  * or backwards?
  1409.                                  */
  1410.  
  1411.                             if(ToUpper(Info -> Key) == Key)
  1412.                                 Forward = FALSE;
  1413.                             else
  1414.                                 Forward = TRUE;
  1415.  
  1416.                                 /* Update the object information. */
  1417.  
  1418.                             switch(Info -> Kind)
  1419.                             {
  1420.                                 case STRING_KIND:
  1421.                                 case INTEGER_KIND:    ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
  1422.  
  1423.                                             *Class    = IDCMP_GADGETDOWN;
  1424.                                             *Code    = 0;
  1425.                                             *Gadget    = GadgetList[i];
  1426.  
  1427.                                             GotIt = TRUE;
  1428.  
  1429.                                             break;
  1430.  
  1431.                                 case BUTTON_KIND:    *Class    = IDCMP_GADGETUP;
  1432.                                             *Code    = 0;
  1433.                                             *Gadget    = GadgetList[i];
  1434.  
  1435.                                             GotIt = TRUE;
  1436.  
  1437.                                             break;
  1438.  
  1439.                                 case CHECKBOX_KIND:    GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1440.                                                 GTCB_Checked,    Info -> Current ? FALSE : TRUE,
  1441.                                             TAG_DONE);
  1442.  
  1443.                                             *Class    = IDCMP_GADGETUP;
  1444.                                             *Code    = Info -> Current;
  1445.                                             *Gadget    = GadgetList[i];
  1446.  
  1447.                                             GotIt = TRUE;
  1448.  
  1449.                                             break;
  1450.  
  1451.                                 case CYCLE_KIND:    if(Forward)
  1452.                                             {
  1453.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1454.                                                     GTCY_Active,    (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
  1455.                                                 TAG_DONE);
  1456.                                             }
  1457.                                             else
  1458.                                             {
  1459.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1460.                                                     GTCY_Active,    Info -> Current ? Info -> Current - 1 : Info -> Max,
  1461.                                                 TAG_DONE);
  1462.                                             }
  1463.  
  1464.                                             *Class    = IDCMP_GADGETUP;
  1465.                                             *Code    = Info -> Current;
  1466.                                             *Gadget    = GadgetList[i];
  1467.  
  1468.                                             GotIt = TRUE;
  1469.  
  1470.                                             break;
  1471.  
  1472.                                 case LISTVIEW_KIND:    if(Forward)
  1473.                                             {
  1474.                                                 if(Info -> Current == ~0)
  1475.                                                     Info -> Current = -1;
  1476.  
  1477.                                                 if(Info -> Current < Info -> Max)
  1478.                                                 {
  1479.                                                     if(Info -> ReadOnly)
  1480.                                                     {
  1481.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1482.                                                             GTLV_Top,    Info -> Current + 1,
  1483.                                                         TAG_DONE);
  1484.                                                     }
  1485.                                                     else
  1486.                                                     {
  1487.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1488.                                                             GTLV_Selected,    Info -> Current + 1,
  1489.                                                             GTLV_Top,    Info -> Current + 1,
  1490.                                                         TAG_DONE);
  1491.                                                     }
  1492.  
  1493.                                                     *Class    = IDCMP_GADGETUP;
  1494.                                                     *Code    = Info -> Current;
  1495.                                                     *Gadget    = GadgetList[i];
  1496.                                                 }
  1497.                                             }
  1498.                                             else
  1499.                                             {
  1500.                                                 if(Info -> Current == ~0)
  1501.                                                     Info -> Current = Info -> Max + 1;
  1502.  
  1503.                                                 if(Info -> Current > Info -> Min)
  1504.                                                 {
  1505.                                                     if(Info -> ReadOnly)
  1506.                                                     {
  1507.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1508.                                                             GTLV_Top,    Info -> Current - 1,
  1509.                                                         TAG_DONE);
  1510.                                                     }
  1511.                                                     else
  1512.                                                     {
  1513.                                                         GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1514.                                                             GTLV_Selected,    Info -> Current - 1,
  1515.                                                             GTLV_Top,    Info -> Current - 1,
  1516.                                                         TAG_DONE);
  1517.                                                     }
  1518.  
  1519.                                                     *Class    = IDCMP_GADGETUP;
  1520.                                                     *Code    = Info -> Current;
  1521.                                                     *Gadget    = GadgetList[i];
  1522.                                                 }
  1523.                                             }
  1524.  
  1525.                                             GotIt = TRUE;
  1526.  
  1527.                                             break;
  1528.  
  1529.                                 case MX_KIND:        if(Forward)
  1530.                                             {
  1531.                                                 if(Info -> Current < Info -> Max)
  1532.                                                 {
  1533.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1534.                                                         GTMX_Active,    *Code = Info -> Current + 1,
  1535.                                                     TAG_DONE);
  1536.  
  1537.                                                     *Class    = IDCMP_GADGETUP;
  1538.                                                     *Code    = Info -> Current;
  1539.                                                     *Gadget    = GadgetList[i];
  1540.                                                 }
  1541.                                             }
  1542.                                             else
  1543.                                             {
  1544.                                                 if(Info -> Current > Info -> Min)
  1545.                                                 {
  1546.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1547.                                                         GTMX_Active,    *Code = Info -> Current - 1,
  1548.                                                     TAG_DONE);
  1549.  
  1550.                                                     *Class    = IDCMP_GADGETUP;
  1551.                                                     *Code    = Info -> Current;
  1552.                                                     *Gadget    = GadgetList[i];
  1553.                                                 }
  1554.                                             }
  1555.  
  1556.                                             GotIt = TRUE;
  1557.  
  1558.                                             break;
  1559.  
  1560.                                 case PALETTE_KIND:    if(Forward)
  1561.                                             {
  1562.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1563.                                                     GTPA_Color,    (Info -> Current == Info -> Max) ? 0 : Info -> Current + 1,
  1564.                                                 TAG_DONE);
  1565.                                             }
  1566.                                             else
  1567.                                             {
  1568.                                                 GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1569.                                                     GTPA_Color,    Info -> Current ? Info -> Current - 1 : Info -> Max,
  1570.                                                 TAG_DONE);
  1571.                                             }
  1572.  
  1573.                                             *Class    = IDCMP_GADGETUP;
  1574.                                             *Code    = Info -> Current;
  1575.                                             *Gadget    = GadgetList[i];
  1576.  
  1577.                                             GotIt = TRUE;
  1578.  
  1579.                                             break;
  1580.  
  1581.                                 case SCROLLER_KIND:    if(Forward)
  1582.                                             {
  1583.                                                 if(Info -> Current < Info -> Max)
  1584.                                                 {
  1585.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1586.                                                         GTSC_Top,    Info -> Current + 1,
  1587.                                                     TAG_DONE);
  1588.  
  1589.                                                     *Class    = IDCMP_MOUSEMOVE;
  1590.                                                     *Code    = Info -> Current;
  1591.                                                     *Gadget    = GadgetList[i];
  1592.                                                 }
  1593.                                             }
  1594.                                             else
  1595.                                             {
  1596.                                                 if(Info -> Current > Info -> Min)
  1597.                                                 {
  1598.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1599.                                                         GTSC_Top,    Info -> Current - 1,
  1600.                                                     TAG_DONE);
  1601.  
  1602.                                                     *Class    = IDCMP_MOUSEMOVE;
  1603.                                                     *Code    = Info -> Current;
  1604.                                                     *Gadget    = GadgetList[i];
  1605.                                                 }
  1606.                                             }
  1607.  
  1608.                                             GotIt = TRUE;
  1609.  
  1610.                                             break;
  1611.  
  1612.                                 case SLIDER_KIND:    if(Forward)
  1613.                                             {
  1614.                                                 if(Info -> Current < Info -> Max)
  1615.                                                 {
  1616.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1617.                                                         GTSL_Level,    Info -> Current + 1,
  1618.                                                     TAG_DONE);
  1619.  
  1620.                                                     *Class    = IDCMP_MOUSEMOVE;
  1621.                                                     *Code    = Info -> Current;
  1622.                                                     *Gadget    = GadgetList[i];
  1623.                                                 }
  1624.                                             }
  1625.                                             else
  1626.                                             {
  1627.                                                 if(Info -> Current > Info -> Min)
  1628.                                                 {
  1629.                                                     GT_SetGadgetAttrs(GadgetList[i],Window,NULL,
  1630.                                                         GTSL_Level,    Info -> Current - 1,
  1631.                                                     TAG_DONE);
  1632.  
  1633.                                                     *Class    = IDCMP_MOUSEMOVE;
  1634.                                                     *Code    = Info -> Current;
  1635.                                                     *Gadget    = GadgetList[i];
  1636.                                                 }
  1637.                                             }
  1638.  
  1639.                                             GotIt = TRUE;
  1640.  
  1641.                                             break;
  1642.  
  1643.                                 default:        break;
  1644.                             }
  1645.                         }
  1646.                     }
  1647.                 }
  1648.             }
  1649.         }
  1650.  
  1651.             /* If no matching object was found, take a closer look at the types. */
  1652.  
  1653.         if(!GotIt)
  1654.         {
  1655.             for(i = 0 ; i <= Last ; i++)
  1656.             {
  1657.                     /* If it's a string object, activat it. */
  1658.  
  1659.                 if(!(GadgetList[i] -> Flags & GFLG_DISABLED) && (GadgetList[i] -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  1660.                 {
  1661.                     ActivateGadget(ActiveGadget = GadgetList[i],Window,NULL);
  1662.  
  1663.                     *Class    = IDCMP_GADGETDOWN;
  1664.                     *Code    = 0;
  1665.                     *Gadget    = GadgetList[i];
  1666.  
  1667.                     break;
  1668.                 }
  1669.             }
  1670.         }
  1671.     }
  1672. }
  1673.  
  1674.     /* SZ_ResetMaxWidth():
  1675.      *
  1676.      *    Reset maximum object width and return current maximum width.
  1677.      */
  1678.  
  1679. LONG
  1680. SZ_ResetMaxWidth()
  1681. {
  1682.     LONG Width = SZ_WidthMax;
  1683.  
  1684.     SZ_WidthMax = 0;
  1685.  
  1686.     return(Width);
  1687. }
  1688.  
  1689.     /* SZ_UpdateMaxWidth():
  1690.      *
  1691.      *    Update current maximum object width.
  1692.      */
  1693.  
  1694. VOID __regargs
  1695. SZ_UpdateMaxWidth(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
  1696. {
  1697.     LONG Width = SZ_Width(Type,Title,Chars,Choices);
  1698.  
  1699.     if(Width > SZ_WidthMax)
  1700.         SZ_WidthMax = Width;
  1701. }
  1702.  
  1703.     /* SZ_GetWindowWidth():
  1704.      *
  1705.      *    Get the current window width.
  1706.      */
  1707.  
  1708. LONG
  1709. SZ_GetWindowWidth()
  1710. {
  1711.     return(SZ_WindowWidth);
  1712. }
  1713.  
  1714.     /* SZ_GetWindowHeight():
  1715.      *
  1716.      *    Get the current window height.
  1717.      */
  1718.  
  1719. LONG
  1720. SZ_GetWindowHeight()
  1721. {
  1722.     return(SZ_WindowHeight + SZ_Screen -> WBorBottom);
  1723. }
  1724.  
  1725.     /* SZ_GetLeftEdge():
  1726.      *
  1727.      *    Get the current object left edge.
  1728.      */
  1729.  
  1730. LONG
  1731. SZ_GetLeftEdge()
  1732. {
  1733.     return(SZ_CurrentLeft);
  1734. }
  1735.  
  1736.     /* SZ_GetTopEdge():
  1737.      *
  1738.      *    Get the current object top edge.
  1739.      */
  1740.  
  1741. LONG
  1742. SZ_GetTopEdge()
  1743. {
  1744.     return(SZ_CurrentTop);
  1745. }
  1746.  
  1747.     /* SZ_SetTopEdge(LONG Top):
  1748.      *
  1749.      *    Set the current object top edge.
  1750.      */
  1751.  
  1752. VOID __regargs
  1753. SZ_SetTopEdge(LONG Top)
  1754. {
  1755.     SZ_CurrentTop = Top;
  1756. }
  1757.  
  1758.     /* SZ_SetLeftEdge(LONG Left):
  1759.      *
  1760.      *    Set the current object left edge.
  1761.      */
  1762.  
  1763. VOID __regargs
  1764. SZ_SetLeftEdge(LONG Left)
  1765. {
  1766.     SZ_CurrentLeft = Left;
  1767. }
  1768.  
  1769.     /* SZ_SetAbsoluteTop(LONG Top):
  1770.      *
  1771.      *    Set new inner window top edge.
  1772.      */
  1773.  
  1774. VOID __regargs
  1775. SZ_SetAbsoluteTop(LONG Top)
  1776. {
  1777.     SZ_Top = Top;
  1778. }
  1779.  
  1780.     /* SZ_SetAbsoluteLeft(LONG Left):
  1781.      *
  1782.      *    Set new inner window left edge.
  1783.      */
  1784.  
  1785. VOID __regargs
  1786. SZ_SetAbsoluteLeft(LONG Left)
  1787. {
  1788.     SZ_Left = Left;
  1789. }
  1790.  
  1791.     /* SZ_SetWidth(LONG Width):
  1792.      *
  1793.      *    Set current object width.
  1794.      */
  1795.  
  1796. VOID __regargs
  1797. SZ_SetWidth(LONG Width)
  1798. {
  1799.     SZ_CurrentWidth = Width;
  1800. }
  1801.  
  1802.     /* SZ_GetDimension(LONG *Width,LONG *Height):
  1803.      *
  1804.      *    Get current window dimensions.
  1805.      */
  1806.  
  1807. VOID __regargs
  1808. SZ_GetDimension(LONG *Width,LONG *Height)
  1809. {
  1810.     *Width    = SZ_WindowWidth;
  1811.     *Height    = SZ_WindowHeight + SZ_Screen -> WBorBottom;
  1812. }
  1813.  
  1814.     /* SZ_TextWidth(STRPTR String):
  1815.      *
  1816.      *    Determine string width in pixels.
  1817.      */
  1818.  
  1819. LONG __regargs
  1820. SZ_TextWidth(STRPTR String)
  1821. {
  1822.     UBYTE    TempString[256];
  1823.     WORD    i,j;
  1824.  
  1825.     for(i = j = 0 ; String[i] ; i++)
  1826.     {
  1827.         if(String[i] != '_')
  1828.             TempString[j++] = String[i];
  1829.     }
  1830.  
  1831.     return(TextLength(SZ_RPort,TempString,j));
  1832. }
  1833.  
  1834.     /* SZ_AddLeftOffset(LONG Offset):
  1835.      *
  1836.      *    Update current object left offset.
  1837.      */
  1838.  
  1839. VOID __regargs
  1840. SZ_AddLeftOffset(LONG Offset)
  1841. {
  1842.     SZ_CurrentLeft += Offset;
  1843. }
  1844.  
  1845.     /* SZ_LeftOffsetN(LONG DataArray,...):
  1846.      *
  1847.      *    Determine the maximum length of a number of
  1848.      *    gadget labels (first, second, third item, -1 terminates
  1849.      *    the array).
  1850.      */
  1851.  
  1852. LONG __stdargs
  1853. SZ_LeftOffsetN(LONG DataArray,...)
  1854. {
  1855.     extern STRPTR __regargs    LocaleString(LONG ID);
  1856.  
  1857.     LONG    *Data = &DataArray,
  1858.          Len,
  1859.          Max = 0;
  1860.  
  1861.     while(*Data != -1)
  1862.     {
  1863.         if((Len = SZ_TextWidth(LocaleString(*Data++))) > Max)
  1864.             Max = Len;
  1865.     }
  1866.  
  1867.     return(Max + INTERWIDTH);
  1868. }
  1869.  
  1870.     /* SZ_LeftOffsetDelta(LONG From,LONG To):
  1871.      *
  1872.      *    Determine the maximum length of a number of
  1873.      *    gadget labels (given as first and last gadget).
  1874.      */
  1875.  
  1876. LONG __regargs
  1877. SZ_LeftOffsetDelta(LONG From,LONG To)
  1878. {
  1879.     extern STRPTR __regargs    LocaleString(LONG ID);
  1880.  
  1881.     LONG    i,
  1882.         Len,
  1883.         Max = 0;
  1884.  
  1885.     for(i = From ; i <= To ; i++)
  1886.     {
  1887.         if((Len = SZ_TextWidth(LocaleString(i))) > Max)
  1888.             Max = Len;
  1889.     }
  1890.  
  1891.     return(Max + INTERWIDTH);
  1892. }
  1893.  
  1894.     /* SZ_SizeCleanup():
  1895.      *
  1896.      *    Free data allocated by SZ_SizeSetup().
  1897.      */
  1898.  
  1899. VOID
  1900. SZ_SizeCleanup()
  1901. {
  1902.     if(SZ_TextFont)
  1903.     {
  1904.         CloseFont(SZ_TextFont);
  1905.  
  1906.         SZ_TextFont = NULL;
  1907.     }
  1908.  
  1909.     if(SZ_RPort)
  1910.     {
  1911.         FreeVec(SZ_RPort);
  1912.  
  1913.         SZ_RPort = NULL;
  1914.     }
  1915. }
  1916.  
  1917.     /* SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title):
  1918.      *
  1919.      *    Perform setups for gadget creation.
  1920.      */
  1921.  
  1922. BYTE __regargs
  1923. SZ_SizeSetup(struct Screen *Screen,struct TextAttr *TextAttr,BYTE Title)
  1924. {
  1925.     struct DrawInfo *DrawInfo;
  1926.  
  1927.     SZ_SizeCleanup();
  1928.  
  1929.     if(DrawInfo = GetScreenDrawInfo(Screen))
  1930.     {
  1931.         SZ_TextPen = DrawInfo -> dri_Pens[TEXTPEN];
  1932.  
  1933.         FreeScreenDrawInfo(Screen,DrawInfo);
  1934.     }
  1935.  
  1936.     SZ_Screen = Screen;
  1937.  
  1938.     if(SZ_RPort = (struct RastPort *)AllocVec(sizeof(struct RastPort),MEMF_ANY | MEMF_CLEAR))
  1939.     {
  1940.         InitRastPort(SZ_RPort);
  1941.  
  1942.         if(!TextAttr)
  1943.             TextAttr = Screen -> Font;
  1944.  
  1945.         if(DiskfontBase)
  1946.             SZ_TextFont = (struct TextFont *)OpenDiskFont(TextAttr);
  1947.         else
  1948.             SZ_TextFont = (struct TextFont *)OpenFont(TextAttr);
  1949.  
  1950.         if(SZ_TextFont)
  1951.         {
  1952.             InterWidth = INTERWIDTH;
  1953.  
  1954.             if(SZ_TextFont -> tf_YSize <= 8)
  1955.                 InterHeight = 1;
  1956.             else
  1957.                 InterHeight = SZ_TextFont -> tf_YSize / 4;
  1958.                 
  1959.             SetFont(SZ_RPort,SZ_TextFont);
  1960.  
  1961.             if(Title)
  1962.                 SZ_Top    = Screen -> WBorTop + Screen -> Font -> ta_YSize + 1 + InterHeight;
  1963.             else
  1964.                 SZ_Top    = Screen -> WBorTop + InterHeight;
  1965.  
  1966.             SZ_Left        = InterWidth;
  1967.  
  1968.             SZ_CurrentLeft    = InterWidth;
  1969.             SZ_CurrentTop    = SZ_Top;
  1970.  
  1971.             SZ_WindowWidth    = 0;
  1972.             SZ_WindowHeight    = 0;
  1973.  
  1974.             SZ_CurrentWidth    = 0;
  1975.             SZ_MaxWidth    = 0;
  1976.  
  1977.             return(TRUE);
  1978.         }
  1979.     }
  1980.  
  1981.     SZ_SizeCleanup();
  1982.  
  1983.     return(FALSE);
  1984. }
  1985.  
  1986.     /* SZ_Height(UBYTE Type,LONG Lines,BYTE Display):
  1987.      *
  1988.      *    Determine the height of an object.
  1989.      */
  1990.  
  1991. LONG __regargs
  1992. SZ_Height(UBYTE Type,LONG Lines,BYTE Display)
  1993. {
  1994.     LONG Height = 0;
  1995.  
  1996.     switch(Type)
  1997.     {
  1998.         case LISTVIEW_KIND:    Height = 4 + Lines * SZ_TextFont -> tf_YSize + 4;
  1999.  
  2000.                     if(Display == SZLV_Display)
  2001.                         Height += 2 + SZ_TextFont -> tf_YSize + 2;
  2002.  
  2003.                     if(Display == SZLV_String)
  2004.                         Height += 3 + SZ_TextFont -> tf_YSize + 3;
  2005.  
  2006.                     break;
  2007.  
  2008.         case INTEGER_KIND:
  2009.         case STRING_KIND:    Height = 3 + SZ_TextFont -> tf_YSize + 3;
  2010.                     break;
  2011.  
  2012.         case CYCLE_KIND:
  2013.         case TEXT_KIND:
  2014.         case BUTTON_KIND:    Height = 2 + SZ_TextFont -> tf_YSize + 2;
  2015.                     break;
  2016.  
  2017.         case CHECKBOX_KIND:    if(SZ_TextFont -> tf_YSize < 11)
  2018.                         Height = 11;
  2019.                     else
  2020.                         Height = SZ_TextFont -> tf_YSize;
  2021.  
  2022.                     break;
  2023.  
  2024.         case SLIDER_KIND:    Height = 1 + SZ_TextFont -> tf_YSize + 1;
  2025.                     break;
  2026.  
  2027.         case MX_KIND:        Height = Lines * (SZ_TextFont -> tf_YSize + 1) - 1;
  2028.                     break;
  2029.  
  2030.         case PALETTE_KIND:    Height = 2 * SZ_TextFont -> tf_YSize;
  2031.                     break;
  2032.     }
  2033.  
  2034.     return(Height);
  2035. }
  2036.  
  2037.     /* SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices):
  2038.      *
  2039.      *    Determine the width of an object.
  2040.      */
  2041.  
  2042. LONG __regargs
  2043. SZ_Width(UBYTE Type,STRPTR Title,LONG Chars,STRPTR *Choices)
  2044. {
  2045.     LONG    Width = 0,
  2046.         Len,Max = 0,i;
  2047.  
  2048.     switch(Type)
  2049.     {
  2050.         case LISTVIEW_KIND:    Width = (4 + Chars * SZ_TextFont -> tf_XSize + 4) + (2 + 2 * SZ_TextFont -> tf_XSize + 2) + 4;    /* KLUDGE + 4 */
  2051.                     break;
  2052.  
  2053.         case TEXT_KIND:
  2054.         case BUTTON_KIND:    if(Title)
  2055.                         Width = 6 + SZ_TextWidth(Title) + 6;
  2056.                     else
  2057.                         Width = 6 + Chars * SZ_TextFont -> tf_XSize + 6;
  2058.  
  2059.                     break;
  2060.  
  2061.         case SLIDER_KIND:
  2062.         case STRING_KIND:
  2063.         case INTEGER_KIND:    Width = 6 + Chars * SZ_TextFont -> tf_XSize + 6;
  2064.                     break;
  2065.  
  2066.         case CHECKBOX_KIND:    if(SZ_TextFont -> tf_XSize < 13)
  2067.                         Width = 26;
  2068.                     else
  2069.                         Width = 2 * SZ_TextFont -> tf_XSize;
  2070.  
  2071.                     break;
  2072.  
  2073.         case CYCLE_KIND:    if(Choices)
  2074.                     {
  2075.                         for(i = 0 ; Choices[i] ; i++)
  2076.                         {
  2077.                             if((Len = TextLength(SZ_RPort,Choices[i],strlen(Choices[i]))) > Max)
  2078.                                 Max = Len;
  2079.                         }
  2080.  
  2081.                         Width = 24 + Max + 4;
  2082.                     }
  2083.                     else
  2084.                         Width = 24 + Chars * SZ_TextFont -> tf_XSize + 4;
  2085.  
  2086.                     break;
  2087.  
  2088.         case MX_KIND:        if(SZ_TextFont -> tf_XSize < 8)
  2089.                         Width = 17;
  2090.                     else
  2091.                         Width = 2 * SZ_TextFont -> tf_XSize;
  2092.  
  2093.                     break;
  2094.     }
  2095.  
  2096.     return(Width);
  2097. }
  2098.  
  2099.     /* SZ_FreeBox(struct TextBox *Box):
  2100.      *
  2101.      *    Free a text box.
  2102.      */
  2103.  
  2104. VOID __regargs
  2105. SZ_FreeBox(struct TextBox *Box)
  2106. {
  2107.     if(Box)
  2108.     {
  2109.         if(Box -> Text)
  2110.         {
  2111.             LONG i;
  2112.  
  2113.             for(i = 0 ; i < Box -> NumLines ; i++)
  2114.             {
  2115.                 if(Box -> Text[i])
  2116.                     FreeVec(Box -> Text[i]);
  2117.             }
  2118.  
  2119.             FreeVec(Box -> Text);
  2120.         }
  2121.  
  2122.         if(Box -> Title)
  2123.             FreeVec(Box -> Title);
  2124.  
  2125.         FreeVec(Box);
  2126.     }
  2127. }
  2128.  
  2129.     /* SZ_FreeBoxes(struct TextBox *FirstBox):
  2130.      *
  2131.      *    Free a number of text boxes.
  2132.      */
  2133.  
  2134. VOID __regargs
  2135. SZ_FreeBoxes(struct TextBox *FirstBox)
  2136. {
  2137.     if(FirstBox)
  2138.     {
  2139.         struct TextBox *NextBox;
  2140.  
  2141.         do
  2142.         {
  2143.             NextBox = FirstBox -> NextBox;
  2144.  
  2145.             SZ_FreeBox(FirstBox);
  2146.  
  2147.             FirstBox = NextBox;
  2148.         }
  2149.         while(FirstBox);
  2150.     }
  2151. }
  2152.  
  2153.     /* SZ_BoxWidth(LONG Chars):
  2154.      *
  2155.      *    Determine the width of a text box.
  2156.      */
  2157.  
  2158. LONG __regargs
  2159. SZ_BoxWidth(LONG Chars)
  2160. {
  2161.     return(4 + SZ_TextFont -> tf_XSize * Chars + 4);
  2162. }
  2163.  
  2164.     /* SZ_BoxHeight(LONG Lines):
  2165.      *
  2166.      *    Determine the height of a text box.
  2167.      */
  2168.  
  2169. LONG __regargs
  2170. SZ_BoxHeight(LONG Lines)
  2171. {
  2172.     return(2 + SZ_TextFont -> tf_YSize * Lines + 2);
  2173. }
  2174.  
  2175.     /* SZ_CreateTextBox(struct TextBox **FirstBox,...):
  2176.      *
  2177.      *    Create a text box, this routine works similar
  2178.      *    to the CreateGadget() frontend.
  2179.      */
  2180.  
  2181. struct TextBox * __stdargs
  2182. SZ_CreateTextBox(struct TextBox **FirstBox,...)
  2183. {
  2184.     va_list                 VarArgs;
  2185.     struct TagItem            *TagList,
  2186.                     *ThisTag;
  2187.     LONG                 Chars,Lines,
  2188.                      Width,
  2189.                      Height,
  2190.                      Left = SZ_CurrentLeft;
  2191.     BYTE                 AutoWidth    = FALSE,
  2192.                      MoveDown    = TRUE,
  2193.                      SetLeft    = FALSE,
  2194.                      SetBelow    = FALSE;
  2195.  
  2196.     struct TextBox            *Box;
  2197.     LONG                 i;
  2198.  
  2199.     va_start(VarArgs,FirstBox);
  2200.  
  2201.     TagList = (struct TagItem *)VarArgs;
  2202.  
  2203.     if(ThisTag = FindTagItem(SZ_Lines,TagList))
  2204.         Lines = (LONG)ThisTag -> ti_Data;
  2205.     else
  2206.         return(NULL);
  2207.  
  2208.     Height = 2 + SZ_TextFont -> tf_YSize * Lines + 2;
  2209.  
  2210.     if(ThisTag = FindTagItem(SZ_Chars,TagList))
  2211.         Chars = (LONG)ThisTag -> ti_Data;
  2212.     else
  2213.     {
  2214.         if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  2215.             AutoWidth = ThisTag -> ti_Data;
  2216.  
  2217.         if(!AutoWidth)
  2218.             return(NULL);
  2219.         else
  2220.             Chars = (SZ_CurrentWidth - 8) / SZ_TextFont -> tf_XSize;
  2221.     }
  2222.  
  2223.     if(!(Box = (struct TextBox *)AllocVec(sizeof(struct TextBox),MEMF_ANY | MEMF_CLEAR)))
  2224.         return(NULL);
  2225.  
  2226.     if(ThisTag = FindTagItem(SZ_SetLeft,TagList))
  2227.         SetLeft = ThisTag -> ti_Data;
  2228.  
  2229.     if(ThisTag = FindTagItem(SZ_SetBelow,TagList))
  2230.         SetBelow = ThisTag -> ti_Data;
  2231.  
  2232.     if(ThisTag = FindTagItem(SZ_AlignBottom,TagList))
  2233.     {
  2234.         if(ThisTag -> ti_Data)
  2235.             SZ_CurrentTop = SZ_WindowHeight;
  2236.     }
  2237.  
  2238.     if(ThisTag = FindTagItem(SZ_AlignExtra,TagList))
  2239.     {
  2240.         if(ThisTag -> ti_Data)
  2241.             SZ_CurrentTop += InterHeight;
  2242.     }
  2243.  
  2244.     if(ThisTag = FindTagItem(SZ_NewColumn,TagList))
  2245.     {
  2246.         if(ThisTag -> ti_Data)
  2247.         {
  2248.             SZ_CurrentTop    = SZ_Top;
  2249.             Left        = Left + SZ_MaxWidth + InterWidth;
  2250.  
  2251.             SZ_MaxWidth    = 0;
  2252.         }
  2253.     }
  2254.  
  2255.     if(ThisTag = FindTagItem(SZ_AutoWidth,TagList))
  2256.         AutoWidth = ThisTag -> ti_Data;
  2257.  
  2258.     if(!AutoWidth)
  2259.         Width = SZ_BoxWidth(Chars);
  2260.     else
  2261.         Width = SZ_CurrentWidth;
  2262.  
  2263.     if(ThisTag = FindTagItem(SZ_AlignLeft,TagList))
  2264.     {
  2265.         if(ThisTag -> ti_Data)
  2266.         {
  2267.             Left = SZ_Left;
  2268.  
  2269.             MoveDown = FALSE;
  2270.         }
  2271.     }
  2272.  
  2273.     if(ThisTag = FindTagItem(SZ_AlignRight,TagList))
  2274.     {
  2275.         if(ThisTag -> ti_Data)
  2276.         {
  2277.             Left = SZ_WindowWidth - INTERWIDTH - Width;
  2278.  
  2279.             MoveDown = FALSE;
  2280.         }
  2281.     }
  2282.  
  2283.     if(ThisTag = FindTagItem(SZ_AlignCentre,TagList))
  2284.     {
  2285.         if(ThisTag -> ti_Data)
  2286.         {
  2287.             Left = (SZ_WindowWidth - Width) / 2;
  2288.  
  2289.             MoveDown = FALSE;
  2290.         }
  2291.     }
  2292.  
  2293.     if(ThisTag = FindTagItem(SZ_GroupCount,TagList))
  2294.     {
  2295.         LONG Count = ThisTag -> ti_Data,Width = SZ_WindowWidth;
  2296.  
  2297.         if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  2298.         {
  2299.             Width -= ThisTag -> ti_Data - InterWidth;
  2300.  
  2301.             SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  2302.             SZ_GroupX    = Left = ThisTag -> ti_Data;
  2303.         }
  2304.         else
  2305.         {
  2306.             SZ_GroupDelta    = SZ_CurrentWidth + ((Width - 2 * InterWidth) - (Count * SZ_CurrentWidth)) / (Count - 1);
  2307.             SZ_GroupX    = Left = SZ_Left;
  2308.         }
  2309.  
  2310.         MoveDown = FALSE;
  2311.     }
  2312.     else
  2313.     {
  2314.         if(ThisTag = FindTagItem(SZ_UseLeft,TagList))
  2315.             Left = ThisTag -> ti_Data;
  2316.     }
  2317.  
  2318.     if(ThisTag = FindTagItem(SZ_GroupNext,TagList))
  2319.     {
  2320.         if(ThisTag -> ti_Data)
  2321.         {
  2322.             SZ_GroupX += SZ_GroupDelta;
  2323.  
  2324.             Left = SZ_GroupX;
  2325.  
  2326.             MoveDown = FALSE;
  2327.         }
  2328.     }
  2329.  
  2330.     if(ThisTag = FindTagItem(SZ_UseTop,TagList))
  2331.         SZ_CurrentTop = ThisTag -> ti_Data;
  2332.  
  2333.     Box -> Left        = Left;
  2334.     Box -> Top        = SZ_CurrentTop;
  2335.     Box -> Width        = Width;
  2336.     Box -> Height        = Height;
  2337.  
  2338.     Box -> LineWidth    = Chars * SZ_TextFont -> tf_XSize;
  2339.     Box -> LineHeight    = SZ_TextFont -> tf_YSize;
  2340.  
  2341.     Box -> NumChars        = Chars;
  2342.     Box -> NumLines        = Lines;
  2343.  
  2344.     Box -> TextPen        = SZ_TextPen;
  2345.  
  2346.     if(!(Box -> Title = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
  2347.     {
  2348.         SZ_FreeBox(Box);
  2349.  
  2350.         return(NULL);
  2351.     }
  2352.  
  2353.     if(!(Box -> Text = (STRPTR *)AllocVec(sizeof(STRPTR) * Lines,MEMF_ANY | MEMF_CLEAR)))
  2354.     {
  2355.         SZ_FreeBox(Box);
  2356.  
  2357.         return(NULL);
  2358.     }
  2359.  
  2360.     for(i = 0 ; i < Lines ; i++)
  2361.     {
  2362.         if(!(Box -> Text[i] = (STRPTR)AllocVec(Chars + 1,MEMF_ANY | MEMF_CLEAR)))
  2363.         {
  2364.             SZ_FreeBox(Box);
  2365.  
  2366.             return(NULL);
  2367.         }
  2368.     }
  2369.  
  2370.     if(SetBelow)
  2371.         MoveDown = FALSE;
  2372.  
  2373.     if(MoveDown)
  2374.     {
  2375.         SZ_CurrentTop    = SZ_CurrentTop + Height + InterHeight;
  2376.  
  2377.         if(SZ_CurrentTop > SZ_WindowHeight)
  2378.             SZ_WindowHeight = SZ_CurrentTop;
  2379.     }
  2380.     else
  2381.     {
  2382.         if(SZ_CurrentTop + Height + InterHeight > SZ_WindowHeight)
  2383.             SZ_WindowHeight = SZ_CurrentTop + Height + InterHeight;
  2384.  
  2385.         SZ_MaxWidth = 0;
  2386.     }
  2387.  
  2388.     if(Width > SZ_MaxWidth)
  2389.         SZ_MaxWidth = Width;
  2390.  
  2391.     if(Left + SZ_MaxWidth + INTERWIDTH > SZ_WindowWidth)
  2392.         SZ_WindowWidth = Left + SZ_MaxWidth + INTERWIDTH;
  2393.  
  2394.     if(!SetLeft)
  2395.         SZ_CurrentLeft = Left;
  2396.  
  2397.     if(!(*FirstBox))
  2398.         *FirstBox = Box;
  2399.     else
  2400.     {
  2401.         struct TextBox *CurrentBox = *FirstBox;
  2402.  
  2403.         while(CurrentBox -> NextBox)
  2404.             CurrentBox = CurrentBox -> NextBox;
  2405.  
  2406.         CurrentBox -> NextBox = Box;
  2407.     }
  2408.  
  2409.     return(Box);
  2410. }
  2411.  
  2412.     /* SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...):
  2413.      *
  2414.      *    Set the titles displayed in a text box.
  2415.      */
  2416.  
  2417. VOID __stdargs
  2418. SZ_SetBoxTitles(struct TextBox *Box,STRPTR Array,...)
  2419. {
  2420.     if(Box)
  2421.     {
  2422.         STRPTR    *Data = &Array;
  2423.         LONG     i = 0;
  2424.  
  2425.         while(*Data != NULL)
  2426.         {
  2427.             if(i < Box -> NumLines)
  2428.                 Box -> Title[i++] = *Data;
  2429.  
  2430.             Data++;
  2431.         }
  2432.     }
  2433. }
  2434.  
  2435.     /* SZ_PrintLine():
  2436.      *
  2437.      *    Print a string into a text box.
  2438.      */
  2439.  
  2440. VOID __stdargs
  2441. SZ_PrintLine(struct RastPort *RPort,struct TextBox *Box,LONG Line,STRPTR String,...)
  2442. {
  2443.     if(Box)
  2444.     {
  2445.         if(AttemptLockLayerRom(RPort -> Layer))
  2446.         {
  2447.             BYTE    FgPen = RPort -> FgPen,DrMd = RPort -> DrawMode;
  2448.             LONG    Width,Len,Left = Box -> Left + 4,Top = Box -> Top + 2 + Line * Box -> LineHeight;
  2449.             va_list    VarArgs;
  2450.             UBYTE    Buffer[256];
  2451.  
  2452.             va_start(VarArgs,String);
  2453.             VSPrintf(Buffer,String,VarArgs);
  2454.             va_end(VarArgs);
  2455.  
  2456.             if(DrMd != JAM2)
  2457.                 SetDrMd(RPort,JAM2);
  2458.  
  2459.             SetAPen(RPort,Box -> TextPen);
  2460.  
  2461.             Len = strlen(Buffer);
  2462.  
  2463.             if(Len > Box -> NumChars)
  2464.                 Len = Box -> NumChars;
  2465.  
  2466.             Width = TextLength(RPort,Buffer,Len);
  2467.  
  2468.             Move(RPort,Left,Top + RPort -> Font -> tf_Baseline);
  2469.             Text(RPort,Buffer,Len);
  2470.  
  2471.             if(Width != Box -> LineWidth)
  2472.             {
  2473.                 if(FgPen != 0)
  2474.                     SetAPen(RPort,0);
  2475.  
  2476.                 RectFill(RPort,Left + Width,Top,Left + Box -> LineWidth - 1,Top + Box -> LineHeight - 1);
  2477.             }
  2478.  
  2479.             SetAPen(RPort,FgPen);
  2480.  
  2481.             if(DrMd != JAM2)
  2482.                 SetDrMd(RPort,DrMd);
  2483.  
  2484.             if(String != Box -> Text[Line])
  2485.                 strcpy(Box -> Text[Line],Buffer);
  2486.  
  2487.             UnlockLayerRom(RPort -> Layer);
  2488.         }
  2489.     }
  2490. }
  2491.  
  2492.     /* SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box):
  2493.      *
  2494.      *    (Re-)Draw a text box.
  2495.      */
  2496.  
  2497. VOID __regargs
  2498. SZ_DrawBox(struct RastPort *RPort,struct TextBox *Box)
  2499. {
  2500.     if(Box)
  2501.     {
  2502.         LONG LineY,i,Len,FgPen = RPort -> FgPen;
  2503.  
  2504.         DrawBevelBox(RPort,Box -> Left,Box -> Top,Box -> Width,Box -> Height,
  2505.             GT_VisualInfo,    VisualInfo,
  2506.             GTBB_Recessed,    TRUE,
  2507.         TAG_DONE);
  2508.  
  2509.         LineY = Box -> Top + 2 + RPort -> Font -> tf_Baseline;
  2510.  
  2511.         SetAPen(RPort,Box -> TextPen);
  2512.  
  2513.         for(i = 0 ; i < Box -> NumLines ; i++)
  2514.         {
  2515.             Len = strlen(Box -> Title[i]);
  2516.  
  2517.             Move(RPort,Box -> Left - INTERWIDTH - TextLength(RPort,Box -> Title[i],Len),LineY);
  2518.             Text(RPort,Box -> Title[i],Len);
  2519.  
  2520.             LineY += Box -> LineHeight;
  2521.         }
  2522.  
  2523.         SetAPen(RPort,FgPen);
  2524.  
  2525.         for(i = 0 ; i < Box -> NumLines ; i++)
  2526.             SZ_PrintLine(RPort,Box,i,Box -> Text[i]);
  2527.     }
  2528. }
  2529.  
  2530.     /* SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox):
  2531.      *
  2532.      *    (Re-)Draw a number of text boxes.
  2533.      */
  2534.  
  2535. VOID __regargs
  2536. SZ_DrawBoxes(struct RastPort *RPort,struct TextBox *FirstBox)
  2537. {
  2538.     do
  2539.     {
  2540.         SZ_DrawBox(RPort,FirstBox);
  2541.  
  2542.         FirstBox = FirstBox -> NextBox;
  2543.     }
  2544.     while(FirstBox);
  2545. }
  2546.