home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / fish / 911-930 / ff911 / gadlayout / gadlayout.c < prev    next >
C/C++ Source or Header  |  1994-05-04  |  54KB  |  1,642 lines

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