home *** CD-ROM | disk | FTP | other *** search
/ The AGA Experience 2 / agavol2.iso / software / sound / utils / gfft-2.03 / source / gfft-2.03-source.lha / wbtools.c < prev   
Encoding:
C/C++ Source or Header  |  1996-01-02  |  36.6 KB  |  1,344 lines

  1. /***************************************************************************
  2.  *          Copyright (C) 1994  Charles P. Peterson                  *
  3.  *         4007 Enchanted Sun, San Antonio, Texas 78244-1254             *
  4.  *              Email: Charles_P_Peterson@fcircus.sat.tx.us                *
  5.  *                                                                         *
  6.  *          This is free software with NO WARRANTY.                  *
  7.  *          See gfft.c, or run program itself, for details.              *
  8.  *              Support is available for a fee.                      *
  9.  ***************************************************************************
  10.  *
  11.  * Program:     gfft--General FFT analysis
  12.  * File:        wbtools.c
  13.  * Purpose:     workbench GUI toolkit for GFFT
  14.  * Author:      Charles Peterson (CPP)
  15.  * History:     19-Nov-1993 CPP; Created.
  16.  *              4-Aug-94 CPP (1.04); Filenames may contain spaces
  17.  *              14-Dec-94 CPP (1.16); Fix message indicator for >4 colors
  18.  *              14-Dec-94 CPP (1.17); Fix button gadgets for >4 colors
  19.  *               5-Jan-95 CPP (1.18); Use system default font if possible
  20.  *              17-Jan-95 CPP (1.20); Size shells nicely
  21.  *              26-Jan-95 CPP (1.26); Allow largest possible font size
  22.  *              27-Jan-95 CPP (1.27); Report window open failure
  23.  *              28-Jan-95 CPP (1.29); Labeled radio buttons
  24.  *              28-Jan-95 CPP (1.30); Tall action buttons
  25.  *               6-Feb-95 CPP (1.31); Progress requester gadgets
  26.  *               6-Feb-95 CPP (1.32); Render to window while requester on
  27.  *              10-Feb-95 CPP (1.34); Thicker requester borders
  28.  *
  29.  * Comments:    Workbench GUI.  Amiga Dependent!
  30.  *              There may be other toolkits.  Mine is intended to be
  31.  *              compatible with all releases of AmigaDOS, be fairly
  32.  *              simple, and have a 3d-like look.  I've had to make
  33.  *              some small compromises:  non-toggle gadgets only
  34.  *              have their borders change when selected (the only good way
  35.  *              to get around this is to have multiple images...with about
  36.  *              an order of magnitude increase in complexity...or by using
  37.  *              BOOPSI, which is fairly complicated itself and 2.0+
  38.  *              dependent, or use MUI, which would not only necessitate
  39.  *              a complete re-write but also would introduce some copyright
  40.  *              inconsistencies.  So, my rationalization anyway is that
  41.  *              there is no _perfect_ choice, and the only better choices
  42.  *              would take much more of my time to implement.  I haven't
  43.  *              made enough money on it so far to justify that.
  44.  */
  45.  
  46. #ifdef AMIGA
  47. #define GUI_DEBUG
  48.  
  49. #include <stdio.h>     /* sprintf() */
  50. #include <string.h>
  51. /*
  52.  * Amiga includes
  53.  */
  54. #include <exec/types.h>
  55. #include <exec/exec.h>
  56. #include <workbench/workbench.h>
  57. #include <workbench/icon.h>
  58. #include <workbench/startup.h>
  59. #include <intuition/intuition.h>
  60. #include <intuition/sghooks.h>
  61. #include <clib/intuition_protos.h>
  62. #include <clib/exec_protos.h>
  63. #include <proto/icon.h>
  64. #include <proto/dos.h>
  65. #include <dos/dos.h>
  66. #include <libraries/asl.h>
  67. #include <clib/asl_protos.h>
  68. #include <graphics/text.h>
  69. #include <clib/graphics_protos.h>
  70. #include <graphics/gfxmacros.h>  /* BNDRYOFF */
  71. #include <proto/graphics.h>    /* GfxBase */
  72. #include <graphics/gfxbase.h>
  73.  
  74. #include "gfft.h"
  75. #include "wbench.h"
  76. #include "settings.h"
  77.  
  78. #define USE_MAX_ROWS_FOR_FONT_CHECK
  79.  
  80. /*
  81.  * Dialogue Window parameters...pretty good guesses for 2.0 and 1.3
  82.  * reset later (some require drawinfo to be available for reset)
  83.  */
  84. #define SHINE_PEN_20 2
  85. #define SHADOW_PEN_20 1
  86. #define SHINE_PEN_13 1
  87. #define SHADOW_PEN_13 2
  88. #define TEXT_PEN 1         /* Seems to work well under both 2.0 and 1.3 */
  89. #define FILL_TEXT_PEN 2    /* ditto; hmmn, I like better than 2.0 default */
  90. #define FILL_PEN 3
  91. #define BACKGROUND_PEN 0   /* almost guaranteed now, but may be updated */
  92.  
  93. #define DEFAULT_SCREEN_DEPTH 2
  94. #define DEFAULT_SCREEN_FONT_HEIGHT 8
  95. #define DEFAULT_FONT_HEIGHT 8
  96. #define DEFAULT_FONT_WIDTH 8
  97.  
  98. #define FONT_COLUMNS_REQUIRED 80
  99. #define FONT_ROWS_REQUIRED 24
  100.  
  101. #define DEFAULT_SHELL_WIDTH 640
  102. #define DEFAULT_SHELL_HEIGHT 200
  103.  
  104.  
  105. #define WINDOW_LEFT 0         /* Same as right edge */
  106. #define WINDOW_TOP 0          /* Allow for WB title & click area above */
  107.  
  108. #define FIRST_WINDOW_BUTTON_LEFT 12
  109. #define FIRST_WINDOW_BUTTON_TOP 6
  110.  
  111. #define FIRST_REQUESTER_BUTTON_LEFT 12
  112. #define FIRST_REQUESTER_BUTTON_TOP 6
  113.  
  114. #define BUTTON_SIDE_EDGE (Font_Width)
  115.  
  116. #define BUTTON_TOP_EDGE 3    /* Inside button to text; same as bottom edge*/
  117. #define BUTTON_TOP_SPACE 2   /* Vertical space between buttons */
  118.  
  119. /*
  120.  * Use the following when possible
  121.  */
  122.  
  123. #define BUTTON_WIDTH(WIDTH) ((WIDTH) * Font_Width + 2 * BUTTON_SIDE_EDGE)
  124.  
  125. #define BUTTON_HEIGHT (Font_Height + 2 * BUTTON_TOP_EDGE)
  126. #define BUTTON_SPACING (BUTTON_HEIGHT + BUTTON_TOP_SPACE)
  127. #define BUTTON_TOP(row) (first_button_top + row * BUTTON_SPACING)
  128.  
  129. #define WINDOW_HEIGHT(max_rows) (BUTTON_TOP(max_rows) + \
  130.   BUTTON_TOP_SPACE)  /* for the bottom edge */
  131.  
  132. struct TextAttr FontA = {
  133. "topaz.font",
  134. DEFAULT_FONT_HEIGHT,
  135. NULL,
  136. NULL
  137. };
  138.  
  139. struct TextAttr *FontAp = &FontA;
  140.  
  141. struct TextFont *fontp = NULL; /* Set if system default font used */
  142.  
  143. static short shine_pen = SHINE_PEN_20;
  144. static short shadow_pen = SHADOW_PEN_20;
  145. static short text_pen = TEXT_PEN;
  146. static short fill_pen = FILL_PEN;
  147. static short fill_text_pen = FILL_TEXT_PEN;
  148. static short background_pen = BACKGROUND_PEN;
  149.  
  150. short Screen_Font_Height = DEFAULT_SCREEN_FONT_HEIGHT;
  151. short Font_Height = DEFAULT_FONT_HEIGHT;
  152. short Font_Width = DEFAULT_FONT_WIDTH;
  153. static short screen_depth = DEFAULT_SCREEN_DEPTH;
  154.  
  155. static short first_button_left = FIRST_WINDOW_BUTTON_LEFT;
  156. static short first_button_top = FIRST_WINDOW_BUTTON_TOP + 
  157.                                 DEFAULT_FONT_HEIGHT;
  158. static short max_rows = 0;
  159. static int gadget_type_mode = NULL;
  160. static struct IntuiText *next_textp = NULL;
  161. static struct Gadget *next_gadgetp = NULL;
  162. static struct Requester *current_requesterp = NULL;
  163.  
  164. #define REQUESTER_STACK_DEPTH 10
  165. static struct Requester *requester_stack[REQUESTER_STACK_DEPTH] =
  166. {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  167. static int requester_stack_index = 0;
  168.  
  169.  
  170. struct Library *IntuitionBase = NULL;
  171. BOOLEAN Old_Intuition = FALSE;
  172. short Max_Columns = 0;
  173.  
  174. int Shell_Width = DEFAULT_SHELL_WIDTH;
  175. int Shell_Height = DEFAULT_SHELL_HEIGHT;
  176.  
  177.  
  178. extern struct Library *AslBase;   /* from filereq.c */
  179. extern struct FileRequester *File_Requesterp;
  180.  
  181.  
  182. static struct Gadget *text_button__new (char *text, short tcol, short trow);
  183.  
  184. void open_libraries (void)
  185. {
  186. /*
  187.  * Intuition is currently the only library for which we need to know
  188.  * version number, hence, we have to open it explicitly.
  189.  */
  190.     if (!IntuitionBase)
  191.     {
  192.     IntuitionBase = OpenLibrary ("intuition.library", 37);
  193.     if (IntuitionBase == NULL) 
  194.     {
  195.         Old_Intuition = TRUE;
  196.         IntuitionBase = OpenLibrary ("intuition.library", 0);
  197.         if (IntuitionBase == NULL)
  198.         {
  199.         error_message (CANT_OPEN_INTUITION);
  200.         gabort (EXIT_FAILURE);
  201.         }
  202.     }
  203.     }
  204. }
  205.  
  206. void setup_window_defaults (int max_rows)
  207. {
  208.     struct Screen *screen;
  209.     struct DrawInfo *draw_info;
  210.  
  211.     if (Old_Intuition)
  212.     {
  213.     shine_pen = SHINE_PEN_13;  /* These usually work for 1.3... */
  214.     shadow_pen = SHADOW_PEN_13;  /* Should do this better someday */
  215.     /* everything else is defaulted */
  216.     }
  217.     else  /* Ok, Rev 37 or greater, get pens and fonts */
  218.     {
  219.     if (screen = LockPubScreen (NULL))
  220.     {
  221.         if (draw_info = GetScreenDrawInfo (screen))
  222.         {
  223.         /* vars not used outside this block */
  224.         char *system_default_font_name;
  225.         short system_default_font_height;
  226.         short system_default_font_width;
  227.         short screen_width;
  228.         short screen_height;
  229.         short save_font_height;
  230.         
  231.         shine_pen = draw_info->dri_Pens[SHINEPEN];
  232.         shadow_pen = draw_info->dri_Pens[SHADOWPEN];
  233.         text_pen = draw_info->dri_Pens[TEXTPEN];
  234.         fill_pen = draw_info->dri_Pens[FILLPEN];
  235.         fill_text_pen = draw_info->dri_Pens[FILLTEXTPEN];
  236.         background_pen = draw_info->dri_Pens[BACKGROUNDPEN];
  237.         screen_depth = draw_info->dri_Depth;
  238.         screen_width = screen->Width;
  239.         screen_height = screen->Height;
  240.         Screen_Font_Height = 
  241.           draw_info->dri_Font->tf_YSize;
  242.         first_button_top = FIRST_WINDOW_BUTTON_TOP + 
  243.           Screen_Font_Height;
  244.         /*
  245.          * Get system default font (always monospaced) info...
  246.          * (Maybe if I make some money on this, I'll rewrite to
  247.          * use the screen font (which might be proportional).
  248.          * Test to see that font permits max_rows and
  249.          * FONT_COLUMNS_REQUIRED
  250.          * before using (otherwise, we're defaulting to TOPAZ 8).
  251.          */
  252.         system_default_font_name =
  253.           GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name;
  254.         system_default_font_height =
  255.           GfxBase->DefaultFont->tf_YSize;
  256.         system_default_font_width =
  257.           GfxBase->DefaultFont->tf_XSize;
  258.         
  259.         save_font_height = Font_Height;
  260.         Font_Height = system_default_font_height;
  261.         
  262.         if (!Topaz && 
  263.  
  264. #ifndef FORCE_FONT
  265. #ifndef USE_MAX_ROWS_FOR_FONT_CHECK
  266.             (screen_height  / system_default_font_height >=
  267.              FONT_ROWS_REQUIRED) &&
  268. #else
  269.             (WINDOW_HEIGHT(max_rows) <= screen_height) &&
  270. #endif
  271. #endif
  272.             (screen_width / system_default_font_width >=
  273.              FONT_COLUMNS_REQUIRED))
  274.         {
  275.             FontA.ta_Name = system_default_font_name;
  276.             FontA.ta_YSize = system_default_font_height;
  277.             
  278.             Font_Height = system_default_font_height;
  279.             Font_Width = system_default_font_width;
  280.             
  281.             fontp = GfxBase->DefaultFont;
  282.             
  283. /* Looks nicer without resetting shell height, upped later if needed  */
  284.             
  285.             Shell_Width = FONT_COLUMNS_REQUIRED * 
  286.               system_default_font_width;
  287.         }
  288.         else 
  289.         {
  290.             Font_Height = save_font_height;
  291.             
  292.             Shell_Height = FONT_ROWS_REQUIRED *
  293.               system_default_font_height;
  294.             
  295.             Shell_Width = FONT_COLUMNS_REQUIRED * 
  296.               system_default_font_width;
  297.             
  298.             if (Shell_Height > screen_height)
  299.               Shell_Height = screen_height;
  300.             
  301.             if (Shell_Width > screen_width)
  302.               Shell_Width = screen_width;
  303.         }
  304.         FreeScreenDrawInfo (screen, draw_info);
  305.         }
  306.         UnlockPubScreen (NULL, screen);
  307.     }
  308.     }
  309. }
  310.  
  311. void close_amiga_stuff (void)
  312. {
  313.     if (IntuitionBase)
  314.     {
  315.     CloseLibrary (IntuitionBase);
  316.     IntuitionBase = NULL;
  317.     }
  318.     if (File_Requesterp)
  319.     {
  320.     FreeAslRequest(File_Requesterp);
  321.     File_Requesterp = NULL;
  322.     }
  323.     if (AslBase)
  324.     {
  325.         CloseLibrary(AslBase);
  326.     AslBase = NULL;
  327.     }
  328. }
  329.  
  330.  
  331. void gadget__begin (int gadget_type_flag)
  332. {
  333.     gadget_type_mode = gadget_type_flag;
  334.     Max_Columns = 0;
  335.     max_rows = 0;
  336.     next_textp = NULL;
  337.     next_gadgetp = NULL;
  338.  
  339.     if (gadget_type_mode == GTYP_REQGADGET)
  340.     {
  341.     first_button_left = FIRST_REQUESTER_BUTTON_LEFT;
  342.     first_button_top = FIRST_REQUESTER_BUTTON_TOP;
  343.     }
  344.     else
  345.     {
  346.     first_button_left = FIRST_WINDOW_BUTTON_LEFT;
  347.     first_button_top = FIRST_WINDOW_BUTTON_TOP + Screen_Font_Height;
  348.     }
  349. }
  350.  
  351. struct Border *requester_border__new (short height, short width,
  352.                 short top_pen, short bottom_pen)
  353. {
  354.     struct Border *rborder;
  355.     struct Border *nborder;
  356.  
  357.     rborder = border__new (height-1, width-1, top_pen, bottom_pen);
  358.  
  359.     nborder = rborder->NextBorder->NextBorder = border__new 
  360.       (height-3, width-3, top_pen, bottom_pen);
  361.  
  362.     nborder->LeftEdge += 1;
  363.     nborder->TopEdge += 1;
  364.     nborder->NextBorder->LeftEdge += 1;
  365.     nborder->NextBorder->TopEdge += 1;
  366.  
  367.     nborder = nborder->NextBorder->NextBorder = border__new 
  368.       (height-5, width-5, top_pen, bottom_pen);
  369.  
  370.     nborder->LeftEdge += 2;
  371.     nborder->TopEdge += 2;
  372.     nborder->NextBorder->LeftEdge += 2;
  373.     nborder->NextBorder->TopEdge += 2;
  374.  
  375.     return rborder;
  376. }
  377.  
  378.  
  379. struct Border *button_border__new (short width, short top_pen,
  380.                    short bottom_pen)
  381. {
  382.  
  383.     struct Border *bborder;
  384.  
  385.     bborder = border__new (BUTTON_HEIGHT-1, width-1, top_pen, bottom_pen);
  386.     return bborder;
  387. }
  388.  
  389.  
  390. struct Border *border__new (short height, short width, short top_pen,
  391.                 short bottom_pen)
  392. {
  393.     short *xy_pairs_u, *xy_pairs_l;
  394.     struct Border *border_u, *border_l;
  395.  
  396.     xy_pairs_u = gcalloc (6, sizeof (short), NOTHING_SPECIAL);
  397.     xy_pairs_l = gcalloc (6, sizeof (short), NOTHING_SPECIAL);
  398.     border_u = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL);
  399.     border_l = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL);
  400.  
  401.     xy_pairs_u[0] = 0;
  402.     xy_pairs_u[1] = height;
  403.     xy_pairs_u[2] = 0;
  404.     xy_pairs_u[3] = 0;
  405.     xy_pairs_u[4] = width;
  406.     xy_pairs_u[5] = 0;
  407.  
  408.     xy_pairs_l[0] = 1;        /* Looks a little nicer, I think, than 0 */
  409.     xy_pairs_l[1] = height;
  410.     xy_pairs_l[2] = width;
  411.     xy_pairs_l[3] = height;
  412.     xy_pairs_l[4] = width;
  413.     xy_pairs_l[5] = 0;
  414.  
  415.     border_u->LeftEdge = 0;
  416.     border_u->TopEdge = 0;
  417.     border_u->XY = xy_pairs_u;
  418.     border_u->FrontPen = top_pen;
  419.     border_u->DrawMode = JAM1;
  420.     border_u->NextBorder = border_l;
  421.     border_u->Count = 3;
  422.  
  423.     border_l->LeftEdge = 0;
  424.     border_l->TopEdge = 0;
  425.     border_l->XY = xy_pairs_l;
  426.     border_l->FrontPen = bottom_pen;
  427.     border_l->DrawMode = JAM1;
  428.     border_l->NextBorder = NULL;
  429.     border_l->Count = 3;
  430.  
  431.     return border_u;
  432. }
  433.     
  434.  
  435. struct Gadget *progress_gadget__new (short length, short tcol, short trow)
  436. {
  437.     struct Gadget *gadgetp;
  438.  
  439.     gadgetp = message_gadget__new (length, tcol, trow);
  440.     gadgetp->UserData = NULL;
  441.  
  442.     return gadgetp;
  443. }
  444.  
  445. void progress_gadget__clear (struct Gadget *gadgetp, struct Window *windowp)
  446. {
  447.     gadgetp->UserData = NULL;
  448.     if (gadgetp->GadgetText)
  449.       message_gadget__write (gadgetp, NullString, windowp);
  450. }
  451.  
  452. void progress_gadget__update (struct Gadget *gadgetp,
  453.                   int percentage,
  454.                   struct Window *windowp)
  455. {
  456.     struct RastPort *rport;
  457.     UBYTE save_apen;
  458.     struct Requester *requesterp;
  459.     int last_percentage = (int) gadgetp->UserData;
  460.  
  461.     if (percentage == -1 || last_percentage == -1)
  462.     {
  463.     if (last_percentage == -1) return;
  464.     message_gadget__write (gadgetp, "Unable to measure progress...",
  465.                    windowp);
  466.     gadgetp->UserData = (APTR) -1;
  467.     return;
  468.     }
  469.  
  470.     if (last_percentage >= percentage) return;
  471.     if (percentage > 100 ) percentage = 100;
  472.     gadgetp->UserData = (APTR) percentage;
  473.  
  474.     if (windowp)
  475.     {
  476.     short x1, y1, x2, y2;
  477.  
  478.     x1 = gadgetp->LeftEdge + 3;
  479.     y1 = gadgetp->TopEdge + 2;
  480.  
  481.     x2 = x1 + (gadgetp->Width - 7) * (percentage/100.0);
  482.     y2 = y1 + gadgetp->Height - 5;
  483.  
  484.     RemoveGadget (windowp, gadgetp);
  485.  
  486.     requesterp = 
  487.       (gadgetp->GadgetType & GTYP_REQGADGET) ?
  488.         current_requesterp :
  489.           NULL;
  490.  
  491.     rport = (requesterp) ? 
  492.       requesterp->ReqLayer->rp :
  493.         windowp->RPort;
  494.  
  495.     save_apen = rport->FgPen;
  496.  
  497.     SetAPen (rport, (UBYTE) fill_pen);
  498.  
  499.     RectFill (rport, x1, y1, x2, y2);
  500.  
  501.     SetAPen (rport, (UBYTE) save_apen);
  502.  
  503.     AddGList (windowp, gadgetp, -1, 1, requesterp);
  504.     refresh_gadget (gadgetp, windowp);
  505.     }
  506. }
  507.  
  508.  
  509. struct Gadget *message_gadget__new (short length, short tcol, short trow)
  510. {
  511.     struct Gadget *mgadgetp;
  512.  
  513.     mgadgetp = gadget__new (length, tcol, trow);
  514.     mgadgetp->Flags = GFLG_GADGHNONE;
  515.     mgadgetp->Activation = NULL;
  516.     mgadgetp->GadgetRender = button_border__new (BUTTON_WIDTH (length),
  517.                          shadow_pen, shine_pen);
  518.     mgadgetp->GadgetText = NULL;
  519.     return mgadgetp;
  520. }
  521.  
  522. struct Gadget *labeled_radio_button__new 
  523.   (char *label, char *text, short tcol, short trow)
  524. {
  525.     short button_offset = strlen (label) + 2;
  526.     struct Gadget *gadgetp = radio_button__new (text, tcol + button_offset, 
  527.                         trow);
  528.     gadgetp->GadgetText->NextText = button_text__new (label);
  529.     gadgetp->GadgetText->NextText->LeftEdge -= BUTTON_SIDE_EDGE*2 + 
  530.       strlen (label) * Font_Width;
  531.  
  532.     return gadgetp;
  533. }
  534.  
  535. struct Gadget *radio_button__new (char *text, short tcol, short trow)
  536. {
  537.     struct Gadget *gadgetp;
  538.  
  539.     gadgetp = text_button__new (text, tcol, trow);
  540.  
  541.     gadgetp->SelectRender = button_border__new (BUTTON_WIDTH(strlen (text)),
  542.                                                 shadow_pen, shine_pen);
  543.     gadgetp->Flags = GFLG_GADGHIMAGE;
  544.     gadgetp->Activation &= ~GACT_RELVERIFY;
  545.     gadgetp->Activation &= ~TOGGLESELECT;
  546.     gadgetp->Activation |= GADGIMMEDIATE;
  547.     return gadgetp;
  548. }
  549.  
  550. struct Gadget *tall_action_button__new (char *text, short tcol, short trow)
  551. {
  552.     struct Gadget *gadgetp;
  553.     struct Border *borderp;
  554.  
  555.     gadgetp = action_button__new (text, tcol, trow);
  556.  
  557. /*
  558.  * Add extra borders to make button appear taller
  559.  */
  560.     if (screen_depth > 1)
  561.     {
  562.     borderp = (struct Border *) gadgetp->GadgetRender;
  563.     borderp->NextBorder->NextBorder = button_border__new 
  564.       (BUTTON_WIDTH(strlen (text)), shine_pen, 
  565.        shadow_pen);
  566.     
  567.     borderp = borderp->NextBorder->NextBorder;
  568.     borderp->XY[1] += 1;
  569. #if FALSE
  570.     borderp->XY[0] += 1;
  571.     borderp->XY[2] += 1;
  572.     borderp->XY[3] += 1;
  573.     borderp->XY[4] += -1;
  574.     borderp->XY[5] += 1;
  575. #endif    
  576.  
  577.     borderp = borderp->NextBorder;
  578.     borderp->XY[0] += 0;
  579.     borderp->XY[1] += 1;
  580.     borderp->XY[2] += 1;
  581.     borderp->XY[3] += 1;
  582.     borderp->XY[4] += 1;
  583.     borderp->XY[5] += 1;
  584.     
  585.     borderp = (struct Border *) gadgetp->SelectRender;
  586.     borderp->NextBorder->NextBorder = button_border__new 
  587.       (BUTTON_WIDTH(strlen (text)), shadow_pen, 
  588.        shine_pen);
  589.     
  590.     borderp = borderp->NextBorder->NextBorder;
  591.     borderp->XY[1] += 1;
  592. #if FALSE
  593.     borderp->XY[0] += 1;
  594.     borderp->XY[2] += 1;
  595.     borderp->XY[3] += 1;
  596.     borderp->XY[4] += -1;
  597.     borderp->XY[5] += 1;
  598. #endif
  599.     
  600.     borderp = borderp->NextBorder;
  601.     borderp->XY[0] += 0;
  602.     borderp->XY[1] += 1;
  603.     borderp->XY[2] += 1;
  604.     borderp->XY[3] += 1;
  605.     borderp->XY[4] += 1;
  606.     borderp->XY[5] += 1;
  607.  
  608.     }
  609.     return gadgetp;
  610. }
  611.     
  612.  
  613.  
  614. struct Gadget *action_button__new (char *text, short tcol, short trow)
  615. {
  616.     struct Gadget *gadgetp;
  617.  
  618.     gadgetp = text_button__new (text, tcol, trow);
  619.     if (screen_depth > 1)
  620.     {
  621.     gadgetp->SelectRender = button_border__new 
  622.       (BUTTON_WIDTH(strlen (text)), shadow_pen, shine_pen);
  623.     gadgetp->Flags = GFLG_GADGHIMAGE;
  624.     }
  625.     return gadgetp;
  626. }
  627.  
  628. static struct Gadget *text_button__new (char *text, short tcol, short trow)
  629. {
  630.     struct Gadget *gadgetp;
  631.  
  632.     gadgetp = gadget__new (strlen (text), tcol, trow);
  633.     gadgetp->GadgetText = button_text__new (text);
  634.     return gadgetp;
  635. }
  636.  
  637. struct Gadget *gadget__new (short length, short tcol, short trow)
  638. {
  639.     struct Gadget *gadgetp;
  640.     short local_max_column = length + tcol;
  641.  
  642.     if (local_max_column > Max_Columns) Max_Columns = local_max_column;
  643.     if (trow + 1 > max_rows) max_rows = trow + 1;
  644.  
  645.     gadgetp = gcalloc (1, sizeof (struct Gadget), NOTHING_SPECIAL);
  646.  
  647.     gadgetp->NextGadget = next_gadgetp;
  648.     next_gadgetp = gadgetp;
  649.  
  650.     gadgetp->LeftEdge = first_button_left + tcol * Font_Width;
  651.     gadgetp->TopEdge = first_button_top + trow * BUTTON_SPACING;
  652.     gadgetp->Width = BUTTON_WIDTH (length);
  653.     gadgetp->Height = BUTTON_HEIGHT;
  654.     gadgetp->Activation = GACT_RELVERIFY;
  655.     gadgetp->GadgetType = GTYP_BOOLGADGET | gadget_type_mode;
  656.     gadgetp->GadgetRender = button_border__new (BUTTON_WIDTH (length),
  657.                         shine_pen, shadow_pen);
  658.     gadgetp->SelectRender = NULL;
  659.     gadgetp->Flags = GFLG_GADGHCOMP;
  660.     gadgetp->GadgetText = NULL;
  661.     gadgetp->MutualExclude = NULL;
  662.     gadgetp->SpecialInfo = NULL;
  663.     gadgetp->GadgetID = NULL;
  664.     gadgetp->UserData = NULL;
  665.     return gadgetp;
  666. }
  667.  
  668.  
  669. struct StringInfo *string_info__new (short max_chars, short vis_chars)
  670. {
  671.     struct StringInfo *string_info;
  672.  
  673.     string_info = gcalloc (1, sizeof (struct StringInfo), NOTHING_SPECIAL);
  674.  
  675.     string_info->Buffer = gcalloc (1, max_chars+1, NOTHING_SPECIAL);
  676.     string_info->MaxChars = max_chars+1;
  677.     string_info->UndoBuffer = NULL;
  678.     string_info->BufferPos = 0;
  679.     string_info->DispPos = 0;
  680.     string_info->CTop = BUTTON_TOP_EDGE;
  681.     string_info->CLeft = BUTTON_SIDE_EDGE;
  682.     string_info->DispCount = vis_chars;
  683.  
  684.  
  685.     if (fontp)
  686.     {
  687.     struct StringExtend *string_extendp = 
  688.       gcalloc (1, sizeof (struct StringExtend), NOTHING_SPECIAL);
  689.  
  690.     string_extendp->Font = fontp;
  691.     string_extendp->Pens[0] = text_pen;
  692.     string_extendp->Pens[1] = background_pen;
  693.     string_extendp->ActivePens[0] = text_pen;
  694.     string_extendp->ActivePens[1] = background_pen;
  695.  
  696.     string_info->Extension = string_extendp;
  697.     
  698.     }
  699.  
  700.     return string_info;
  701. }
  702.  
  703.  
  704. struct Gadget *string_gadget__new (char *prompt, char *initial_name,
  705.                       short max_chars, 
  706.                       short length, short tcol, 
  707.                       short trow)
  708. {
  709.     struct Gadget *string_gadgetp;
  710.     struct Border *borderp;
  711.     struct Border *bottomp;
  712.     short *bottom_xy;
  713.     short right_text_offset, right_border_offset;
  714.     short container_length, container_tcol;
  715.     
  716. /*
  717.  * (Damn! Intuition doesn't allow user offset for string gadget container
  718.  *  offsets within overall gadget area, so must do it manually.)
  719.  */
  720.     container_length = length - (strlen (prompt) + 2);
  721.     container_tcol = tcol + (strlen (prompt) + 2);
  722.  
  723.     string_gadgetp = gadget__new (container_length, container_tcol, trow);
  724.  
  725.     string_gadgetp->GadgetType = GTYP_STRGADGET | gadget_type_mode;
  726.     string_gadgetp->Activation |= GADGIMMEDIATE;
  727.  
  728.     if (fontp) string_gadgetp->Flags |= GFLG_STRINGEXTEND;
  729.  
  730.     string_gadgetp->SpecialInfo = string_info__new (max_chars, length-4);
  731.  
  732.     string_gadgetp->GadgetText = button_text__new (prompt);
  733.  
  734.     right_border_offset = BUTTON_SIDE_EDGE;
  735.     right_text_offset = BUTTON_SIDE_EDGE*2 + strlen (prompt) * 
  736.       Font_Width + right_border_offset;
  737.  
  738.     string_gadgetp->GadgetText->LeftEdge -= right_text_offset;
  739.  
  740.     string_gadgetp->LeftEdge += right_border_offset;
  741.     borderp = (struct Border *) string_gadgetp->GadgetRender;
  742.     borderp->XY[0] -= right_border_offset;
  743.     borderp->XY[2] -= right_border_offset;
  744.     borderp->XY[4] -= right_border_offset;
  745.     borderp = borderp->NextBorder;
  746.     borderp->XY[0] -= right_border_offset;
  747.     borderp->XY[2] -= right_border_offset;
  748.     borderp->XY[4] -= right_border_offset;
  749.     string_gadgetp->Width -= right_border_offset + BUTTON_SIDE_EDGE;
  750.  
  751.     string_gadgetp->TopEdge += BUTTON_TOP_EDGE;
  752.     string_gadgetp->GadgetText->TopEdge -= BUTTON_TOP_EDGE;
  753.     borderp = (struct Border *) string_gadgetp->GadgetRender;
  754.     borderp->XY[1] -= BUTTON_TOP_EDGE;
  755.     borderp->XY[3] -= BUTTON_TOP_EDGE;
  756.     borderp->XY[5] -= BUTTON_TOP_EDGE;
  757.     borderp = borderp->NextBorder;
  758.     borderp->XY[1] -= BUTTON_TOP_EDGE;
  759.     borderp->XY[3] -= BUTTON_TOP_EDGE;
  760.     borderp->XY[5] -= BUTTON_TOP_EDGE;
  761.     string_gadgetp->Height -= BUTTON_TOP_EDGE * 2;
  762. /*
  763.  * Add "bottom line"
  764.  */
  765.     bottomp = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL);
  766.     bottom_xy = gcalloc (4, sizeof (short), NOTHING_SPECIAL);
  767.  
  768.     bottom_xy[0] = 0;
  769.     bottom_xy[1] = Font_Height;
  770.     bottom_xy[2] = container_length * Font_Width;
  771.     bottom_xy[3] = Font_Height;
  772.     
  773.     bottomp->LeftEdge = 0;
  774.     bottomp->TopEdge = 0;
  775.     bottomp->XY = bottom_xy;
  776.     bottomp->FrontPen = shadow_pen;
  777.     bottomp->DrawMode = JAM1;
  778.     bottomp->NextBorder = NULL;
  779.     bottomp->Count = 2;
  780.  
  781.     borderp->NextBorder = bottomp;
  782.  
  783.     if (initial_name)
  784.     {
  785.     struct StringInfo *string_info = string_gadgetp->SpecialInfo;
  786.     strcpy (string_info->Buffer, initial_name);
  787.     }
  788.  
  789.     return string_gadgetp;
  790. }
  791.  
  792.  
  793. struct IntuiText *requester_text__new (char *text, short tcol, short trow)
  794. {
  795.     struct IntuiText *textst;
  796.     short local_max_column = tcol + strlen (text);
  797.  
  798.     if (local_max_column > Max_Columns) Max_Columns = local_max_column;
  799.     if (trow + 1 > max_rows) max_rows = trow + 1;
  800.  
  801.     textst = button_text__new (text);
  802.     textst->LeftEdge = first_button_left + BUTTON_SIDE_EDGE + 
  803.       tcol * Font_Width;
  804.     textst->TopEdge = BUTTON_TOP_EDGE + BUTTON_TOP(trow);
  805.     textst->NextText = next_textp;
  806.     next_textp = textst;
  807.  
  808.     return textst;
  809. }
  810.  
  811. struct IntuiText *button_text__new (char *text)
  812. {
  813.     struct IntuiText *textst;
  814.  
  815.     textst = gcalloc (1, sizeof (struct IntuiText), NOTHING_SPECIAL);
  816.  
  817.     textst->FrontPen = text_pen;
  818.     textst->BackPen = background_pen;
  819.     textst->DrawMode = JAM1;
  820.     textst->LeftEdge = BUTTON_SIDE_EDGE;
  821.     textst->TopEdge = BUTTON_TOP_EDGE;
  822.     textst->ITextFont = FontAp;
  823. /*  textst->ITextFont = NULL; This gives screen font, may be prop font */
  824.     textst->IText = text;
  825.     textst->NextText = NULL;
  826.     return textst;
  827. }
  828.  
  829. void refresh_gadget (struct Gadget *gadgetp, struct Window *windowp)
  830. {
  831.     struct Requester *requesterp = 
  832.       (gadgetp->GadgetType & GTYP_REQGADGET) ?
  833.     current_requesterp :
  834.       NULL;
  835.  
  836.     RefreshGList (gadgetp, windowp, requesterp, 1);
  837. }
  838.  
  839. void toggle_button__toggle (struct Gadget *gadgetp, 
  840.              char *(*on_function)(char *arg),
  841.              char *(*off_function)(char *arg),
  842.              struct Window *windowp)
  843. {
  844.     if (!(gadgetp->Flags & GFLG_SELECTED))
  845.     {
  846.     (*off_function) (NullString);
  847.     }
  848.     else
  849.     {
  850.     (*on_function) (NullString);
  851.     }
  852. }
  853.  
  854. void radio_button__toggle (struct Gadget *gadgetp, 
  855.              char *(*on_function)(char *arg),
  856.              char *(*off_function)(char *arg),
  857.              struct Window *windowp)
  858. {
  859. /*
  860.  * Must do imagery here for radio buttons
  861.  */
  862.     if (gadgetp->Flags & GFLG_SELECTED)
  863.     {
  864.     (*off_function) (NullString);
  865.     radio_button__out (gadgetp, windowp);
  866.     }
  867.     else
  868.     {
  869.     (*on_function) (NullString);
  870.     radio_button__in (gadgetp, windowp);
  871.     }
  872. }
  873.  
  874. char *string_gadget__apply (struct Gadget *string_gadgetp,
  875.                 char *(*apply_function)(char *arg))
  876. {
  877.     struct StringInfo *string_infop = 
  878.       string_gadgetp->SpecialInfo;
  879.     char *buffer = string_infop->Buffer;
  880.     buffer[string_infop->NumChars] = '\0';
  881.     (*apply_function) (buffer);
  882.     return buffer;
  883. }
  884.  
  885. /*
  886.  * (1.04) Names in requesters may include spaces, so
  887.  * must be quoted
  888.  */
  889. char *name_string_gadget__apply (struct Gadget *string_gadgetp,
  890.                  char *(*apply_function)(char *arg))
  891. {
  892.     char *enquote_buffer;
  893.     struct StringInfo *string_infop = 
  894.       string_gadgetp->SpecialInfo;
  895.     char *buffer = string_infop->Buffer;
  896.     buffer[string_infop->NumChars] = '\0';
  897.  
  898.     if (!string_infop->NumChars)
  899.     {
  900.     (*apply_function) (buffer);  /* Null String; don't enquote */
  901.     }
  902.     else
  903.     {
  904.     enquote_buffer = gmalloc (string_infop->NumChars + 8, 
  905.                   NOTHING_SPECIAL);
  906.     sprintf (enquote_buffer, "\"%s\"", buffer);
  907.     (*apply_function) (enquote_buffer);
  908.     gfree (enquote_buffer);
  909.     }
  910.     return buffer;
  911. }
  912.  
  913. void string_gadget__reset (struct Gadget *string_gadgetp,
  914.                 char *new_string,
  915.                 struct Window *windowp)
  916. {
  917.     struct StringInfo *string_infop = 
  918.       string_gadgetp->SpecialInfo;
  919.     char *buffer = string_infop->Buffer;
  920.     int string_length = 0;
  921.     if (!new_string || (string_length = strlen (new_string)) <= 0)
  922.     {
  923.     buffer[0] = '\0';
  924.     }
  925.     else
  926.     {
  927.     strcpy (buffer, new_string);
  928.     }
  929.     string_infop->NumChars = string_length;
  930.     refresh_gadget (string_gadgetp, windowp);
  931. }
  932.  
  933.  
  934. void message_requester (struct Window *windowp, char *message_text)
  935. {
  936.     extern char *Got_It_S;
  937.     struct IntuiText *mtextp = button_text__new (message_text);
  938.     struct IntuiText *got_it_textp = button_text__new (Got_It_S);
  939.  
  940.     if (Old_Intuition)
  941.     {
  942.     mtextp->DrawMode = JAM2 | INVERSVID;
  943.     got_it_textp->DrawMode = JAM2 | INVERSVID;
  944.     }
  945.  
  946.     AutoRequest (windowp, mtextp, NULL, got_it_textp,
  947.              IDCMP_GADGETDOWN,
  948.              IDCMP_GADGETDOWN, 640, 50);
  949.  
  950.     gfree (mtextp);
  951.     gfree (got_it_textp);
  952. }
  953.  
  954. /*
  955.  * I have decided NOT to follow the guidelines for 'mutually exclusive'
  956.  * gadgets on page 140 of the Amiga Rom Kernel Reference Manual, Third
  957.  * Edition, which specifically advise against this combination (mutually
  958.  * exclusive gadgets using 'complementing'--though I don't really use
  959.  * 'complementing' here anymore--I use explicit colors to be compatible with
  960.  * larger numbers of colors).
  961.  *
  962.  * However, I have chosen instead to follow the guidelines for 'Updating
  963.  * a Gadget's Imagery' on pages 129-130.  Before a radio_button is
  964.  * refreshed in either selected or unselected state, the background
  965.  * behind it is restored ("cleared") with RectFill.  I do this very
  966.  * carefully as you will see.
  967.  *
  968.  * This concept has been extended to cover other features, such as
  969.  * gadget disable and enable, which I couldn't get to work before.
  970.  *
  971.  * This should be acceptable and stable with future released of Intuition.
  972.  * At least, there is some hope.  And it works with 1.2-2.1 for sure.
  973.  *
  974.  * It now even handles requester gadgets properly.
  975.  */
  976.  
  977. void radio_button__in (struct Gadget *gadgetp, struct Window *windowp)
  978. {
  979.     struct RastPort *rport;
  980.     short x1, y1, x2, y2;
  981.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  982.     struct Requester *requesterp = 
  983.       (gadgetp->GadgetType & GTYP_REQGADGET) ?
  984.     current_requesterp :
  985.       NULL;
  986.  
  987.     if (windowp)
  988.     {
  989. /*    if (!(gadgetp->Flags & GFLG_SELECTED)) /* pushing my luck too far*/
  990.     {
  991.         RemoveGadget (windowp, gadgetp); 
  992.         gadgetp->Flags |= GFLG_SELECTED;
  993.         gadgetp->GadgetText->FrontPen = fill_text_pen;
  994.         gadgetp->GadgetText->BackPen = fill_pen;
  995.  
  996.         rport = (requesterp) ? 
  997.           requesterp->ReqLayer->rp :
  998.         windowp->RPort;
  999.  
  1000.         save_apen = rport->FgPen;
  1001.  
  1002.         SetAPen (rport, (UBYTE) fill_pen);
  1003.         SetDrMd (rport, JAM1);
  1004.         SetAfPt (rport, NULL, 0);
  1005.         SetWrMsk (rport, (UBYTE) 0xff);
  1006.         BNDRYOFF (rport);
  1007.         x1 = gadgetp->LeftEdge;
  1008.         y1 = gadgetp->TopEdge;
  1009.         x2 = x1 + gadgetp->Width - 1;
  1010.         y2 = y1 + gadgetp->Height - 1;
  1011.         
  1012.         RectFill (rport, x1, y1, x2, y2);
  1013.         
  1014.         SetAPen (rport, (UBYTE) save_apen);
  1015.         
  1016.         AddGList (windowp, gadgetp, -1, 1, requesterp);
  1017.         refresh_gadget (gadgetp, windowp);
  1018.     }
  1019.     }
  1020.     else  /* if (!windowp) */
  1021.     {
  1022.     gadgetp->Flags |= GFLG_SELECTED;
  1023.     }
  1024. }
  1025.     
  1026. void radio_button__out (struct Gadget *gadgetp, struct Window *windowp)
  1027. {
  1028.     struct RastPort *rport;
  1029.     short x1, y1, x2, y2;
  1030.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  1031.     struct Requester *requesterp = 
  1032.       (gadgetp->GadgetType & GTYP_REQGADGET) ?
  1033.     current_requesterp :
  1034.       NULL;
  1035.  
  1036.     if (windowp)
  1037.     {
  1038.     if (gadgetp->Flags & GFLG_SELECTED)
  1039.     {
  1040.         RemoveGadget (windowp, gadgetp);
  1041.         gadgetp->Flags &= ~GFLG_SELECTED;
  1042.         gadgetp->GadgetText->FrontPen = text_pen;
  1043.         gadgetp->GadgetText->BackPen = background_pen;
  1044.  
  1045.         rport = (requesterp) ? 
  1046.           requesterp->ReqLayer->rp :
  1047.         windowp->RPort;
  1048.  
  1049.         save_apen = rport->FgPen;
  1050.  
  1051.         SetAPen (rport, (UBYTE) background_pen);
  1052.         SetDrMd (rport, JAM1);
  1053.         SetAfPt (rport, NULL, 0);
  1054.         SetWrMsk (rport, (UBYTE) 0xff);
  1055.         BNDRYOFF (rport);
  1056.         x1 = gadgetp->LeftEdge;
  1057.         y1 = gadgetp->TopEdge;
  1058.         x2 = x1 + gadgetp->Width - 1;
  1059.         y2 = y1 + gadgetp->Height - 1;
  1060.  
  1061.         RectFill (rport, x1, y1, x2, y2);
  1062.  
  1063.         SetAPen (rport, (UBYTE) save_apen);
  1064.  
  1065.         AddGList (windowp, gadgetp, -1, 1, requesterp);
  1066.         refresh_gadget (gadgetp, windowp);
  1067.     }
  1068.     }
  1069.     else /* if (!windowp) */
  1070.     {
  1071.     gadgetp->Flags &= ~GFLG_SELECTED;
  1072.     }
  1073. }
  1074.  
  1075. void gadget__disable (struct Gadget *gadgetp, struct Window *windowp)
  1076. {
  1077.     struct RastPort *rport;
  1078.     short x1, y1, x2, y2;
  1079.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  1080.     struct Requester *requesterp = 
  1081.       (gadgetp->GadgetType & GTYP_REQGADGET) ?
  1082.     current_requesterp :
  1083.       NULL;
  1084.  
  1085.     if (gadgetp->Flags & GFLG_DISABLED) return;
  1086.  
  1087.     if (!windowp)
  1088.     {
  1089.     gadgetp->Flags |= GFLG_DISABLED;
  1090.     return;
  1091.     }
  1092.  
  1093.     RemoveGadget (windowp, gadgetp);
  1094.     gadgetp->Flags |= GFLG_DISABLED;
  1095.  
  1096.     rport = (requesterp) ? 
  1097.       requesterp->ReqLayer->rp :
  1098.     windowp->RPort;
  1099.  
  1100.     save_apen = rport->FgPen;
  1101.  
  1102.     if (gadgetp->Flags & GFLG_SELECTED)
  1103.     {
  1104.     SetAPen (rport, (UBYTE) fill_pen);
  1105.     }
  1106.     else
  1107.     {
  1108.     SetAPen (rport, (UBYTE) background_pen);
  1109.     }
  1110.     SetDrMd (rport, JAM1);
  1111.     SetAfPt (rport, NULL, 0);
  1112.     SetWrMsk (rport, (UBYTE) 0xff);
  1113.     BNDRYOFF (rport);
  1114.     x1 = gadgetp->LeftEdge;
  1115.     y1 = gadgetp->TopEdge;
  1116.     x2 = x1 + gadgetp->Width - 1;
  1117.     y2 = y1 + gadgetp->Height - 1;
  1118.     
  1119.     RectFill (rport, x1, y1, x2, y2);
  1120.     
  1121.     SetAPen (rport, (UBYTE) save_apen);
  1122.  
  1123.     AddGList (windowp, gadgetp, -1, 1, requesterp);
  1124.     refresh_gadget (gadgetp, windowp);
  1125. }
  1126.  
  1127. void gadget__enable (struct Gadget *gadgetp, struct Window *windowp)
  1128. {
  1129.     struct RastPort *rport;
  1130.     short x1, y1, x2, y2;
  1131.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  1132.     struct Requester *requesterp = 
  1133.       (gadgetp->GadgetType & GTYP_REQGADGET) ?
  1134.     current_requesterp :
  1135.       NULL;
  1136.  
  1137.     if (!(gadgetp->Flags & GFLG_DISABLED)) return;
  1138.  
  1139.     if (!windowp)
  1140.     {
  1141.     gadgetp->Flags |= GFLG_DISABLED;
  1142.     return;
  1143.     }
  1144.  
  1145. /* Yes, of course, OnGadget isn't smart enough for border gadgets */
  1146.  
  1147.     RemoveGadget (windowp, gadgetp);
  1148.     gadgetp->Flags &= ~GFLG_DISABLED;
  1149.  
  1150.     rport = (requesterp) ? 
  1151.       requesterp->ReqLayer->rp :
  1152.     windowp->RPort;
  1153.  
  1154.     save_apen = rport->FgPen;
  1155.  
  1156.     if (gadgetp->Flags & GFLG_SELECTED)
  1157.     {
  1158.     SetAPen (rport, (UBYTE) fill_pen);
  1159.     }
  1160.     else
  1161.     {
  1162.     SetAPen (rport, (UBYTE) background_pen);
  1163.     }
  1164.     SetDrMd (rport, JAM1);
  1165.     SetAfPt (rport, NULL, 0);
  1166.     SetWrMsk (rport, (UBYTE) 0xff);
  1167.     BNDRYOFF (rport);
  1168.     x1 = gadgetp->LeftEdge;
  1169.     y1 = gadgetp->TopEdge;
  1170.     x2 = x1 + gadgetp->Width - 1;
  1171.     y2 = y1 + gadgetp->Height - 1;
  1172.     
  1173.     RectFill (rport, x1, y1, x2, y2);
  1174.     
  1175.     SetAPen (rport, (UBYTE) save_apen);
  1176.  
  1177.     AddGList (windowp, gadgetp, -1, 1, requesterp);
  1178.     refresh_gadget (gadgetp, windowp);
  1179. }
  1180.  
  1181.  
  1182. void message_gadget__write (struct Gadget *gadgetp, char *message, struct
  1183.                 Window *windowp)
  1184. {
  1185.     struct RastPort *rport;
  1186.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  1187.     struct Requester *requesterp = 
  1188.       (gadgetp->GadgetType & GTYP_REQGADGET) ?
  1189.     current_requesterp :
  1190.       NULL;
  1191.  
  1192.     if (windowp) RemoveGadget (windowp, gadgetp);
  1193.  
  1194.     if (gadgetp->GadgetText) gfree (gadgetp->GadgetText);
  1195.     if (!message || !strlen(message))
  1196.     {
  1197.     gadgetp->GadgetText = NULL;
  1198.     }
  1199.     else
  1200.     {
  1201.     gadgetp->GadgetText = button_text__new (message);
  1202.     }
  1203.  
  1204.     /*  gadgetp->GadgetText->FrontPen = fill_text_pen; */
  1205.  
  1206.     if (windowp)
  1207.     {
  1208.     short x1, y1, x2, y2;
  1209.  
  1210.     x1 = gadgetp->LeftEdge;
  1211.     y1 = gadgetp->TopEdge;
  1212.     x2 = x1 + gadgetp->Width - 1;
  1213.     y2 = y1 + gadgetp->Height - 1;
  1214.  
  1215.     rport = (requesterp) ? 
  1216.       requesterp->ReqLayer->rp :
  1217.         windowp->RPort;
  1218.  
  1219.     save_apen = rport->FgPen;
  1220.  
  1221.     SetAPen (rport, (UBYTE) background_pen);
  1222.  
  1223.     RectFill (rport, x1, y1, x2, y2);
  1224.  
  1225.     SetAPen (rport, (UBYTE) save_apen);
  1226.  
  1227.     AddGList (windowp, gadgetp, -1, 1, requesterp);
  1228.     refresh_gadget (gadgetp, windowp);
  1229.     }
  1230. }
  1231.  
  1232. struct Window *window__new (char *title)
  1233. {
  1234.     struct NewWindow new_window; /* parameter structure to create window */
  1235.     struct Window *windowp = NULL;
  1236.     short height = WINDOW_HEIGHT (max_rows);
  1237.  
  1238.     short width = (Max_Columns * Font_Width) + 
  1239.       (2 * (FIRST_WINDOW_BUTTON_LEFT + BUTTON_SIDE_EDGE));
  1240.  
  1241.     if (Shell_Height < height) Shell_Height = height;
  1242.     if (Shell_Width < width) Shell_Width = width;
  1243.  
  1244.     new_window.LeftEdge = WINDOW_LEFT;
  1245.     new_window.TopEdge = WINDOW_TOP;
  1246.     new_window.Height = height;
  1247.     new_window.Width = width;
  1248.       new_window.DetailPen = 0;
  1249.     new_window.BlockPen = 1;
  1250.     new_window.Title = title;
  1251.     new_window.Flags = SMART_REFRESH | ACTIVATE | WINDOWCLOSE | 
  1252.       WINDOWDRAG | WINDOWDEPTH | NOCAREREFRESH;
  1253.     new_window.IDCMPFlags = IDCMP_CLOSEWINDOW | IDCMP_GADGETUP |
  1254.       IDCMP_GADGETDOWN | IDCMP_RAWKEY;
  1255.     if (Old_Intuition)
  1256.     {
  1257.     new_window.Type = WBENCHSCREEN;
  1258.     }
  1259.     else
  1260.     {
  1261.     new_window.Type = PUBLICSCREEN;  /* It's the latest thing */
  1262.     }
  1263.     new_window.FirstGadget = next_gadgetp;
  1264.     new_window.Screen = NULL;
  1265.     new_window.BitMap = NULL;
  1266.     new_window.MinWidth = 0;
  1267.     new_window.MinHeight = 0;
  1268.     new_window.MaxWidth = 0;
  1269.     new_window.MaxHeight = 0;
  1270.     
  1271. /* Try to open the window.  Like the call to OpenLibrary(), if
  1272.  * the OpenWindow call is successful, it returns a pointer to
  1273.  * the structure for your new window.  If the OpenWindow() call
  1274.  * fails, it returns a zero.
  1275.  */
  1276.     if ((windowp = (struct Window *) OpenWindow (&new_window)) == NULL )
  1277.     {
  1278.     error_message (WINDOW_OPEN_FAILED);
  1279.     gabort (EXIT_FAILURE);
  1280.     }
  1281.     return windowp;
  1282. }
  1283.  
  1284. struct Requester *requester__new (void)
  1285. {
  1286.     struct Requester *requesterp;
  1287.     short height = (max_rows * (Font_Height + (2 * BUTTON_TOP_EDGE)))
  1288.                      + ((max_rows - 1) * BUTTON_TOP_SPACE) +
  1289.              + (2 * FIRST_REQUESTER_BUTTON_TOP);
  1290.     short width = (Max_Columns * Font_Width) + 
  1291.       (2 * (FIRST_REQUESTER_BUTTON_LEFT + BUTTON_SIDE_EDGE));
  1292.  
  1293.     requesterp = gmalloc (sizeof (struct Requester), NOTHING_SPECIAL);
  1294.     InitRequester (requesterp);
  1295.     requesterp->BackFill = background_pen;
  1296.     requesterp->ReqBorder = requester_border__new (height, width, shine_pen,
  1297.                            shadow_pen);
  1298.     requesterp->Width = width;
  1299.     requesterp->Height = height;
  1300.     requesterp->RelLeft = 0;
  1301.     requesterp->RelTop = 0;
  1302.     requesterp->Flags = POINTREL;
  1303.     return requesterp;
  1304. }
  1305.  
  1306. BOOLEAN requester__display (struct Requester *rp, struct Window *wp)
  1307. {
  1308.     if (Request (rp, wp))
  1309.     {
  1310.     if (++requester_stack_index >= REQUESTER_STACK_DEPTH)
  1311.     {
  1312.         error_message (REQUESTER_STACK_OVERFLOW);
  1313.         EndRequest (rp, wp);
  1314.         return FALSE;
  1315.     }
  1316.     requester_stack[requester_stack_index] = current_requesterp;
  1317.     current_requesterp = rp;
  1318.     return TRUE;
  1319.     }
  1320.     return FALSE;
  1321. }
  1322.  
  1323. void requester__remove (struct Requester *rp, struct Window *wp)
  1324. {
  1325.     current_requesterp = requester_stack[requester_stack_index];
  1326.     if (requester_stack_index) requester_stack_index--;
  1327.  
  1328.     EndRequest (rp, wp);
  1329. }
  1330.  
  1331. BOOLEAN ignore_tooltype (char *tooltype)
  1332. {
  1333.     if (!strncmp (tooltype, "TOOLPRI", 7)) return TRUE;
  1334.     if (!strncmp (tooltype, "STARTPRI", 8)) return TRUE;
  1335.     if (!strncmp (tooltype, "DONOTWAIT", 9)) return TRUE;
  1336.     if (!strncmp (tooltype, "FILETYPE", 8)) return TRUE;
  1337.     if (!strncmp (tooltype, "DUMMY", 5)) return TRUE;
  1338.     return FALSE;
  1339. }
  1340.  
  1341.  
  1342. #endif  /* ifdef AMIGA */
  1343.  
  1344.