home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / source / gadlay17.lha / gadlayout.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-16  |  60.0 KB  |  1,856 lines

  1. /*
  2. **    $Filename: gadlayout/gadlayout.c $
  3. **    $Release: 1.7 $
  4. **    $Revision: 36.26 $
  5. **    $Date: 93/11/30 $
  6. **
  7. **    GadLayout functions, a dynamic gadget layout system.
  8. **
  9. **    (C) Copyright 1992, 1993, Timothy J. Aston
  10. **    All Rights Reserved
  11. **
  12. **  GadLayout is copyright, so you can't go ahead and just use it however you
  13. **  want, there are some restrictions.  GadLayout consists of the C source
  14. **  files, all header files, and all documentation included.  You may not
  15. **  modify GadLayout in any way.  GadLayout exists for you, the software
  16. **  developer, to use it; however, certain conditions must be complied with
  17. **  before you do:
  18. **
  19. **  1. Your documentation must clearly state that it is making use of the
  20. **     GadLayout dynamic gadget layout system by Timothy Aston.
  21. **  2. You must provide me with, free of charge, a copy of the software you use
  22. **     GadLayout in, and any subsequent updates to it that use GadLayout, also
  23. **     free of charge.  This means that if the software you use it in is
  24. **     shareware, I must be considered a full-registered user of the software.
  25. **     Similarly for commercial software, you must provide me with a
  26. **     complimentary copy.  And in all cases, as long as your software continues
  27. **     to use GadLayout, you must provide with all publically released updates.
  28. **     See the end of this document to find out how to get the stuff to me. 
  29. **     I hope this isn't being too unreasonable, I basically just want to see
  30. **     all the software that uses GadLayout.
  31. **  3. If you modify the GadLayout source at all, you must send your
  32. **     modifications to me.  You may not under any circumstances use the
  33. **     GadLayout sources to create any kind of runtime-linking module, such
  34. **     as a standard Amiga shared-library.
  35. **  4. You may not distribute modified GadLayout source, or include GadLayout
  36. **     source in a distribution without permission from the author.
  37. **  5. Any modified versions of GadLayout will fall under this same licensing
  38. **     agreement.
  39. **
  40. **
  41. */
  42.  
  43. #include <exec/types.h>
  44. #include <exec/memory.h>
  45. #include <utility/tagitem.h>
  46. #include <intuition/intuition.h>
  47. #include <intuition/screens.h>
  48. #include <graphics/clip.h>
  49. #include <graphics/layers.h>
  50. #include <libraries/gadtools.h>
  51. #include <libraries/locale.h>
  52. #include <clib/exec_protos.h>
  53. #include <clib/gadtools_protos.h>
  54. #include <clib/graphics_protos.h>
  55. #include <clib/intuition_protos.h>
  56. #include <clib/layers_protos.h>
  57. #include <clib/locale_protos.h>
  58. #include <clib/utility_protos.h>
  59. #include <string.h>
  60. #include "gadlayout.h"
  61.  
  62.  
  63. /* #define GL_DEBUG 1 */
  64.  
  65. #define MAX(a, b)    (a > b) ? a : b
  66. #define MIN(a, b)    (a < b) ? a : b
  67.  
  68. #define GADLAYOUT_KIND 0xF001
  69. #define GLFLG_READONLY 0x002
  70. #define GLFLG_TOGGLE 0x004
  71.  
  72. /* Local structure used to hold the definitions for the gadgets once they
  73.  * have been laid out.
  74.  */
  75. struct LaidOutGadget
  76. {
  77.     BOOL log_IsEvaluated;
  78.     ULONG log_GadgetKind;
  79.     struct NewGadget log_NewGadget;
  80. };
  81.  
  82. /* Structure used to hold the application strings, used incase we couldn't
  83.  * get a string from the locale catalog.
  84.  */
  85. struct AppString
  86. {
  87.     LONG as_ID;
  88.     STRPTR as_Str;
  89. };
  90.  
  91. /* Private Local structure used to hold all gadget information that needs to
  92.  * be freed.
  93.  */
  94. struct PrivateInfo
  95. {
  96.     struct Screen *pi_Screen;
  97.     APTR pi_VisualInfo;
  98.     struct DrawInfo *pi_DrawInfo;
  99.     struct Gadget *pi_GadList;
  100.     struct Catalog *pi_Catalog;
  101.     struct AppString *pi_AppStrings;
  102.     struct Remember *pi_Remember;
  103. };
  104.  
  105. /* Local function prototypes.
  106.  */
  107. VOID evaluate_gadget(struct PrivateInfo *, WORD, struct LayoutGadget *, struct NewGadget *, struct LaidOutGadget *);
  108. LONG text_width(char *, struct TextAttr *);
  109. STRPTR get_locale_string(struct Catalog *, struct AppString *, LONG);
  110. struct Gadget * create_layout_gad(struct PrivateInfo *, WORD, struct Gadget *, struct NewGadget *, struct TagItem *);
  111. struct Image * create_gad_images(WORD, UWORD, UWORD, struct PrivateInfo *, struct Image *, BOOL);
  112.  
  113. /* Public function prototypes.  These function definitions may differ slightly
  114.  * from what appears in gadlayout_protos.h (the public definitions) since we
  115.  * must hide private structures by using APTRs.
  116.  */
  117. struct PrivateInfo * LayoutGadgets(struct Gadget **, struct LayoutGadget *, struct Screen *, Tag *, ...);
  118. struct PrivateInfo * LayoutGadgetsA(struct Gadget **gad_list, struct LayoutGadget *g, struct Screen *, struct TagItem *);
  119. VOID GL_SetGadgetAttrs(struct PrivateInfo *, struct Gadget *, struct Window *, struct Requester *, Tag *, ...);
  120. VOID GL_SetGadgetAttrsA(struct PrivateInfo *, struct Gadget *, struct Window *, struct Requester *, struct TagItem *taglist);
  121. WORD GadgetArrayIndex(WORD, struct LayoutGadget *);
  122. struct Gadget * GetGadgetInfo(WORD, struct LayoutGadget *);
  123. UBYTE GadgetKeyCmd(struct PrivateInfo *, WORD, struct LayoutGadget *);
  124. VOID FreeLayoutGadgets(struct PrivateInfo *);
  125.  
  126. extern struct Library *LocaleBase;
  127.  
  128. /* Data for the drawer image.
  129.  */
  130. __chip static UWORD drawer_data[10] =
  131. {
  132.     0x03C0,
  133.     0x0420,
  134.     0xF810,
  135.     0xFC10,
  136.     0xC3F0,
  137.     0xC010,
  138.     0xC010,
  139.     0xC010,
  140.     0xC010,
  141.     0xFFF0
  142. };
  143.  
  144. /* Data for the file image.
  145.  */
  146. __chip static UWORD file_data[10] =
  147. {
  148.     0xFF00,
  149.     0xC180,
  150.     0xC140,
  151.     0xC120,
  152.     0xC1F0,
  153.     0xC030,
  154.     0xC030,
  155.     0xC030,
  156.     0xC030,
  157.     0xFFF0
  158. };
  159.  
  160. struct Image file_image =
  161. {
  162.     0, 0,
  163.     12, 10,
  164.     2,
  165.     file_data,
  166.     0x01, 0x00,
  167.     NULL,
  168. };
  169.  
  170. /* Data for the drawer image.
  171.  */
  172. struct Image drawer_image =
  173. {
  174.     0, 0,
  175.     12, 10,
  176.     2,
  177.     drawer_data,
  178.     0x01, 0x00,
  179.     NULL,
  180. };
  181.  
  182.  
  183. /****** gadlayout/LayoutGadgetsA ********************************************
  184. *
  185. *   NAME
  186. *       LayoutGadgetsA -- Formats an array of GadTools gadgets.
  187. *       LayoutGadgets -- Varargs stub for LayoutGadgetsA().
  188. *
  189. *   SYNOPSIS
  190. *       gad_info = LayoutGadgetsA(gad_list, gadgets, screen, taglist)
  191. *       APTR LayoutGadgetsA(struct Gadget **, struct LayoutGadget *,
  192. *                           struct Screen *, struct TagItem *)
  193. *
  194. *       gad_info = LayoutGadgets(gad_list, gadgets, screen, firsttag, ...)
  195. *       APTR LayoutGadgets(struct Gadget **, struct LayoutGadget *,
  196. *                          struct Screen *, Tag *, ...)
  197. *
  198. *   FUNCTION
  199. *       Creates a laid-out gadget list from a LayoutGadget array, which
  200. *       describes each gadget you want to create.  Gadgets you create
  201. *       can be any of the gadget kinds supported by GadTools, as well
  202. *       as any of the extended gadget kinds provided by GadLayout.
  203. *       Gadgets can easily be defined so that the automatically adjust
  204. *       their sizes and positions to accomodate fonts of any size
  205. *       (including proportional fonts) and also to adapt to different
  206. *       locale strings.  The real power of GadLayout is that allows you
  207. *       to create a gadget layout that dynamically adjusts to different
  208. *       user's environments.
  209. *
  210. *   INPUTS
  211. *       gad_list - Pointer to the gadget list pointer, this will be
  212. *           ready to pass to OpenWindowTags() or AddGList().
  213. *
  214. *       gadgets - An array of LayoutGadget structures.  Each element
  215. *           in the array describes one of the gadgets that you will
  216. *           be creating.  Each LayoutGadget structure in the array
  217. *           should be initialized as follows:
  218. *
  219. *           lg_GadgetID - The ID for this gadget.
  220. *           lg_LayoutTags - A taglist consisting of the following tags:
  221. *               GL_GadgetKind (ULONG) - Which gadget kind to use.  This
  222. *                   may be any of the GadTools gadget kinds (defined in
  223. *                   libraries/gadtools.h), or one of the additional kinds
  224. *                   provided by GadLayout, which are:
  225. *                   IMAGEBUTTON_KIND : A button gadget with that uses an
  226. *                                      Intuition Image structure for its
  227. *                                      contents.  The image will be centred
  228. *                                      automatically.
  229. *                   DRAWER_KIND : A drawer button gadget.  Use this to
  230. *                                 allow the user to use the ASL file
  231. *                                 requester to select a path.
  232. *                   FILE_KIND : A file button gadget.  Use this to allow
  233. *                               the user to use the ASL file requester
  234. *                               to select a file.
  235. *                   Additional kinds may be added in the future.
  236. *               GL_Width (WORD) - Absolute gadget width, in pixels.
  237. *               GL_DupeWidth (UWORD) - Duplicate the width of another
  238. *                   gadget.
  239. *               GL_AutoWidth (WORD) - Set width according to length of
  240. *                   text label + ti_Data.  Note that this function
  241. *                   does not take into account the amount of space any
  242. *                   gadget imagery might take within the gadgets area.
  243. *               GL_Columns (UWORD) - Set width of gadget so that
  244. *                   approximately ti_Data columns of text with the
  245. *                   gadget's font will fit.  This will only be an
  246. *                   approximation, because with proportional fonts the
  247. *                   width of character varies.  Note that this function
  248. *                   does not take into account the amount of space any
  249. *                   gadget imagery might take within the gadgets area.
  250. *               GL_AddWidth (WORD) - Add some value to the total width
  251. *                   calculation.
  252. *               GL_MinWidth (WORD) - Make sure that the final width of
  253. *                   the gadget is at least this.
  254. *               GL_MaxWidth (WORD) - Make sure that the final width of
  255. *                   the gadget is at most this.
  256. *               GL_Height (WORD) - Absolute gadget width.
  257. *               GL_DupeHeight (UWORD) - Duplicate the height of another
  258. *                   gadget.
  259. *               GL_HeightFactor (UWORD) - Make the gadget height a multiple
  260. *                   of the font height (useful for LISTVIEW_KIND gadgets).
  261. *               GL_AutoHeight (WORD) - Set height according to height of
  262. *                   text font + ti_Data.
  263. *               GL_AddHeight (WORD) - Add some value to the total height
  264. *                   calculation.
  265. *               GL_MinHeight (WORD) - Make sure that the final height of
  266. *                   the gadget is at least this.
  267. *               GL_MaxHeight (WORD) - Make sure that the final height of
  268. *                   the gadget is at most this.
  269. *               GL_Top (WORD) - Absolute top edge.
  270. *               GL_TopRel (UWORD)  - Top edge relative to bottom edge of
  271. *                   another gadget (specified by its gadget ID).
  272. *               GL_AdjustTop (WORD) - ADD the height of the text font +
  273. *                   ti_Data to the top edge (often used to to properrly
  274. *                   position gadgets that have their label above).
  275. *               GL_AlignTop (UWORD) - Align the top edge of the gadget
  276. *                   with the top edge of another gadget (specified by its
  277. *                   gadget ID).
  278. *               GL_AddTop (WORD) -  Add some value to the final top edge
  279. *                   calculation.
  280. *               GL_Bottom (WORD) - Absolute bottom edge.
  281. *               GL_BottomRel (UWORD) - Bottom edge relative to top edge of
  282. *                   another gadget (specified by its gadget ID).
  283. *               GL_AlignBottom (UWORD) - Align the bottom edge of the gadget
  284. *                   with the bottom edge of another gadget (specified by its
  285. *                   gadget ID).
  286. *               GL_AddBottom (WORD) - Add some value to the final bottom edge
  287. *                   calculation.
  288. *               GL_Left (WORD) - Absolute left edge.
  289. *               GL_LeftRel (UWORD) - Left edge relative to right edge of
  290. *                   another gadget (specified by its gadget ID).
  291. *               GL_AdjustLeft (WORD) - ADD the width of the text label +
  292. *                   ti_Data to the left edge.
  293. *               GL_AlignLeft (UWORD) - Align the left edge of the gadget
  294. *                   with the left edge of another gadget (specified by its
  295. *                   gadget ID).
  296. *               GL_AddLeft (WORD) - Add some value to the final left edge
  297. *                   calculation.
  298. *               GL_Right (WORD) - Absolute right edge.
  299. *               GL_RightRel (UWORD) - Right edge relative to left edge of
  300. *                   another gadget (specified by its gadget ID).
  301. *               GL_AlignRight (UWORD) - Align the right edge of the gadget
  302. *                   with the right edge of another gadget (specified by its
  303. *                   gadget ID).
  304. *               GL_AddRight (WORD) - Add some value to the final right edge
  305. *                   calculation.
  306. *               GL_GadgetText (STRPTR) - Gadget text label.
  307. *               GL_TextAttr (struct TextAttr *) - Desired font for gadget
  308. *                   label, will override the GL_DefTextAttr if used.
  309. *               GL_Flags - (ULONG) Gadget flags.
  310. *               GL_UserData (VOID *)- Gadget UserData.
  311. *               GL_LocaleText - Gadget label taken from a locale catalog,
  312. *                   you supply the locale string ID.  If you use this tag
  313. *                   you MUST have used GL_AppStrings in your call to
  314. *                   LayoutGadgets().
  315. *
  316. *               If you've specified one of GadLayout's own gadget kinds
  317. *               with GL_GadgetKind, the following tags are available for
  318. *               defining attributes of those gadgets:
  319. *
  320. *               GLIM_Image (struct Image *) - Provide a pointer to the
  321. *                   Image structure to to be used in an IMAGEBUTTON_KIND
  322. *                   structure.  This pointer only need be valid when
  323. *                   LayoutGadgets() is called.
  324. *               GLIM_ReadOnly (BOOL) - Specifies that the gadget is read-
  325. *                   only.  It will get a recessed border and will not be
  326. *                   highlighted when clicked on.
  327. *               GLIM_Toggle (BOOL) - If true, the gadget becomes a toggle
  328. *                   switch gadget that can be clicked on and off.  The
  329. *                   initial state of the gadget will be unselected.
  330. *
  331. *               Generally you need only specify the tags when the data
  332. *               has changed from the previously gadget.  This gets a
  333. *               little tricky when you use the relation tags like
  334. *               GL_TopRel, as this means that gadgets will not be
  335. *               processed in sequential order necessarily.
  336. *
  337. *           lg_GadToolsTags - When defining a GadTools gadgets, you
  338. *               can pass a GadTools taglist to set options for that
  339. *               gadget.  This would be the same set of tags that you
  340. *               might pass to CreateGadgetA() if you were using GadTools
  341. *               directly.
  342. *           lg_Gadget - The pointer to the Gadget structure created for
  343. *               this gadget will be placed here.  You should initialize
  344. *               this field to NULL.  WARNING: The gadget structure
  345. *               created READ-ONLY!
  346. *
  347. *       screen - A pointer to the screen that the gadgets will be
  348. *           created for.  The is required so that the layout routines
  349. *           can get display info about the screen, no rendering will
  350. *           be done.
  351. *
  352. *       taglist - Pointer to a TagItem list (see below for allowed tags)
  353. *
  354. *   TAGS
  355. *       GL_RightExtreme (LONG *) - A pointer to a LONG where GadLayout
  356. *           will put the co-ordinate of the rightmost point where any
  357. *           imagery of the laid-out gadgets will be drawn.  Use this to
  358. *           open a window exactly big enough to hold all your gadgets.
  359. *           Use this value alone with the WA_InnerWidth window tag and
  360. *           NOT WA_Width, since you do not know how big the window
  361. *           border will be.
  362. *       GL_LowerExtreme (LONG *) - A pointer to a LONG where GadLayout
  363. *           will put the co-ordinate of the lowermost point where any
  364. *           imagery of the laid-out gadget will be drawn.  Use this to open
  365. *           a window exactly big enough to hold all your gadgets.
  366. *           Use this value alone with the WA_InnerHeight window tag and
  367. *           NOT WA_Height, since you do not know how big the window
  368. *           border will be.
  369. *       GL_DefTextAttr (struct TextAttr *) - Instead of having to indicate
  370. *           a TextAttr for each gadget, you can specify a font to be used
  371. *           by default for all your gadgets.
  372. *       GL_Catalog (struct Catalog *) - Specify the locale catalog to use
  373. *           to get your strings from.  If you wish to localize your gadget
  374. *           string via GL_LocaleText you MUST use this tag as well as
  375. *           GL_AppStrings.  You must also make certain that locale.library
  376. *           has been opened successfully with LocaleBase pointing to the
  377. *           library base.
  378. *       GL_AppStrings (struct AppString **) - If you wish to make your
  379. *           gadgets localized, you you must pass a list of strings and
  380. *           their IDs.  The format of these strings is an array of
  381. *           structures, with a LONG that contains the ID and a STRPTR
  382. *           pointing to the string, i.e.:
  383. *               struct AppString
  384. *               {
  385. *                   LONG   as_ID;
  386. *                   STRPTR as_Str;
  387. *               };
  388. *           These strings serve as the default language for the gadgets.
  389. *           See locale.library documentation for more information on
  390. *           localizing applications.  You MUST use this tag in addition to
  391. *           GL_Catalog if you wish to use GL_LocaleText to localize your
  392. *           gadgets.
  393. *       GL_NoCreate (BOOL) - Set to TRUE if you don't want the layout
  394. *           routine to actually create any gadgets.  This is used when
  395. *           you want to use the GL_RightExtreme and GL_LowerExtreme tags
  396. *           to find out how much space your gadgets will take, but don't
  397. *           actually want to create the gadgets just yet.
  398. *       GL_BorderTop (UWORD) - The size of the top border of your window.
  399. *           If your window does not have the WFLG_GIMMEZEROZERO flag set,
  400. *           it will be necessary to pass the size of the window borders.
  401. *           This value can be gotten either from the Window structure of
  402. *           your window (if it is already open), or from the Screen
  403. *           structure of your screen (see intuition/screens.h for details
  404. *           about this).  NOTE: This value is NOT added to the value
  405. *           returned by GL_LowerExtreme!
  406. *       GL_BorderLeft (UWORD) - The size of the left border of your window.
  407. *           If your window does not have the WFLG_GIMMEZEROZERO flag set,
  408. *           it will be necessary to pass the size of the window borders.
  409. *           This value can be gotten either from the Window structure of
  410. *           your window (if it is already open), or from the Screen
  411. *           structure of your screen (see intuition/screens.h for details
  412. *           about this).  NOTE: This value is NOT added to the value
  413. *           returned by GL_RightExtreme.
  414. *
  415. *   RESULT
  416. *       gad_info - A pointer to a private structure.  You must keep this
  417. *           value and pass it to FreeLayoutGadgets() later on in order to
  418. *           free up all resources used by your gadgets.
  419. *
  420. *   NOTES
  421. *       You must be careful with the taglist in the lg_LayoutTags field.
  422. *       Tags are processed sequentally in the order you give them in, and
  423. *       if a tag references another gadget (eg. the GL_TopRel tag), then
  424. *       processing of the current gadget halts while the referenced gadget
  425. *       is processed (if it has not already been processed).  Problems can
  426. *       arise if this gadget refers back to the original gadget that
  427. *       referenced it, if it is referring to a field that has not yet been
  428. *       processed in that gadget.  For example, gadget GAD_BUTTON1 may use
  429. *       the GL_TopRel tag to refer to GAD_BUTTON2, which may subsequently
  430. *       make use of GL_LeftRel to refer back to GAD_BUTTON1.  The gadgets
  431. *       left edge must already be defined in GAD_BUTTON1 (i.e. a tag such
  432. *       as GL_Left MUST appear before the GL_TopRel tag) if GAD_BUTTON2 is
  433. *       to get the left edge desired.
  434. *
  435. *   BUGS
  436. *       Doesn't do any checking to make sure gadgets don't overlap.
  437. *       Essentially assumes you know what you're doing with the layout.
  438. *
  439. *       Bad things will happen if you provide an IMAGEBUTTON_KIND gadget
  440. *       with an image too big to fit within the dimensions you've provided
  441. *       for the gadget.
  442. *
  443. *   SEE ALSO
  444. *       FreeLayoutGadgets(), gadlayout/gadlayout.h, libraries/gadtools.h,
  445. *       GadTools documentation.
  446. *
  447. *****************************************************************************
  448. *
  449. *  Have you read the license info?  It tells you that you must send your
  450. *  modifications of GadLayout to me, and that you may not make GadLayout
  451. *  into a shared library.
  452. *
  453. */
  454. struct PrivateInfo * LayoutGadgets(struct Gadget **gad_list, struct LayoutGadget *gadgets,
  455.                    struct Screen *screen, Tag *firsttag, ...)
  456. {
  457.     return( LayoutGadgetsA(gad_list, gadgets, screen, &firsttag) );
  458. }
  459.  
  460. struct PrivateInfo * LayoutGadgetsA(struct Gadget **gad_list, struct LayoutGadget *gadgets,
  461.                     struct Screen *screen, struct TagItem *taglist)
  462. {
  463.     struct PrivateInfo *pi;
  464.     struct Gadget *last_gad;
  465.     struct NewGadget ng;
  466.     struct LaidOutGadget gad_array[100];    /* Cop-out, should be dynamic */
  467.     struct TagItem *tag=NULL;
  468.     struct TextAttr *tattr=NULL;
  469.     UWORD bordertop=0, borderleft=0;
  470.     WORD *rightextreme=NULL, *lowerextreme=NULL;
  471.     BOOL nocreate=FALSE;
  472.     WORD num_gads=0, i;
  473.  
  474.     /* Allocate and initialize the PrivateInfo structure.
  475.      */
  476.     if (!(pi = (struct PrivateInfo *)AllocVec(sizeof(struct PrivateInfo), MEMF_CLEAR)))
  477.         return(NULL);
  478.  
  479.     pi->pi_Screen = screen;
  480.     if (!(pi->pi_VisualInfo = GetVisualInfo(screen, TAG_DONE)))
  481.         return(NULL);
  482.     if (!(pi->pi_DrawInfo = GetScreenDrawInfo(pi->pi_Screen)))
  483.         return(NULL);
  484.     pi->pi_Remember = NULL;
  485.  
  486.     /* Count the number of gadgets that we have, and allocate space for
  487.      * NewGadget structures for all of them.
  488.      */
  489.     while (gadgets[num_gads].lg_GadgetID != -1)
  490.         num_gads++;
  491.  
  492.     /* if (!(gad_array = (struct LaidOutGadget *)AllocVec(num_gads * sizeof(struct LaidOutGadget), MEMF_ANY | MEMF_CLEAR)))
  493.         return(NULL); */
  494.  
  495.     /* Evaluate the tag list.  Order does not make any difference with the
  496.      * tags supported at the moment.  In the case of duplicate tags, only
  497.      * the first will be recognized.
  498.      */
  499.  
  500.     /* ti_Data is a pointer to a LONG to store the right-most point that a
  501.      * gadget will exist in.
  502.      */
  503.     if (tag = FindTagItem(GL_RightExtreme, taglist))
  504.     {
  505. #ifdef GL_DEBUG
  506.         Printf("Tag: GL_RightExtreme  Data: %ld\n",tag->ti_Data);
  507. #endif
  508.         rightextreme = (WORD *)tag->ti_Data;
  509.     }
  510.     /* ti_Data is a pointer to a LONG to store the lower-most point that a
  511.      * a gadget will exist in.
  512.      */
  513.     if (tag = FindTagItem(GL_LowerExtreme, taglist))
  514.     {
  515. #ifdef GL_DEBUG
  516.         Printf("Tag: GL_LowerExtreme  Data: %ld\n",tag->ti_Data);
  517. #endif
  518.         lowerextreme = (WORD *)tag->ti_Data;
  519.     }
  520.     /* Indicates locale for the gadgets.
  521.      */
  522.     if (tag = FindTagItem(GL_Catalog, taglist))
  523.     {
  524. #ifdef GL_DEBUG
  525.         Printf("Tag: GL_Catalog  Data: %ld\n",tag->ti_Data);
  526. #endif
  527.         pi->pi_Catalog = (struct Catalog *)tag->ti_Data;
  528.     }
  529.     /* Indicates locale for the gadgets.
  530.      */
  531.     if (tag = FindTagItem(GL_AppStrings, taglist))
  532.     {
  533. #ifdef GL_DEBUG
  534.         Printf("Tag: GL_AppStrings  Data: %ld\n",tag->ti_Data);
  535. #endif
  536.         pi->pi_AppStrings = (struct AppString *)tag->ti_Data;
  537.     }
  538.     /* Specifies a default font for use with all gadgets, can still be
  539.      * over-ridden with GL_TextAttr.
  540.      */
  541.     if (tag = FindTagItem(GL_DefTextAttr, taglist))
  542.     {
  543. #ifdef GL_DEBUG
  544.         Printf("Tag: GL_DefTextAttr  Data: %ld\n",tag->ti_Data);
  545. #endif
  546.         tattr = (struct TextAttr *)tag->ti_Data;
  547.     }
  548.     /* Specifies the size of the top window border.
  549.      */
  550.     if (tag = FindTagItem(GL_BorderTop, taglist))
  551.     {
  552. #ifdef GL_DEBUG
  553.         Printf("Tag: GL_BorderTop  Data: %ld\n",tag->ti_Data);
  554. #endif
  555.         bordertop = (UWORD)tag->ti_Data;
  556.     }
  557.     /* Specifies the size of the left window border.
  558.      */
  559.     if (tag = FindTagItem(GL_BorderLeft, taglist))
  560.     {
  561. #ifdef GL_DEBUG
  562.         Printf("Tag: GL_BorderLeft  Data: %ld\n",tag->ti_Data);
  563. #endif
  564.         borderleft = (UWORD)tag->ti_Data;
  565.     }
  566.     /* Specifies that we don't actually want to create the gadgets.
  567.      */
  568.     if (tag = FindTagItem(GL_NoCreate, taglist))
  569.     {
  570. #ifdef GL_DEBUG
  571.         Printf("Tag: GL_NoCreate  Data: %ld\n",tag->ti_Data);
  572. #endif
  573.         nocreate = (BOOL)tag->ti_Data;
  574.     }
  575.  
  576.     for (i = 0; i <= num_gads; i++)
  577.         gad_array[i].log_IsEvaluated = FALSE;
  578.  
  579.     /* Initialize the gadget linked list.
  580.      */
  581. #ifdef GL_DEBUG
  582.     PutStr("Creating gadget context\n");
  583. #endif
  584.     if (nocreate == FALSE)
  585.     {
  586.         if (!(last_gad = CreateContext(gad_list)))
  587.             return(NULL);
  588.     }
  589.  
  590.     /* Initialize some suitable defaults for the gadgets.
  591.      */
  592.     ng.ng_Height = ng.ng_Width = 0;
  593.     ng.ng_LeftEdge = ng.ng_TopEdge = 0;
  594.     ng.ng_GadgetText = NULL;
  595.     ng.ng_TextAttr = tattr;
  596.     ng.ng_GadgetID = 0;
  597.     ng.ng_Flags = 0;
  598.     ng.ng_VisualInfo = pi->pi_VisualInfo;            
  599.     ng.ng_UserData = NULL;
  600.  
  601.     if (rightextreme)
  602.         *rightextreme = 0;
  603.     if (lowerextreme)
  604.         *lowerextreme = 0;
  605.  
  606.     /* Read each gadget in the layout array, setting up its NewGadget structure.
  607.      */
  608. #ifdef GL_DEBUG
  609.     PutStr("Evaluating each gadget\n");
  610. #endif
  611.     for (i = 0; i < num_gads; i++)
  612.         evaluate_gadget(pi, i, gadgets, &ng, gad_array);
  613.  
  614.     /* OK, the gagdets have all been laid out into NewGadget structures, we
  615.      * now go ahead and create them all.
  616.      */
  617. #ifdef GL_DEBUG
  618.     PutStr("Creating each gadget\n");
  619. #endif
  620.     for (i = 0; i < num_gads; i++)
  621.     {
  622. #ifdef GL_DEBUG
  623.         Printf("Creating gadget %ld\n", (WORD)i);
  624. #endif
  625.         if (rightextreme)
  626.             *rightextreme = MAX(*rightextreme, gad_array[i].log_NewGadget.ng_LeftEdge + gad_array[i].log_NewGadget.ng_Width);
  627.         if (lowerextreme)
  628.             *lowerextreme = MAX(*lowerextreme, gad_array[i].log_NewGadget.ng_TopEdge + gad_array[i].log_NewGadget.ng_Height);
  629.  
  630.         if (nocreate == FALSE)
  631.         {
  632.             gad_array[i].log_NewGadget.ng_LeftEdge += borderleft;
  633.             gad_array[i].log_NewGadget.ng_TopEdge += bordertop;
  634.  
  635.             switch (gad_array[i].log_GadgetKind)
  636.             {
  637.                 case IMAGEBUTTON_KIND:
  638.                 case FILE_KIND:
  639.                 case DRAWER_KIND:
  640.                     gadgets[i].lg_Gadget = last_gad = create_layout_gad(pi,
  641.                                                                         gad_array[i].log_GadgetKind,
  642.                                                                         last_gad,
  643.                                                                         &(gad_array[i].log_NewGadget),
  644.                                                                         gadgets[i].lg_LayoutTags);
  645.                     break;
  646.  
  647.                 default:
  648.                     gadgets[i].lg_Gadget = last_gad = CreateGadgetA(gad_array[i].log_GadgetKind,
  649.                                                                     last_gad,
  650.                                                                     &(gad_array[i].log_NewGadget),
  651.                                                                     gadgets[i].lg_GadToolsTags);
  652.                     break;
  653.             }
  654.         }
  655. #ifdef GL_DEBUG
  656.         if (last_gad == NULL)
  657.             PutStr("Couldn't create gadget\n");
  658. #endif
  659.     }
  660.     /* FreeVec(gad_array); */
  661.  
  662. #ifdef GL_DEBUG
  663.     PutStr("Done\n");
  664. #endif
  665.     if (nocreate == FALSE)
  666.     {
  667.         if (last_gad != NULL)
  668.         {
  669.             pi->pi_GadList = *gad_list;
  670.  
  671.             return(pi);
  672.         }
  673.     }
  674.     else
  675.         FreeVec(pi);
  676.  
  677.     return(NULL);
  678. }
  679.  
  680.  
  681. /****** gadlayout/GL_SetGadgetAttrsA ****************************************
  682. *
  683. *   NAME
  684. *       GL_SetGadgetAttrsA -- Change attributes of a GadLayout gadget.
  685. *       GL_SetGadgetAttrs -- Varargs stub for GL_SetGadgetAttrsA.
  686. *
  687. *   SYNOPSIS
  688. *       GL_SetGadgetAttrsA(gad_info, gad, win, req, taglist)
  689. *       VOID GL_SetGadgetAttrsA(APTR, struct Gadget *, struct Window *,
  690. *                               struct Requester *, struct TagItem *)
  691. *
  692. *       GL_SetGadgetAttrs(gad_info, gad, win, req, firsttag, ...)
  693. *       VOID GL_SetGadgetAttrs(APTR, struct Gadget *, struct Window *,
  694. *                              struct Requester *, Tag *, ...)
  695. *
  696. *   FUNCTION
  697. *       Changes attributes for one of the GadLayout gadget kinds according
  698. *       according to the attributes chosen in the tag list.
  699. *
  700. *   INPUTS
  701. *       gad_info - The value returned by LayoutGadgetsA().
  702. *       gad - Pointer to the gadget in question.
  703. *       win - Pointer to the window containing the gadget.
  704. *       req - Pointer to the requester containing the gadget, or NULL if
  705. *           not in a requester. (Not implemented yet, use NULL.)
  706. *       taglist - Pointer to a TagItem list.
  707. *
  708. *   TAGS
  709. *       IMAGEBUTTON_KIND:
  710. *       GLIM_Image (struct Image *) - Changes the image displayed in the
  711. *           gadget.
  712. *       GLIM_Toggle (BOOL) - Makes the gadget a toggle switch gadget (if
  713. *           it is not already) and puts it into either the selected state
  714. *           (ti_Data = TRUE) or deselectd state (ti_Data = FALSE).
  715. *
  716. *   BUGS
  717. *       This function is not compatable with itself in releases 1.5 and
  718. *       lower, because of the new pi parameter!  ALL OLD CODE WILL HAVE TO
  719. *       BE CHANGED!!!
  720. *
  721. *       Attributes not pertaining to a specific gadget kind will not
  722. *       always be ignored, so you will need to be careful that you only
  723. *       try to change attributes that are valid for the gadget's kind.
  724. *
  725. *****************************************************************************
  726. *
  727. *  Have you read the license info?  It tells you that you must send your
  728. *  modifications of GadLayout to me, and that you may not make GadLayout
  729. *  into a shared library.
  730. *
  731. */
  732. VOID GL_SetGadgetAttrs(struct PrivateInfo *pi, struct Gadget *gad, struct Window *win, struct Requester *req,
  733.                         Tag *firsttag, ...)
  734. {
  735.     return( GL_SetGadgetAttrsA(pi, gad, win, req, &firsttag) );
  736. }
  737.  
  738. VOID GL_SetGadgetAttrsA(struct PrivateInfo *pi, struct Gadget *gad,
  739.                         struct Window *win, struct Requester *req,
  740.                         struct TagItem *taglist)
  741. {
  742.     struct TagItem *tag;
  743.  
  744.     if (tag = FindTagItem(GLIM_Image, taglist))
  745.     {
  746.         if ((gad->MutualExclude & GADLAYOUT_KIND) == GADLAYOUT_KIND)
  747.         {
  748.             struct Image *image = (struct Image *)gad->GadgetRender;
  749.             struct Image *new_image = (struct Image *)tag->ti_Data;
  750.  
  751.             /* Remove the gadget while we work on it.
  752.              */
  753.             RemoveGadget(win, gad);
  754.  
  755.             /* Setup the new gadget imagery.
  756.              */
  757.             gad->GadgetRender = create_gad_images(IMAGEBUTTON_KIND, gad->Width, gad->Height,
  758.                                                   pi, new_image,
  759.                                                   gad->MutualExclude & GLFLG_READONLY);
  760.  
  761.             /* Re-add the gadget and refresh it.
  762.              */
  763.             AddGadget(win, gad, ~0);
  764.             RefreshGList(gad, win, req, 1);
  765.         }
  766.     }
  767.     else if (tag = FindTagItem(GLIM_Toggle, taglist))
  768.     {
  769.         if ((gad->MutualExclude & GADLAYOUT_KIND) == GADLAYOUT_KIND)
  770.         {
  771.             /* Remove the gadget while we work on it.
  772.              */
  773.             RemoveGadget(win, gad);
  774.  
  775.             gad->Activation |= GACT_TOGGLESELECT;
  776.  
  777.             if (tag->ti_Data)
  778.                 gad->Flags |= GFLG_SELECTED;
  779.             else
  780.                 gad->Flags &= ~GFLG_SELECTED;
  781.  
  782.             /* Re-add the gadget and refresh it.
  783.              */
  784.             AddGadget(win, gad, ~0);
  785.             RefreshGList(gad, win, req, 1);
  786.         }
  787.     }
  788. }
  789.  
  790.  
  791. /****** gadlayout/GadgetArrayIndex ******************************************
  792. *
  793. *   NAME
  794. *       GadgetArrayIndex -- Get a gadget's index in the LayoutGadget array.
  795. *
  796. *   SYNOPSIS
  797. *       i = GadgetArrayIndex(gad_id, gadgets)
  798. *       WORD GadgetArrayIndex(WORD, struct LayoutGadget *)
  799. *
  800. *   FUNCTION
  801. *       Given a gadget ID, returns the index of that gadget's definition
  802. *       in the LayoutGadget array.  For example, in cases where you need
  803. *       to know a gadget's Gadget structure (eg. if you wanted to use
  804. *       the Intuition function ActivateGadget() to make a string or an
  805. *       integer gadget active), you would need to lookup the lg_Gadget
  806. *       field in the LayoutGadget array.  You MUST NOT GIVE THE ARRAY
  807. *       INDEX YOURSELF, THIS IS NOT GUARUNTEED TO REMAIN VALID!  Instead,
  808. *       pass the id of the gadget that you want and this function will
  809. *       return the array index for you.
  810. *
  811. *   INPUTS
  812. *       gad_id - The ID of the gadget you want to find.
  813. *       gadgets - The LayoutGadget array that this gadget is defined in.
  814. *
  815. *   RESULT
  816. *       i - The index into the LayoutGadget array of the entry of the
  817. *          gadget ID you asked for.
  818. *
  819. *****************************************************************************
  820. *
  821. *  Have you read the license info?  It tells you that you must send your
  822. *  modifications of GadLayout to me, and that you may not make GadLayout
  823. *  into a shared library.
  824. *
  825. */
  826. WORD GadgetArrayIndex(WORD gad_id, struct LayoutGadget *gadgets)
  827. {
  828.     WORD i=0;
  829.  
  830.     while ( (gadgets[i].lg_GadgetID != gad_id) && (gadgets[i].lg_GadgetID != -1) )
  831.         i++;
  832.  
  833.     return(i);
  834. }
  835.  
  836.  
  837. /****** gadlayout/GetGadgetInfo *********************************************
  838. *
  839. *   NAME
  840. *       GetGadgetInfo -- Get a pointer to a gadget's structure.
  841. *
  842. *   SYNOPSIS
  843. *       gadget = GetGadgetInfo(gad_id, gadgets)
  844. *       WORD GetGadgetInfo(WORD, struct LayoutGadget *)
  845. *
  846. *   FUNCTION
  847. *       Given a gadget ID, returns the GadTools Gadget structure of that
  848. *       gadget.
  849. *
  850. *   INPUTS
  851. *       gad_id - The ID of the gadget you want to find.
  852. *       gadgets - The LayoutGadget array that this gadget is defined in.
  853. *
  854. *   RESULT
  855. *       gadget - The GadTools Gadget structure of the gadget ID you asked
  856. *           for.  As per GadTools conventions, the actual contents of this
  857. *           structure are PRIVATE.
  858. *
  859. *   SEE ALSO
  860. *       GadgetArrayIndex()
  861. *
  862. *****************************************************************************
  863. *
  864. *  Have you read the license info?  It tells you that you must send your
  865. *  modifications of GadLayout to me, and that you may not make GadLayout
  866. *  into a shared library.
  867. *
  868. */
  869. struct Gadget * GetGadgetInfo(WORD gad_id, struct LayoutGadget *gadgets)
  870. {
  871.     WORD i=0;
  872.  
  873.     while ( (gadgets[i].lg_GadgetID != gad_id) && (gadgets[i].lg_GadgetID != -1) )
  874.         i++;
  875.  
  876.     return(gadgets[i].lg_Gadget);
  877. }
  878.  
  879.  
  880. /****** gadlayout/GadgetKeyCmd **********************************************
  881. *
  882. *   NAME
  883. *       GadgetKeyCmd -- Returns the key equivalent of a gadget.
  884. *
  885. *   SYNOPSIS
  886. *       key = GadgetKeyCmd(gad_info, gad_id, gadgets)
  887. *       UBYTE GadgetKeyCmd(APTR, WORD, struct LayoutGadget *)
  888. *
  889. *   FUNCTION
  890. *       Looks for an underscore (_) character in a gadgets label to determine
  891. *       the key equivalent, if any, for a gadget.  This is particularly
  892. *       useful in localized code where the key equivalent may differ
  893. *       depending on what locale the user is running under.
  894. *
  895. *   INPUTS
  896. *       gad_info - The value returned by LayoutGadgetsA().
  897. *       gad_id - The GadgetID of the gadget whose key equivalent you want.
  898. *       gadgets - The LayoutGadget arrow that your gadget exists in.
  899. *
  900. *   RESULT
  901. *       key - The key equivalent for the gadget, always in lowercase.
  902. *
  903. *   BUGS
  904. *       Only works if GT_Underscore, '_' is used for key equivalents, will
  905. *       not work if another underscore character is used.
  906. *
  907. *****************************************************************************
  908. *
  909. *  Have you read the license info?  It tells you that you must send your
  910. *  modifications of GadLayout to me, and that you may not make GadLayout
  911. *  into a shared library.
  912. *
  913. */
  914. UBYTE GadgetKeyCmd(struct PrivateInfo *pi, WORD gad_id, struct LayoutGadget *gadgets)
  915. {
  916.     char key = 0;
  917.     WORD i=0;
  918.  
  919.     while ( (gadgets[i].lg_GadgetID != gad_id) && (gadgets[i].lg_GadgetID != -1) )
  920.         i++;
  921.  
  922.     if (gadgets[i].lg_GadgetID != -1)
  923.     {
  924.         struct TagItem *tag=NULL;
  925.         char text[100]="", *temp_text;
  926.  
  927.         if (tag = FindTagItem(GL_GadgetText, gadgets[i].lg_LayoutTags))
  928.             strcpy(text, (char *)tag->ti_Data);
  929.         else if (tag = FindTagItem(GL_LocaleText, gadgets[i].lg_LayoutTags))
  930.             strcpy(text, get_locale_string(pi->pi_Catalog, pi->pi_AppStrings, tag->ti_Data));
  931.  
  932.         if (temp_text = strpbrk(text, "_"))
  933.             key = ToLower(temp_text[1]);
  934.     }
  935.     return(key);
  936. }
  937.  
  938.  
  939. /****** gadlayout/FreeLayoutGadgets *****************************************
  940. *
  941. *   NAME
  942. *       FreeLayoutGadgets -- Frees gadgets laid out with LayoutGadgets().
  943. *
  944. *   SYNOPSIS
  945. *       FreeLayoutGadgets(gad_info);
  946. *       VOID FreeLayoutGadgets(APTR);
  947. *
  948. *   FUNCTION
  949. *       Frees all resources used in creating and laying out gadgets with
  950. *       LayoutGadgets().  This frees all gadgets as well as other
  951. *       resources used.  Generally this will be called after a call to
  952. *       CloseWindow() in Intuition.
  953. *
  954. *   INPUTS
  955. *       gad_info - The pointer returned by LayoutGadgets().
  956. *
  957. *   SEE ALSO
  958. *       LayoutGadgetsA()
  959. *
  960. *****************************************************************************
  961. *
  962. * PrivateInfo is a private data-type, and therefore this function is
  963. * documented as taking APTR.
  964. *
  965. *  Have you read the license info?  It tells you that you must send your
  966. *  modifications of GadLayout to me, and that you may not make GadLayout
  967. *  into a shared library.
  968. *
  969. */
  970. VOID FreeLayoutGadgets(struct PrivateInfo *pi)
  971. {
  972.     struct Gadget *g;
  973.  
  974.     if (pi)
  975.     {
  976.         g = pi->pi_GadList;
  977.  
  978.         /* while (g)
  979.         {
  980.             if ((g->MutualExclude & GADLAYOUT_KIND) == GADLAYOUT_KIND)
  981.             {
  982.                 struct Image *image = (struct Image *)g->GadgetRender;
  983.                 WORD i;
  984.  
  985.                 for(i = 0 ; i < 2 ; i++)
  986.                     FreeVec(image[i].ImageData);
  987.  
  988.                 FreeVec(image);
  989.             }
  990.             g = g->NextGadget;
  991.         } */
  992.         FreeRemember(&(pi->pi_Remember), TRUE);
  993.  
  994.         if (pi->pi_VisualInfo)
  995.             FreeVisualInfo(pi->pi_VisualInfo);
  996.          if (pi->pi_DrawInfo)
  997.             FreeScreenDrawInfo(pi->pi_Screen, pi->pi_DrawInfo);
  998.         if (pi->pi_GadList)
  999.             FreeGadgets(pi->pi_GadList);
  1000.  
  1001.         FreeVec(pi);
  1002.     }
  1003. }
  1004.  
  1005.  
  1006. /* Local routine that handles the layout tag list.  Each tag is evaluated
  1007.  * and the NewGadget structure for the gadget is setup.
  1008.  */
  1009. VOID evaluate_gadget(struct PrivateInfo *pi, WORD gad_num, struct LayoutGadget *gadgets,
  1010.                      struct NewGadget *ng, struct LaidOutGadget *gad_array)
  1011. {
  1012.     struct TagItem *tag=NULL, *tstate;
  1013.     struct NewGadget temp_ng;
  1014.     ULONG gad_kind=BUTTON_KIND;
  1015.     LONG textwidth;
  1016.     WORD found_num=0;
  1017.     BOOL extended_kind=FALSE;
  1018.  
  1019.     /* If we are already evaluating this gadgeting, then we won't risk a
  1020.      * recursive state by trying to do it again.
  1021.      */
  1022.     if (gad_array[gad_num].log_IsEvaluated)
  1023.         return;
  1024.  
  1025.     gad_array[gad_num].log_IsEvaluated = TRUE;
  1026.  
  1027.     ng->ng_GadgetID = gadgets[gad_num].lg_GadgetID;
  1028.  
  1029.     /* Look at each tag item sequentially.
  1030.      */
  1031.     tstate = gadgets[gad_num].lg_LayoutTags;
  1032.     while (tag = NextTagItem(&tstate))
  1033.     {
  1034.         switch (tag->ti_Tag)
  1035.         {
  1036.             case GL_GadgetKind:
  1037.                 /* Use a GadTools gadget, ti_Data indicates which kind (from
  1038.                  * libraries/gadtools.h).
  1039.                  */
  1040. #ifdef GL_DEBUG
  1041.                 Printf("Gadget: %ld  Tag: GL_GadgetKind  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID ,tag->ti_Data);
  1042. #endif
  1043.                 gad_kind = tag->ti_Data;
  1044.  
  1045.                 switch (tag->ti_Data)
  1046.                 {
  1047.                     case IMAGEBUTTON_KIND:
  1048.                     case BORDERBUTTON_KIND:
  1049.                     case DRAWER_KIND:
  1050.                     case FILE_KIND:
  1051.                         extended_kind = TRUE;
  1052.                         break;
  1053.                     default:
  1054.                         extended_kind = FALSE;
  1055.                         break;
  1056.                 }
  1057.                 break;
  1058.  
  1059.             case GL_GadgetText:
  1060.                 /* Gadget label.
  1061.                  */
  1062. #ifdef GL_DEBUG
  1063.                 Printf("Gadget: %ld  Tag: GL_GadgetText  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID ,tag->ti_Data);
  1064. #endif
  1065.                 ng->ng_GadgetText = (STRPTR)tag->ti_Data;
  1066.                 break;
  1067.  
  1068.             case GL_LocaleText:
  1069.                 /* Gadget label.
  1070.                  */
  1071. #ifdef GL_DEBUG
  1072.                 Printf("Gadget: %ld  Tag: GL_LocaleText  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID ,tag->ti_Data);
  1073. #endif
  1074.                 ng->ng_GadgetText = get_locale_string(pi->pi_Catalog, pi->pi_AppStrings, tag->ti_Data);
  1075.                 break;
  1076.  
  1077.             case GL_TextAttr:
  1078.                 /* Desired font for gadget label.
  1079.                  */
  1080. #ifdef GL_DEBUG
  1081.                 Printf("Gadget: %ld  Tag: GL_TextAttr  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1082. #endif
  1083.                 ng->ng_TextAttr = (struct TextAttr *)tag->ti_Data;
  1084.                 break;
  1085.  
  1086.             case GL_Flags:
  1087.                 /* Gadget flags.
  1088.                  */
  1089. #ifdef GL_DEBUG
  1090.                 Printf("Gadget: %ld  Tag: GL_Flags  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1091. #endif
  1092.                 ng->ng_Flags = tag->ti_Data;
  1093.                 break;
  1094.  
  1095.             case GL_UserData:
  1096.                 /* Gadget UserData.
  1097.                  */
  1098. #ifdef GL_DEBUG
  1099.                 Printf("Gadget: %ld  Tag: GL_UserData  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1100. #endif
  1101.                 ng->ng_UserData = (APTR)tag->ti_Data;
  1102.                 break;
  1103.  
  1104.             case GL_Width:
  1105.                 /* Absolute gadget width.
  1106.                  */
  1107. #ifdef GL_DEBUG
  1108.                 Printf("Gadget: %ld  Tag: GL_Width  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1109. #endif
  1110.                 ng->ng_Width = tag->ti_Data;
  1111.                 break;
  1112.  
  1113.             case GL_AutoWidth:
  1114.                 /* Set width according to length of text label + (LONG)ti_Data.
  1115.                  */
  1116. #ifdef GL_DEBUG
  1117.                 Printf("Gadget: %ld  Tag: GL_AutoWidth  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1118. #endif
  1119.                 textwidth = text_width(ng->ng_GadgetText, ng->ng_TextAttr);
  1120.                 ng->ng_Width = textwidth + (LONG)tag->ti_Data;
  1121.                 break;
  1122.  
  1123.             case GL_Columns:
  1124.                 /* Set width according to approximately fit ti_Data columns.
  1125.                  */
  1126. #ifdef GL_DEBUG
  1127.                 Printf("Gadget: %ld  Tag: GL_Columns  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1128. #endif
  1129.                 {
  1130.                     char tempstr[2] = "X";
  1131.  
  1132.                     textwidth = text_width(tempstr, ng->ng_TextAttr) * (WORD)tag->ti_Data;
  1133.                     ng->ng_Width = textwidth;
  1134.                 }
  1135.                 break;
  1136.  
  1137.             case GL_MinWidth:
  1138.                 /* Make sure the width is at least a certain value.
  1139.                  */
  1140. #ifdef GL_DEBUG
  1141.                 Printf("Gadget: %ld  Tag: GL_MinWidth  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1142. #endif
  1143.                 if (ng->ng_Width < (LONG)tag->ti_Data)
  1144.                     ng->ng_Width = (LONG)tag->ti_Data;
  1145.                 break;
  1146.  
  1147.             case GL_MaxWidth:
  1148.                 /* Make sure the width is at most a certain value.
  1149.                  */
  1150. #ifdef GL_DEBUG
  1151.                 Printf("Gadget: %ld  Tag: GL_MaxWidth  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1152. #endif
  1153.                 if (ng->ng_Width > (LONG)tag->ti_Data)
  1154.                     ng->ng_Width = (LONG)tag->ti_Data;
  1155.                 break;
  1156.  
  1157.             case GL_Height:
  1158.                 /* Absolute gadget height.
  1159.                  */
  1160. #ifdef GL_DEBUG
  1161.                 Printf("Gadget: %ld  Tag: GL_Height  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1162. #endif
  1163.                 ng->ng_Height = tag->ti_Data;
  1164.                 break;
  1165.  
  1166.             case GL_DupeHeight:
  1167.                 /* Duplicate the height of another gadget.
  1168.                  */
  1169. #ifdef GL_DEBUG
  1170.                 Printf("Gadget: %ld  Tag: GL_DupeHeight  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1171. #endif
  1172.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1173.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1174.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1175.                     sizeof(struct NewGadget));
  1176.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1177.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1178.                 ng->ng_Height = gad_array[found_num].log_NewGadget.ng_Height;
  1179.                 break;
  1180.  
  1181.             case GL_HeightFactor:
  1182.                 /* Make height a multiple of the font height.
  1183.                  */
  1184. #ifdef GL_DEBUG
  1185.                 Printf("Gadget: %ld  Tag: GL_HeightFactor  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1186. #endif
  1187.                 ng->ng_Height = tag->ti_Data * ng->ng_TextAttr->ta_YSize;
  1188.                 break;
  1189.  
  1190.             case GL_AutoHeight:
  1191.                 /* Set height according to height of text font + (LONG)ti_Data.
  1192.                  */
  1193. #ifdef GL_DEBUG
  1194.                 Printf("Gadget: %ld  Tag: GL_AutoHeight  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1195. #endif
  1196.                 ng->ng_Height = ng->ng_TextAttr->ta_YSize + 2 + (LONG)tag->ti_Data;
  1197.                 break;
  1198.  
  1199.             case GL_AddHeight:
  1200.                 /* Add some value to the total height calculation.
  1201.                  */
  1202. #ifdef GL_DEBUG
  1203.                 Printf("Gadget: %ld  Tag: GL_AddHeight  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1204. #endif
  1205.                 ng->ng_Height += (LONG)tag->ti_Data;
  1206.                 break;
  1207.  
  1208.             case GL_MinHeight:
  1209.                 /* Make sure the height is at least a certain value.
  1210.                  */
  1211. #ifdef GL_DEBUG
  1212.                 Printf("Gadget: %ld  Tag: GL_MinHeight  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1213. #endif
  1214.                 if (ng->ng_Height < (LONG)tag->ti_Data)
  1215.                     ng->ng_Height = (LONG)tag->ti_Data;
  1216.                 break;
  1217.  
  1218.             case GL_MaxHeight:
  1219.                 /* Make sure the height is at most a certain value.
  1220.                  */
  1221. #ifdef GL_DEBUG
  1222.                 Printf("Gadget: %ld  Tag: GL_MaxHeight  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1223. #endif
  1224.                 if (ng->ng_Height > (LONG)tag->ti_Data)
  1225.                     ng->ng_Height = (LONG)tag->ti_Data;
  1226.                 break;
  1227.  
  1228.             case GL_Top:
  1229.                 /* Absolute top edge.
  1230.                  */
  1231. #ifdef GL_DEBUG
  1232.                 Printf("Gadget: %ld  Tag: GL_Top  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1233. #endif
  1234.                 ng->ng_TopEdge = tag->ti_Data;
  1235.                 break;
  1236.  
  1237.             case GL_Bottom:
  1238.                 /* Absolute bottom edge.
  1239.                  */
  1240. #ifdef GL_DEBUG
  1241.                 Printf("Gadget: %ld  Tag: GL_Bottom  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1242. #endif
  1243.                 ng->ng_TopEdge = tag->ti_Data - ng->ng_Height;
  1244.                 break;
  1245.  
  1246.             case GL_Left:
  1247.                 /* Absolute left edge.
  1248.                  */
  1249. #ifdef GL_DEBUG
  1250.                 Printf("Gadget: %ld  Tag: GL_Left  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1251. #endif
  1252.                 ng->ng_LeftEdge = tag->ti_Data;
  1253.                 break;
  1254.  
  1255.             case GL_Right:
  1256.                 /* Absolute right edge.
  1257.                  */
  1258. #ifdef GL_DEBUG
  1259.                 Printf("Gadget: %ld  Tag: GL_Right  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1260. #endif
  1261.                 ng->ng_LeftEdge = tag->ti_Data - ng->ng_Width;
  1262.                 break;
  1263.  
  1264.             case GL_DupeWidth:
  1265.                 /* Duplicate the width of another gadget.
  1266.                  */
  1267. #ifdef GL_DEBUG
  1268.                 Printf("Gadget: %ld  Tag: GL_DupeWidth  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1269. #endif
  1270.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1271.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1272.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1273.                     sizeof(struct NewGadget));
  1274.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1275.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1276.                 ng->ng_Width = gad_array[found_num].log_NewGadget.ng_Width;
  1277.                 break;
  1278.  
  1279.             case GL_AddWidth:
  1280.                 /* Add some value to the total width calculation.
  1281.                  */
  1282. #ifdef GL_DEBUG
  1283.                 Printf("Gadget: %ld  Tag: GL_AddWidth  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1284. #endif
  1285.                 ng->ng_Width += (LONG)tag->ti_Data;
  1286.                 break;
  1287.  
  1288.             case GL_LeftRel:
  1289.                 /* Left edge relative to right edge of previous gadget.
  1290.                  */
  1291. #ifdef GL_DEBUG
  1292.                 Printf("Gadget: %ld  Tag: GL_LeftRel  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1293. #endif
  1294.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1295.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1296.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1297.                     sizeof(struct NewGadget));
  1298.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1299.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1300.                 ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge + gad_array[tag->ti_Data].log_NewGadget.ng_Width;
  1301.                 break;
  1302.  
  1303.             case GL_AlignLeft:
  1304.                 /* Align left edge with the left edge of another gadget.
  1305.                  */
  1306. #ifdef GL_DEBUG
  1307.                 Printf("Gadget: %ld  Tag: GL_AlignLeft  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1308. #endif
  1309.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1310.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1311.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1312.                     sizeof(struct NewGadget));
  1313.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1314.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1315.                 ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge;
  1316.                 break;
  1317.  
  1318.             case GL_AdjustLeft:
  1319.                 /* ADD the width of the text label + ti_Data to the left edge.
  1320.                  */
  1321. #ifdef GL_DEBUG
  1322.                 Printf("Gadget: %ld  Tag: GL_AdjustLeft  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1323. #endif
  1324.                 textwidth = text_width(ng->ng_GadgetText, ng->ng_TextAttr);
  1325.                 ng->ng_LeftEdge += textwidth + (LONG)tag->ti_Data;
  1326.                 break;
  1327.  
  1328.             case GL_AddLeft:
  1329.                 /* Add some value to the final left edge calculation.
  1330.                  */
  1331. #ifdef GL_DEBUG
  1332.                 Printf("Gadget: %ld  Tag: GL_AddLeft  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1333. #endif
  1334.                 ng->ng_LeftEdge += (LONG)tag->ti_Data;
  1335.                 break;
  1336.  
  1337.             case GL_TopRel:
  1338.                 /* Top edge relative to bottom edge of another gadget.
  1339.                  */
  1340. #ifdef GL_DEBUG
  1341.                 Printf("Gadget: %ld  Tag: GL_TopRel  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1342. #endif
  1343.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1344.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1345.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1346.                     sizeof(struct NewGadget));
  1347.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1348.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1349.                 ng->ng_TopEdge = gad_array[found_num].log_NewGadget.ng_TopEdge
  1350.                                  + gad_array[found_num].log_NewGadget.ng_Height;
  1351.                 break;
  1352.  
  1353.             case GL_BottomRel:
  1354.                 /* Bottom edge relative to top edge of another gadget.
  1355.                  */
  1356. #ifdef GL_DEBUG
  1357.                 Printf("Gadget: %ld  Tag: GL_BottomRel  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1358. #endif
  1359.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1360.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1361.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1362.                     sizeof(struct NewGadget));
  1363.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1364.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1365.                 ng->ng_TopEdge = gad_array[found_num].log_NewGadget.ng_TopEdge - ng->ng_Height;
  1366.                 break;
  1367.  
  1368.             case GL_AdjustTop:
  1369.                 /* ADD the height of the text font + ti_Data to the top edge.
  1370.                  */
  1371. #ifdef GL_DEBUG
  1372.                 Printf("Gadget: %ld  Tag: GL_AdjustTop  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1373. #endif
  1374.                 ng->ng_TopEdge += ng->ng_TextAttr->ta_YSize + (LONG)tag->ti_Data;
  1375.                 break;
  1376.  
  1377.             case GL_AlignTop:
  1378.                 /* Align left edge with the left edge of another gadget.
  1379.                  */
  1380. #ifdef GL_DEBUG
  1381.                 Printf("Gadget: %ld  Tag: GL_AlignTop  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1382. #endif
  1383.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1384.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1385.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1386.                     sizeof(struct NewGadget));
  1387.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1388.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1389.                 ng->ng_TopEdge = gad_array[found_num].log_NewGadget.ng_TopEdge;
  1390.                 break;
  1391.  
  1392.             case GL_AddTop:
  1393.                 /* Add some value to the final top edge calculation.
  1394.                  */
  1395. #ifdef GL_DEBUG
  1396.                 Printf("Gadget: %ld  Tag: GL_AddTop  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1397. #endif
  1398.                 ng->ng_TopEdge += (LONG)tag->ti_Data;
  1399.                 break;
  1400.  
  1401.             case GL_AlignBottom:
  1402.                 /* Align left edge with the left edge of another gadget.
  1403.                  */
  1404. #ifdef GL_DEBUG
  1405.                 Printf("Gadget: %ld  Tag: GL_AlignBottom  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1406. #endif
  1407.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1408.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1409.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1410.                     sizeof(struct NewGadget));
  1411.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1412.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1413.                 ng->ng_TopEdge = gad_array[found_num].log_NewGadget.ng_TopEdge
  1414.                                   + gad_array[found_num].log_NewGadget.ng_Height
  1415.                                   - ng->ng_Height;
  1416.                 break;
  1417.  
  1418.             case GL_AddBottom:
  1419.                 /* Add some value to the final bottom edge calculation.
  1420.                  */
  1421. #ifdef GL_DEBUG
  1422.                 Printf("Gadget: %ld  Tag: GL_AddBottom  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1423. #endif
  1424.                 ng->ng_TopEdge += (LONG)tag->ti_Data;
  1425.                 break;
  1426.  
  1427.             case GL_RightRel:
  1428.                 /* Right edge relative to left edge of another gadget.
  1429.                  */
  1430. #ifdef GL_DEBUG
  1431.                 Printf("Gadget: %ld  Tag: GL_RightRel  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1432. #endif
  1433.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1434.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1435.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1436.                     sizeof(struct NewGadget));
  1437.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1438.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1439.                 ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge
  1440.                                   - ng->ng_Width;
  1441.                 break;
  1442.  
  1443.             case GL_AlignRight:
  1444.                 /* Align right edge with the right edge of another gadget.
  1445.                  */
  1446. #ifdef GL_DEBUG
  1447.                 Printf("Gadget: %ld  Tag: GL_AlignRight  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1448. #endif
  1449.                 found_num = GadgetArrayIndex(tag->ti_Data, gadgets);
  1450.                 gad_array[gad_num].log_GadgetKind = gad_kind;
  1451.                 CopyMem(ng, &(gad_array[gad_num].log_NewGadget),
  1452.                     sizeof(struct NewGadget));
  1453.                 CopyMem(ng, &temp_ng, sizeof(struct NewGadget));
  1454.                 evaluate_gadget(pi, found_num, gadgets, &temp_ng, gad_array);
  1455.                 ng->ng_LeftEdge = gad_array[found_num].log_NewGadget.ng_LeftEdge
  1456.                                   + gad_array[found_num].log_NewGadget.ng_Width
  1457.                                   - ng->ng_Width;
  1458.                 break;
  1459.  
  1460.             case GL_AddRight:
  1461.                 /* Add some value to the final right edge calculation.
  1462.                  */
  1463. #ifdef GL_DEBUG
  1464.                 Printf("Gadget: %ld  Tag: GL_AddRight  Data: %ld\n", (LONG)gadgets[gad_num].lg_GadgetID, tag->ti_Data);
  1465. #endif
  1466.                 ng->ng_LeftEdge += (LONG)tag->ti_Data;
  1467.                 break;
  1468.  
  1469.             default:
  1470.                 break;
  1471.         }
  1472.     }
  1473.  
  1474.     /* Now copy everything we know into the NewGadget structure.
  1475.      */
  1476.     gad_array[gad_num].log_GadgetKind = gad_kind;
  1477.     CopyMem(ng, &(gad_array[gad_num].log_NewGadget), sizeof(struct NewGadget));
  1478. }
  1479.  
  1480.  
  1481. /* Local routine to determine how many pixels wide a string will be with a
  1482.  * given font.
  1483.  */
  1484. LONG text_width(char *str, struct TextAttr *font)
  1485. {
  1486.     struct IntuiText itext;
  1487.  
  1488.     itext.IText=str;
  1489.     itext.ITextFont=font;
  1490.     itext.FrontPen=1;
  1491.     itext.BackPen=0;
  1492.     itext.DrawMode=JAM1;
  1493.     itext.LeftEdge=0;
  1494.     itext.TopEdge=0;
  1495.     itext.NextText=NULL;
  1496.  
  1497.     return(IntuiTextLength(&itext));
  1498. }
  1499.  
  1500.  
  1501. /* Local routine to get a localized text string, given its ID.
  1502.  */
  1503. STRPTR get_locale_string(struct Catalog *catalog, struct AppString *appstrings,
  1504.                          LONG id)
  1505. {
  1506.     UWORD i=0;
  1507.     STRPTR local = NULL;
  1508.  
  1509.     if (appstrings)
  1510.     {
  1511.         while (!local)
  1512.         {
  1513.             if (appstrings[i].as_ID == id)
  1514.                 local = appstrings[i].as_Str;
  1515.             i++;
  1516.         }
  1517.  
  1518.         if (LocaleBase)
  1519.             return(GetCatalogStr(catalog, id, local));
  1520.     }
  1521.  
  1522.     return(local);
  1523. }
  1524.  
  1525.  
  1526. /* Locale function to create one of GadLayout's extended gadgets.
  1527.  */
  1528. struct Gadget * create_layout_gad(struct PrivateInfo *pi, WORD gad_kind,
  1529.                                   struct Gadget *last_gad, struct NewGadget *ng,
  1530.                                   struct TagItem *taglist)
  1531. {
  1532.     struct Gadget *gad=NULL, *textgad=NULL;
  1533.     struct TagItem *tag;
  1534.     struct Image *image, *temp_image;
  1535.     struct NewGadget textng;
  1536.     BOOL readonly=FALSE, toggle=FALSE;
  1537.  
  1538.     switch (gad_kind)
  1539.     {
  1540.         case IMAGEBUTTON_KIND:
  1541.         case FILE_KIND:
  1542.         case DRAWER_KIND:
  1543.             if (gad_kind == IMAGEBUTTON_KIND)
  1544.             {
  1545.                 if (tag = FindTagItem(GLIM_Image, taglist))
  1546.                 {
  1547. #ifdef GL_DEBUG
  1548.                     Printf("Tag: GLIM_Image  Data: %ld\n",tag->ti_Data);
  1549. #endif
  1550.                     temp_image = (struct Image *)tag->ti_Data;
  1551.                 }
  1552.                 if (tag = FindTagItem(GLIM_ReadOnly, taglist))
  1553.                 {
  1554. #ifdef GL_DEBUG
  1555.                     Printf("Tag: GLIM_ReadOnly  Data: %ld\n",tag->ti_Data);
  1556. #endif
  1557.                     readonly = tag->ti_Data;
  1558.                 }
  1559.                 if (tag = FindTagItem(GLIM_Toggle, taglist))
  1560.                 {
  1561. #ifdef GL_DEBUG
  1562.                     Printf("Tag: GLIM_Toggle  Data: %ld\n",tag->ti_Data);
  1563. #endif
  1564.                     toggle = tag->ti_Data;
  1565.                 }
  1566.             }
  1567.             else if (gad_kind == DRAWER_KIND)
  1568.                 temp_image = &drawer_image;
  1569.             else if (gad_kind == FILE_KIND)
  1570.                 temp_image = &file_image;
  1571.  
  1572.             /* Since GENERIC_KIND gadgets don't full support the ng_GadgetText
  1573.              * field, we'll get around this by creating a TEXT_KIND gadget
  1574.              * that displays the text for us.
  1575.              */
  1576.             if (ng->ng_GadgetText)
  1577.             {
  1578.                 CopyMem(ng, &textng, sizeof(struct NewGadget));
  1579.                 textng.ng_GadgetID = 1000;
  1580.  
  1581.                 switch (textng.ng_Flags)
  1582.                 {
  1583.                     case PLACETEXT_LEFT:
  1584.                         textng.ng_Width = 0;
  1585.                         break;
  1586.  
  1587.                     case PLACETEXT_RIGHT:
  1588.                         textng.ng_LeftEdge += textng.ng_Width;
  1589.                         textng.ng_Width = 0;
  1590.                         break;
  1591.  
  1592.                     case PLACETEXT_ABOVE:
  1593.                         textng.ng_Height = 0;
  1594.                         break;
  1595.  
  1596.                     case PLACETEXT_BELOW:
  1597.                         textng.ng_TopEdge += textng.ng_Height;
  1598.                         textng.ng_Height = 0;
  1599.                         break;
  1600.  
  1601.                     default:
  1602.                         break;
  1603.                 }
  1604.                 textgad = last_gad = CreateGadget(TEXT_KIND, last_gad, &textng,
  1605.                                         GT_Underscore, '_',
  1606.                                         TAG_DONE);
  1607.             }
  1608.  
  1609.             ng->ng_GadgetText = NULL;
  1610.  
  1611.             /* Create the image structure, then make the gadget.
  1612.              */
  1613.             if (image = create_gad_images(gad_kind, ng->ng_Width, ng->ng_Height,
  1614.                         pi, temp_image, readonly))
  1615.             {
  1616.                 if (gad = last_gad = CreateGadget(GENERIC_KIND, last_gad, ng,
  1617.                                         TAG_DONE))
  1618.                 {
  1619.                     gad->GadgetType |= GTYP_BOOLGADGET;
  1620.                     gad->GadgetRender = &image[0];
  1621.                     gad->SelectRender = &image[1];
  1622.                     gad->Flags |=  GFLG_GADGIMAGE | ((readonly)? GFLG_GADGHNONE : GFLG_GADGHIMAGE);
  1623.                     gad->Activation |= GACT_RELVERIFY | ((toggle)? GACT_TOGGLESELECT : 0);
  1624.                     gad->MutualExclude = GADLAYOUT_KIND | ((readonly)? GLFLG_READONLY : 0) | ((toggle)? GLFLG_TOGGLE : 0);
  1625.                 }
  1626.                 else
  1627.                 {
  1628. #ifdef GL_DEBUG
  1629.                     PutStr("Couldn't create GadLayout gadget\n");
  1630. #endif
  1631.                 }
  1632.             }
  1633.             else
  1634.             {
  1635. #ifdef GL_DEBUG
  1636.                 PutStr("Couldn't create GadLayout imagery\n");
  1637. #endif
  1638.             }
  1639.             ng->ng_GadgetText = textng.ng_GadgetText;
  1640.  
  1641.             break;
  1642.  
  1643.         default:
  1644.             break;
  1645.     }
  1646.     return(gad);
  1647. }
  1648.  
  1649.  
  1650. /* Local routine to return image structures for IMAGEBUTTON_KIND, DRAWER_KIND and
  1651.  * FILE_KIND gadgets.
  1652.  */
  1653. struct Image * create_gad_images(WORD gad_kind, UWORD width, UWORD height,
  1654.                                  struct PrivateInfo *pi, struct Image *image,
  1655.                                  BOOL readonly)
  1656. {
  1657.     struct Image *new_image = NULL;
  1658.     struct Remember *image_rem = NULL;
  1659.     UWORD image_width = 8, image_height = 8;
  1660.  
  1661.     /* Minimum size required.
  1662.      */
  1663.     if (image)
  1664.     {
  1665.         image_width = image->Width;
  1666.         image_height = image->Height;
  1667.     }
  1668.     if ((width >= image_width + 4) && (height >= image_height + 2))
  1669.     {
  1670.         struct RastPort    *rport;
  1671.  
  1672.         /* Allocate local dummy rastport.
  1673.          */
  1674.         if (rport = (struct RastPort *)AllocRemember(&image_rem, sizeof(struct RastPort), MEMF_ANY))
  1675.         {
  1676.             struct BitMap *bitmap[2] = { NULL, NULL };
  1677.             struct Layer_Info *layer_info[2] = { NULL, NULL };
  1678.             struct Layer *layer[2] = { NULL, NULL };
  1679.             BYTE success = FALSE;
  1680.             WORD depth, i,j;
  1681.  
  1682.             /* Determine screen depth.
  1683.              */
  1684.             depth = pi->pi_Screen->RastPort.BitMap->Depth;
  1685.  
  1686.             /* Set up rastport.
  1687.              */
  1688.             InitRastPort(rport);
  1689.  
  1690.             /* Allocate bitmaps and bitplane data.
  1691.              */
  1692.             success = TRUE;
  1693.  
  1694.             for (i = 0 ; success && i < 2 ; i++)
  1695.             {
  1696.                 if (bitmap[i] = (struct BitMap *)AllocRemember(&image_rem, sizeof(struct BitMap), MEMF_ANY))
  1697.                 {
  1698.                     InitBitMap(bitmap[i], depth, width, height);
  1699.  
  1700.                     if (bitmap[i]->Planes[0] = (PLANEPTR)AllocRemember(&(pi->pi_Remember), bitmap[i]->BytesPerRow * bitmap[i]->Rows * bitmap[i]->Depth, MEMF_CHIP | MEMF_CLEAR))
  1701.                     {
  1702.                         for (j = 1 ; j < depth ; j++)
  1703.                             bitmap[i]->Planes[j] = bitmap[i]->Planes[j - 1] + bitmap[i]->BytesPerRow * bitmap[i]->Rows;
  1704.                     }
  1705.                     else
  1706.                         success = FALSE;
  1707.                 }
  1708.                 else
  1709.                     success = FALSE;
  1710.             }
  1711.  
  1712.             /* Did we get what we wanted?
  1713.              */
  1714.             if (success)
  1715.             {
  1716.                 __aligned struct BitMap temp_bitmap;
  1717.                 WORD left, top;
  1718.  
  1719.                 /* Centre the image.
  1720.                  */
  1721.                 left = (width - image_width) / 2;
  1722.                 top    = (height - image_height) / 2;
  1723.  
  1724.                 /* Set up the drawer bitmap.
  1725.                  */
  1726.                 InitBitMap(&temp_bitmap, depth, image_width, image_height);
  1727.  
  1728.                 /* Put the mask into all bitplanes.
  1729.                  */
  1730.                 if (image)
  1731.                     for (i = 0 ; i < depth ; i++)
  1732.                         temp_bitmap.Planes[i] = (PLANEPTR)image->ImageData;
  1733.  
  1734.                 /* Manipulate the first bitmap.
  1735.                  */
  1736.                 rport->BitMap = bitmap[0];
  1737.  
  1738.                 /* Clear the bitmap.
  1739.                  */
  1740.                 SetRast(rport, pi->pi_DrawInfo->dri_Pens[BACKGROUNDPEN]);
  1741.  
  1742.                 if ((gad_kind == DRAWER_KIND) || (gad_kind == FILE_KIND))
  1743.                 {
  1744.                     UBYTE minterm, mask;
  1745.  
  1746.                     /* Clear the drawer mask.
  1747.                      */
  1748.                     minterm = 0x20;
  1749.                     mask = (1 << depth) - 1;
  1750.  
  1751.                     BltBitMap(&temp_bitmap, 0, 0,
  1752.                               bitmap[0], left, top,
  1753.                               image_width, image_height,
  1754.                               minterm, mask, NULL);
  1755.  
  1756.                     minterm = 0xe0;
  1757.                     mask = pi->pi_DrawInfo->dri_Pens[TEXTPEN];
  1758.  
  1759.                     BltBitMap(&temp_bitmap, 0, 0,
  1760.                               bitmap[0], left, top,
  1761.                               image_width, image_height,
  1762.                               minterm, mask, NULL);
  1763.                 }
  1764.                 else if (gad_kind == IMAGEBUTTON_KIND)
  1765.                 {
  1766.                     if (image)
  1767.                         DrawImage(rport, image, left, top);
  1768.                 }
  1769.                 /* Draw the button box.
  1770.                  */
  1771.                 DrawBevelBox(rport, 0, 0, width, height,
  1772.                     ((readonly)? GTBB_Recessed : TAG_IGNORE), TRUE,
  1773.                     GT_VisualInfo, pi->pi_VisualInfo,            
  1774.                     TAG_DONE);
  1775.  
  1776.                 /* Create the selected imagery.
  1777.                  */
  1778.                 rport->BitMap = bitmap[1];
  1779.  
  1780.                 if ((gad_kind == DRAWER_KIND) || (gad_kind == FILE_KIND))
  1781.                 {
  1782.                     /* Set the bitmap to the selected button colour.
  1783.                      */
  1784.                     SetRast(rport, pi->pi_DrawInfo->dri_Pens[FILLPEN]);
  1785.  
  1786.                     /* Clear the drawer mask.
  1787.                      */
  1788.                     BltBitMap(&temp_bitmap, 0, 0,
  1789.                               bitmap[1], left, top,
  1790.                               image_width, image_height,
  1791.                               0x20, (1 << depth) - 1, NULL);
  1792.  
  1793.                     /* Draw the drawer mask.
  1794.                      */
  1795.                     BltBitMap(&temp_bitmap, 0, 0,
  1796.                               bitmap[1], left, top,
  1797.                               image_width, image_height,
  1798.                               0xe0, pi->pi_DrawInfo->dri_Pens[FILLTEXTPEN], NULL);
  1799.                 }
  1800.                 else if (gad_kind == IMAGEBUTTON_KIND)
  1801.                 {
  1802.                     if (image)
  1803.                     {
  1804.                         VOID *buffer=NULL;
  1805.  
  1806.                         DrawImage(rport, image, left, top);
  1807.  
  1808.                         /* if (buffer = AllocVec(width * height, MEMF_CHIP|MEMF_CLEAR))
  1809.                         {
  1810.                             struct TmpRas tmpras;
  1811.  
  1812.                             InitTmpRas(&tmpras, buffer, width * height);
  1813.                             rport->TmpRas = &tmpras;
  1814.  
  1815.                             SetAPen(rport, pi->pi_DrawInfo->dri_Pens[FILLPEN]);
  1816.  
  1817.                             Flood(rport, 1, 0, 0);
  1818.  
  1819.                             FreeVec(buffer);
  1820.                         } */
  1821.                     }
  1822.                 }
  1823.                 /* Draw the selected button box.
  1824.                  */
  1825.                 DrawBevelBox(rport, 0, 0, width, height,
  1826.                     ((!readonly)? GTBB_Recessed : TAG_IGNORE), TRUE,
  1827.                     GT_VisualInfo, pi->pi_VisualInfo,            
  1828.                     TAG_DONE);
  1829.  
  1830.                 /* Allocate space for standard image and selected image.
  1831.                  */
  1832.                 if (new_image = (struct Image *)AllocRemember(&(pi->pi_Remember), 2 * sizeof(struct Image), MEMF_CHIP | MEMF_CLEAR))
  1833.                 {
  1834.                     /* Fill in the standard data.
  1835.                      */
  1836.                     for (i = 0 ; i <= 1 ; i++)
  1837.                     {
  1838.                         new_image[i].Width = width;
  1839.                         new_image[i].Height = height;
  1840.                         new_image[i].Depth = depth;
  1841.                         new_image[i].ImageData = (UWORD *)bitmap[i]->Planes[0];
  1842.                         new_image[i].PlanePick = (1 << depth) - 1;
  1843.                     }
  1844.                 }
  1845.                 /* for (i = 0; i < 2; i++)
  1846.                     FreeVec(bitmap[i]->Planes[0]); */
  1847.             }
  1848.         }
  1849.     }
  1850.     /* Free all memory.
  1851.      */
  1852.     FreeRemember(&image_rem, TRUE);
  1853.  
  1854.     return(new_image);
  1855. }
  1856.