home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / misc / sci / gfft / source / wbtools.c < prev   
Encoding:
C/C++ Source or Header  |  1994-08-04  |  24.6 KB  |  892 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.  * Comments:    Workbench GUI.  Amiga Dependent!
  18.  *              There may be other toolkits.  Mine is intended to be
  19.  *              compatible with all releases of AmigaDOS.  It was
  20.  *              started when I only had the Version 1 RKM's, but has been
  21.  *              upgraded to correspond to the Version 3 RKM's.  It is
  22.  *              simple (I think, anyway).  The basic model is:
  23.  *              rows of 'text buttons.'  Possibly not visually
  24.  *              indulgent.
  25.  */
  26.  
  27. #ifdef AMIGA
  28.  
  29. #include <stdio.h>     /* sprintf() */
  30. #include <string.h>
  31. /*
  32.  * Amiga includes
  33.  */
  34. #include <exec/types.h>
  35. #include <exec/exec.h>
  36. #include <workbench/workbench.h>
  37. #include <workbench/icon.h>
  38. #include <workbench/startup.h>
  39. #include <intuition/intuition.h>
  40. #include <clib/intuition_protos.h>
  41. #include <clib/exec_protos.h>
  42. #include <proto/icon.h>
  43. #include <proto/dos.h>
  44. #include <dos/dos.h>
  45. #include <libraries/asl.h>
  46. #include <clib/asl_protos.h>
  47. #include <graphics/text.h>
  48. #include <clib/graphics_protos.h>
  49. #include <graphics/gfxmacros.h>  /* BNDRYOFF */
  50.  
  51. #include "gfft.h"
  52. #include "wbench.h"
  53.  
  54. /*
  55.  * Dialogue Window parameters...pretty good guesses for 2.0 and 1.3
  56.  * reset later if drawinfo is available
  57.  */
  58. #define SHINE_PEN_20 2
  59. #define SHADOW_PEN_20 1
  60. #define SHINE_PEN_13 1
  61. #define SHADOW_PEN_13 2
  62. #define TEXT_PEN 1          /* Seems to work well under both 2.0 and 1.3 */
  63. #define FILL_TEXT_PEN 2     /* ditto; hmmn, I like better than 2.0 default */
  64. #define BACKGROUND_PEN 0    /* almost guaranteed now, but may be updated */
  65.  
  66. #define FONT_SIZE 8
  67.  
  68. #define FIRST_WINDOW_BUTTON_LEFT 12
  69. #define FIRST_WINDOW_BUTTON_TOP 6
  70.  
  71. #define FIRST_REQUESTER_BUTTON_LEFT 10
  72. #define FIRST_REQUESTER_BUTTON_TOP 4
  73.  
  74. #define BUTTON_SIDE_EDGE 8
  75.  
  76. #define BUTTON_WIDTH(WIDTH) ((WIDTH) * FONT_SIZE + 2 * BUTTON_SIDE_EDGE)
  77.  
  78. #define BUTTON_TOP_EDGE 3    /* Inside button to text; same as bottom edge*/
  79. #define BUTTON_TOP_SPACE 2   /* Vertical space between buttons */
  80. #define BUTTON_HEIGHT (FONT_SIZE + 2 * BUTTON_TOP_EDGE)
  81.  
  82. struct TextAttr Font = {
  83. "topaz.font",
  84. FONT_SIZE,
  85. NULL,
  86. NULL
  87. };
  88.  
  89. static short shine_pen = SHINE_PEN_20;
  90. static short shadow_pen = SHADOW_PEN_20;
  91. static short text_pen = TEXT_PEN;
  92. static short fill_text_pen = FILL_TEXT_PEN;
  93. static short background_pen = BACKGROUND_PEN;
  94. short Screen_Font_Height = 8;  /* Guess, corrected later for 2.0+ */
  95.  
  96. static short first_button_left = FIRST_WINDOW_BUTTON_LEFT;
  97. static short first_button_top = FIRST_WINDOW_BUTTON_TOP + 8;
  98. static short max_rows = 0;
  99. static int gadget_mode_flag = NULL;
  100. static struct IntuiText *next_textp = NULL;
  101. static struct Gadget *next_gadgetp = NULL;
  102. static struct Requester *current_requesterp = NULL;
  103.  
  104. struct Library *IntuitionBase = NULL;
  105. BOOLEAN Old_Intuition = FALSE;
  106. short Max_Columns = 0;
  107.  
  108. extern struct Library *AslBase;   /* from filereq.c */
  109. extern struct FileRequester *File_Requesterp;
  110.  
  111. void open_libraries (void)
  112. {
  113.     struct Screen *screen;
  114.     struct DrawInfo *draw_info;
  115.  
  116.     if (!IntuitionBase)
  117.     {
  118. /*
  119.  * What the hey! SAS C automatically opens libraries for me
  120.  * if I don't define their globals.  It automagically closes them too!
  121.  * This is OK unless I need to specify version, or provide for case
  122.  * (as with newer libraries) where the library may be unavailable.
  123.  */
  124.  
  125. /*    IconBase = OpenLibrary ("icon.library", 0); */
  126. /*    if (IconBase == NULL) gabort (EXIT_FAILURE); */
  127.  
  128.     IntuitionBase = OpenLibrary ("intuition.library", 37);
  129.     if (IntuitionBase == NULL) 
  130.     {
  131.         Old_Intuition = TRUE;
  132.         shine_pen = SHINE_PEN_13;  /* These usually work for 1.3... */
  133.         shadow_pen = SHADOW_PEN_13;  /* Should do this better someday */
  134.         IntuitionBase = OpenLibrary ("intuition.library", 0);
  135.         if (IntuitionBase == NULL)
  136.         {
  137.         error_message (CANT_OPEN_INTUITION);
  138.         gabort (EXIT_FAILURE);
  139.         }
  140.     }
  141.     else  /* Ok, Rev 37 or greater, get pens for default screen */
  142.     {
  143.         if (screen = LockPubScreen (NULL))
  144.         {
  145.         if (draw_info = GetScreenDrawInfo (screen))
  146.         {
  147.             shine_pen = draw_info->dri_Pens[SHINEPEN];
  148.             shadow_pen = draw_info->dri_Pens[SHADOWPEN];
  149.             text_pen = draw_info->dri_Pens[TEXTPEN];
  150. /*            fill_text_pen = draw_info->dri_Pens[FILLTEXTPEN]; */
  151.             background_pen = draw_info->dri_Pens[BACKGROUNDPEN];
  152.             Screen_Font_Height = 
  153.               draw_info->dri_Font->tf_YSize;
  154.             FreeScreenDrawInfo (screen, draw_info);
  155.         }
  156.         UnlockPubScreen (NULL, screen);
  157.         }
  158.     }
  159.     }
  160. }
  161.  
  162. void close_amiga_stuff (void)
  163. {
  164.     if (IntuitionBase)
  165.     {
  166.     CloseLibrary (IntuitionBase);
  167.     IntuitionBase = NULL;
  168.     }
  169.     if (File_Requesterp)
  170.     {
  171.     FreeAslRequest(File_Requesterp);
  172.     File_Requesterp = NULL;
  173.     }
  174.     if (AslBase)
  175.     {
  176.         CloseLibrary(AslBase);
  177.     AslBase = NULL;
  178.     }
  179. }
  180.  
  181.  
  182. struct Border *requester_border__new (short height, short width,
  183.                 short top_pen, short bottom_pen)
  184. {
  185.     struct Border *rborder;
  186.  
  187.     rborder = border__new (height-1, width-1, top_pen, bottom_pen);
  188.     return rborder;
  189. }
  190.  
  191.  
  192. struct Border *button_border__new (short width, short top_pen,
  193.                    short bottom_pen)
  194. {
  195.  
  196.     struct Border *bborder;
  197.  
  198.     bborder = border__new (BUTTON_HEIGHT-1, width-1, top_pen, bottom_pen);
  199.     return bborder;
  200. }
  201.  
  202.  
  203. struct Border *border__new (short height, short width, short top_pen,
  204.                 short bottom_pen)
  205. {
  206.     short *xy_pairs_u, *xy_pairs_l;
  207.     struct Border *border_u, *border_l;
  208.  
  209.     xy_pairs_u = gcalloc (6, sizeof (short), NOTHING_SPECIAL);
  210.     xy_pairs_l = gcalloc (6, sizeof (short), NOTHING_SPECIAL);
  211.     border_u = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL);
  212.     border_l = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL);
  213.  
  214.     xy_pairs_u[0] = 0;
  215.     xy_pairs_u[1] = height;
  216.     xy_pairs_u[2] = 0;
  217.     xy_pairs_u[3] = 0;
  218.     xy_pairs_u[4] = width;
  219.     xy_pairs_u[5] = 0;
  220.  
  221.     xy_pairs_l[0] = 0;
  222.     xy_pairs_l[1] = height;
  223.     xy_pairs_l[2] = width;
  224.     xy_pairs_l[3] = height;
  225.     xy_pairs_l[4] = width;
  226.     xy_pairs_l[5] = 0;
  227.  
  228.     border_u->LeftEdge = 0;
  229.     border_u->TopEdge = 0;
  230.     border_u->XY = xy_pairs_u;
  231.     border_u->FrontPen = top_pen;
  232.     border_u->DrawMode = JAM1;
  233.     border_u->NextBorder = border_l;
  234.     border_u->Count = 3;
  235.  
  236.     border_l->LeftEdge = 0;
  237.     border_l->TopEdge = 0;
  238.     border_l->XY = xy_pairs_l;
  239.     border_l->FrontPen = bottom_pen;
  240.     border_l->DrawMode = JAM1;
  241.     border_l->NextBorder = NULL;
  242.     border_l->Count = 3;
  243.  
  244.     return border_u;
  245. }
  246.     
  247.  
  248. struct Gadget *radio_button__new (char *text, short tcol, short trow)
  249. {
  250.     struct Gadget *gadgetp;
  251.  
  252.     gadgetp = toggle_button__new (text, tcol, trow);
  253.     gadgetp->Activation &= ~TOGGLESELECT;
  254.     return gadgetp;
  255. }
  256.  
  257. struct Gadget *toggle_button__new (char *text, short tcol, short trow)
  258. {
  259.     struct Gadget *gadgetp;
  260.  
  261.     gadgetp = text_button__new (text, tcol, trow);
  262.     gadgetp->Activation &= ~GACT_RELVERIFY;
  263.     gadgetp->Activation |= GADGIMMEDIATE;
  264.     gadgetp->Activation |= TOGGLESELECT;
  265.     return gadgetp;
  266. }
  267.  
  268.  
  269. struct Gadget *message_gadget__new (short length, short tcol, short trow)
  270. {
  271.     struct Gadget *mgadgetp;
  272.  
  273.     mgadgetp = gadget__new (length, tcol, trow);
  274.     mgadgetp->Flags = GFLG_GADGHNONE;
  275.     mgadgetp->Activation = NULL;
  276.     mgadgetp->GadgetRender = button_border__new (BUTTON_WIDTH (length),
  277.                          shadow_pen, shine_pen);
  278.     mgadgetp->GadgetText = NULL;
  279.     return mgadgetp;
  280. }
  281.  
  282. struct Gadget *text_button__new (char *text, short tcol, short trow)
  283. {
  284.     struct Gadget *gadgetp;
  285.  
  286.     gadgetp = gadget__new (strlen (text), tcol, trow);
  287.  
  288.     gadgetp->GadgetText = button_text__new (text);
  289.     return gadgetp;
  290. }
  291.  
  292. void gadget__begin (int gadget_flag)
  293. {
  294.     gadget_mode_flag = gadget_flag;
  295.     Max_Columns = 0;
  296.     max_rows = 0;
  297.     next_textp = NULL;
  298.     next_gadgetp = NULL;
  299.  
  300.     if (gadget_mode_flag == GTYP_REQGADGET)
  301.     {
  302.     first_button_left = FIRST_REQUESTER_BUTTON_LEFT;
  303.     first_button_top = FIRST_REQUESTER_BUTTON_TOP;
  304.     }
  305.     else
  306.     {
  307.     first_button_left = FIRST_WINDOW_BUTTON_LEFT;
  308.     first_button_top = FIRST_WINDOW_BUTTON_TOP + Screen_Font_Height;
  309.     }
  310. }
  311.  
  312. struct Gadget *gadget__new (short length, short tcol, short trow)
  313. {
  314.     struct Gadget *gadgetp;
  315.     short local_max_column = length + tcol;
  316.  
  317.     if (local_max_column > Max_Columns) Max_Columns = local_max_column;
  318.     if (trow + 1 > max_rows) max_rows = trow + 1;
  319.  
  320.     gadgetp = gcalloc (1, sizeof (struct Gadget), NOTHING_SPECIAL);
  321.  
  322.     gadgetp->NextGadget = next_gadgetp;
  323.     next_gadgetp = gadgetp;
  324.  
  325.     gadgetp->LeftEdge = first_button_left + tcol * FONT_SIZE;
  326.     gadgetp->TopEdge = first_button_top + trow * 
  327.       (2 * BUTTON_TOP_EDGE + BUTTON_TOP_SPACE + FONT_SIZE);
  328.     gadgetp->Width = BUTTON_WIDTH (length);
  329.     gadgetp->Height = FONT_SIZE + 2 * BUTTON_TOP_EDGE;
  330.     gadgetp->Activation = GACT_RELVERIFY;
  331.     gadgetp->GadgetType = GTYP_BOOLGADGET;
  332.     gadgetp->GadgetRender = button_border__new (BUTTON_WIDTH (length),
  333.                         shine_pen, shadow_pen);
  334. /*    gadgetp->SelectRender = button_border__new (BUTTON_WIDTH (length)
  335.  *                                                shadow_pen, shine_pen);
  336.  *    gadgetp->Flags = GADGHIMAGE;
  337.  */
  338.     gadgetp->Flags = GFLG_GADGHCOMP | gadget_mode_flag;
  339.     gadgetp->SelectRender = NULL;
  340.  
  341.     gadgetp->GadgetText = NULL;
  342.     gadgetp->MutualExclude = NULL;
  343.     gadgetp->SpecialInfo = NULL;
  344.     gadgetp->GadgetID = NULL;
  345.     gadgetp->UserData = NULL;
  346.     return gadgetp;
  347. }
  348.  
  349.  
  350. struct StringInfo *string_info__new (short max_chars, short vis_chars)
  351. {
  352.     struct StringInfo *string_info;
  353.  
  354.     string_info = gcalloc (1, sizeof (struct StringInfo), NOTHING_SPECIAL);
  355.  
  356.     string_info->Buffer = gcalloc (1, max_chars+1, NOTHING_SPECIAL);
  357.     string_info->MaxChars = max_chars+1;
  358.     string_info->UndoBuffer = NULL;
  359.     string_info->BufferPos = 0;
  360.     string_info->DispPos = 0;
  361.     string_info->CTop = BUTTON_TOP_EDGE;
  362.     string_info->CLeft = BUTTON_SIDE_EDGE;
  363.     string_info->DispCount = vis_chars;
  364.  
  365.     return string_info;
  366. }
  367.  
  368.  
  369. struct Gadget *string_gadget__new (char *prompt, char *initial_name,
  370.                       short max_chars, 
  371.                       short length, short tcol, 
  372.                       short trow)
  373. {
  374.     struct Gadget *string_gadgetp;
  375.     struct Border *borderp;
  376.     struct Border *bottomp;
  377.     short *bottom_xy;
  378.     short right_text_offset, right_border_offset;
  379.     short container_length, container_tcol;
  380.     
  381. /*
  382.  * (Damn! Intuition doesn't allow user offset for string gadget container
  383.  *  offsets within overall gadget area, so must do it manually.)
  384.  */
  385.     container_length = length - (strlen (prompt) + 2);
  386.     container_tcol = tcol + (strlen (prompt) + 2);
  387.  
  388.     string_gadgetp = gadget__new (container_length, container_tcol, trow);
  389.  
  390.     string_gadgetp->GadgetType = GTYP_STRGADGET;
  391.     string_gadgetp->Activation |= GADGIMMEDIATE;
  392.  
  393.     string_gadgetp->SpecialInfo = string_info__new (max_chars, length-4);
  394.  
  395.     string_gadgetp->GadgetText = button_text__new (prompt);
  396.  
  397.     right_border_offset = BUTTON_SIDE_EDGE;
  398.     right_text_offset = BUTTON_SIDE_EDGE*2 + strlen (prompt) * 
  399.       FONT_SIZE + right_border_offset;
  400.  
  401.     string_gadgetp->GadgetText->LeftEdge -= right_text_offset;
  402.  
  403.     string_gadgetp->LeftEdge += right_border_offset;
  404.     borderp = (struct Border *) string_gadgetp->GadgetRender;
  405.     borderp->XY[0] -= right_border_offset;
  406.     borderp->XY[2] -= right_border_offset;
  407.     borderp->XY[4] -= right_border_offset;
  408.     borderp = borderp->NextBorder;
  409.     borderp->XY[0] -= right_border_offset;
  410.     borderp->XY[2] -= right_border_offset;
  411.     borderp->XY[4] -= right_border_offset;
  412.     string_gadgetp->Width -= right_border_offset + BUTTON_SIDE_EDGE;
  413.  
  414.     string_gadgetp->TopEdge += BUTTON_TOP_EDGE;
  415.     string_gadgetp->GadgetText->TopEdge -= BUTTON_TOP_EDGE;
  416.     borderp = (struct Border *) string_gadgetp->GadgetRender;
  417.     borderp->XY[1] -= BUTTON_TOP_EDGE;
  418.     borderp->XY[3] -= BUTTON_TOP_EDGE;
  419.     borderp->XY[5] -= BUTTON_TOP_EDGE;
  420.     borderp = borderp->NextBorder;
  421.     borderp->XY[1] -= BUTTON_TOP_EDGE;
  422.     borderp->XY[3] -= BUTTON_TOP_EDGE;
  423.     borderp->XY[5] -= BUTTON_TOP_EDGE;
  424.     string_gadgetp->Height -= BUTTON_TOP_EDGE * 2;
  425. /*
  426.  * Add "bottom line"
  427.  */
  428.     bottomp = gcalloc (1, sizeof (struct Border), NOTHING_SPECIAL);
  429.     bottom_xy = gcalloc (4, sizeof (short), NOTHING_SPECIAL);
  430.  
  431.     bottom_xy[0] = 0;
  432.     bottom_xy[1] = FONT_SIZE;
  433.     bottom_xy[2] = container_length * FONT_SIZE;
  434.     bottom_xy[3] = FONT_SIZE;
  435.     
  436.     bottomp->LeftEdge = 0;
  437.     bottomp->TopEdge = 0;
  438.     bottomp->XY = bottom_xy;
  439.     bottomp->FrontPen = shadow_pen;
  440.     bottomp->DrawMode = JAM1;
  441.     bottomp->NextBorder = NULL;
  442.     bottomp->Count = 2;
  443.  
  444.     borderp->NextBorder = bottomp;
  445.  
  446.     if (initial_name)
  447.     {
  448.     struct StringInfo *string_info = string_gadgetp->SpecialInfo;
  449.     strcpy (string_info->Buffer, initial_name);
  450.     }
  451.  
  452.     return string_gadgetp;
  453. }
  454.  
  455.  
  456. struct IntuiText *requester_text__new (char *text, short tcol, short trow)
  457. {
  458.     struct IntuiText *textst;
  459.     short local_max_column = tcol + strlen (text);
  460.  
  461.     if (local_max_column > Max_Columns) Max_Columns = local_max_column;
  462.     if (trow + 1 > max_rows) max_rows = trow + 1;
  463.  
  464.     textst = button_text__new (text);
  465.     textst->LeftEdge = first_button_left + BUTTON_SIDE_EDGE + 
  466.       tcol * FONT_SIZE;
  467.     textst->TopEdge = first_button_top + BUTTON_TOP_EDGE + 
  468.       trow * (2 * BUTTON_TOP_EDGE + BUTTON_TOP_SPACE + FONT_SIZE);
  469.     textst->NextText = next_textp;
  470.     next_textp = textst;
  471.  
  472.     return textst;
  473. }
  474.  
  475. struct IntuiText *button_text__new (char *text)
  476. {
  477.     struct IntuiText *textst;
  478.  
  479.     textst = gcalloc (1, sizeof (struct IntuiText), NOTHING_SPECIAL);
  480.  
  481.     textst->FrontPen = TEXT_PEN;
  482.     textst->BackPen = BACKGROUND_PEN;
  483.     textst->DrawMode = JAM1;
  484.     textst->LeftEdge = BUTTON_SIDE_EDGE;
  485.     textst->TopEdge = BUTTON_TOP_EDGE;
  486.     textst->ITextFont = &Font;
  487.     textst->IText = text;
  488.     textst->NextText = NULL;
  489.     return textst;
  490. }
  491.  
  492. void refresh_gadget (struct Gadget *gadgetp, struct Window *windowp)
  493. {
  494.     RefreshGList (gadgetp, windowp, current_requesterp, 1);
  495. }
  496.  
  497. void toggle_button__toggle (struct Gadget *gadgetp, 
  498.              char *(*on_function)(char *arg),
  499.              char *(*off_function)(char *arg),
  500.              struct Window *windowp)
  501. {
  502.     if (!(gadgetp->Flags & SELECTED))
  503.     {
  504.     (*off_function) (NullString);
  505.     }
  506.     else
  507.     {
  508.     (*on_function) (NullString);
  509.     }
  510. }
  511.  
  512. void radio_button__toggle (struct Gadget *gadgetp, 
  513.              char *(*on_function)(char *arg),
  514.              char *(*off_function)(char *arg),
  515.              struct Window *windowp)
  516. {
  517. /*
  518.  * Must do imagery here for radio buttons
  519.  */
  520.     if (gadgetp->Flags & SELECTED)
  521.     {
  522.     (*off_function) (NullString);
  523.     radio_button__out (gadgetp, windowp);
  524.     }
  525.     else
  526.     {
  527.     (*on_function) (NullString);
  528.     radio_button__in (gadgetp, windowp);
  529.     }
  530. }
  531.  
  532. char *string_gadget__apply (struct Gadget *string_gadgetp,
  533.                 char *(*apply_function)(char *arg))
  534. {
  535.     struct StringInfo *string_infop = 
  536.       string_gadgetp->SpecialInfo;
  537.     char *buffer = string_infop->Buffer;
  538.     buffer[string_infop->NumChars] = '\0';
  539.     (*apply_function) (buffer);
  540.     return buffer;
  541. }
  542.  
  543. /*
  544.  * (1.04) Names in requesters may include spaces, so
  545.  * must be quoted
  546.  */
  547. char *name_string_gadget__apply (struct Gadget *string_gadgetp,
  548.                  char *(*apply_function)(char *arg))
  549. {
  550.     char *enquote_buffer;
  551.     struct StringInfo *string_infop = 
  552.       string_gadgetp->SpecialInfo;
  553.     char *buffer = string_infop->Buffer;
  554.     buffer[string_infop->NumChars] = '\0';
  555.  
  556.     if (!string_infop->NumChars)
  557.     {
  558.     (*apply_function) (buffer);  /* Null String; don't enquote */
  559.     }
  560.     else
  561.     {
  562.     enquote_buffer = gmalloc (string_infop->NumChars + 8, 
  563.                   NOTHING_SPECIAL);
  564.     sprintf (enquote_buffer, "\"%s\"", buffer);
  565.     (*apply_function) (enquote_buffer);
  566.     gfree (enquote_buffer);
  567.     }
  568.     return buffer;
  569. }
  570.  
  571. void string_gadget__reset (struct Gadget *string_gadgetp,
  572.                 char *new_string,
  573.                 struct Window *windowp)
  574. {
  575.     struct StringInfo *string_infop = 
  576.       string_gadgetp->SpecialInfo;
  577.     char *buffer = string_infop->Buffer;
  578.     int string_length = 0;
  579.     if (!new_string || (string_length = strlen (new_string)) <= 0)
  580.     {
  581.     buffer[0] = '\0';
  582.     }
  583.     else
  584.     {
  585.     strcpy (buffer, new_string);
  586.     }
  587.     string_infop->NumChars = string_length;
  588.     refresh_gadget (string_gadgetp, windowp);
  589. }
  590.  
  591.  
  592. void message_requester (struct Window *windowp, char *message_text)
  593. {
  594.     extern char *Got_It_S;
  595.     struct IntuiText *mtextp = button_text__new (message_text);
  596.     struct IntuiText *got_it_textp = button_text__new (Got_It_S);
  597.  
  598.     if (Old_Intuition)
  599.     {
  600.     mtextp->DrawMode = JAM2 | INVERSVID;
  601.     got_it_textp->DrawMode = JAM2 | INVERSVID;
  602.     }
  603.  
  604.     AutoRequest (windowp, mtextp, NULL, got_it_textp,
  605.              IDCMP_GADGETDOWN,
  606.              IDCMP_GADGETDOWN, 640, 50);
  607.  
  608.     gfree (mtextp);
  609.     gfree (got_it_textp);
  610. }
  611.  
  612. /*
  613.  * I very much like the appearance of gadgets whose background and text are
  614.  * complemented when selected. Complementing also works well with 3-d gadget
  615.  * borders.  And, I find the use of 'images' to be inefficient and difficult
  616.  * in comparison with Intuition borders and text.  Therefore, I have decided
  617.  * NOT to follow the guidelines for 'mutually exclusive' gadgets on page 140
  618.  * of the Amiga Rom Kernel Reference Manual, Third Edition, which
  619.  * specifically advise against this combination (mutually exclusive gadgets
  620.  * using complementing).
  621.  *
  622.  * However, I have chosen instead to follow the guidelines for 'Updating
  623.  * a Gadget's Imagery' on pages 129-130.  Before a radio_button is
  624.  * refreshed in either selected or unselected state, the background
  625.  * behind it is restored ("cleared") with RectFill.  I do this very
  626.  * carefully as you will see.
  627.  *
  628.  * This concept has been extended to cover other features, such as
  629.  * gadget disable and enable, which I couldn't get to work before.
  630.  *
  631.  * This should be acceptable and stable with future released of Intuition.
  632.  * At least, there is some hope.  And it works with 1.2-2.1 for sure.
  633.  *
  634.  * It now even handles requester gadgets properly.
  635.  */
  636.  
  637. void radio_button__in (struct Gadget *gadgetp, struct Window *windowp)
  638. {
  639.     struct RastPort *rport;
  640.     short x1, y1, x2, y2;
  641.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  642.  
  643.     if (windowp)
  644.     {
  645.     if (!(gadgetp->Flags & GFLG_SELECTED))  /* pushing my luck */
  646.     {
  647.         RemoveGadget (windowp, gadgetp); 
  648.         gadgetp->Flags |= GFLG_SELECTED;
  649.  
  650.         rport = (current_requesterp) ? 
  651.           current_requesterp->ReqLayer->rp :
  652.         windowp->RPort;
  653.  
  654.         save_apen = rport->FgPen;
  655.  
  656.         SetAPen (rport, (UBYTE) background_pen);
  657.         SetDrMd (rport, JAM1);
  658.         SetAfPt (rport, NULL, 0);
  659.         SetWrMsk (rport, (UBYTE) 0xff);
  660.         BNDRYOFF (rport);
  661.         x1 = gadgetp->LeftEdge;
  662.         y1 = gadgetp->TopEdge;
  663.         x2 = x1 + gadgetp->Width - 1;
  664.         y2 = y1 + gadgetp->Height - 1;
  665.         
  666.         RectFill (rport, x1, y1, x2, y2);
  667.         
  668.         SetAPen (rport, (UBYTE) save_apen);
  669.         
  670.         AddGList (windowp, gadgetp, -1, 1, current_requesterp);
  671.         refresh_gadget (gadgetp, windowp);
  672.     }
  673.     }
  674.     else  /* if (!windowp) */
  675.     {
  676.     gadgetp->Flags |= GFLG_SELECTED;
  677.     }
  678. }
  679.     
  680. void radio_button__out (struct Gadget *gadgetp, struct Window *windowp)
  681. {
  682.     struct RastPort *rport;
  683.     short x1, y1, x2, y2;
  684.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  685.  
  686.     if (windowp)
  687.     {
  688.     if (gadgetp->Flags & GFLG_SELECTED)
  689.     {
  690.         RemoveGadget (windowp, gadgetp);
  691.         gadgetp->Flags &= ~GFLG_SELECTED;
  692.  
  693.         rport = (current_requesterp) ? 
  694.           current_requesterp->ReqLayer->rp :
  695.           windowp->RPort;
  696.  
  697.         save_apen = rport->FgPen;
  698.  
  699.         SetAPen (rport, (UBYTE) background_pen);
  700.         SetDrMd (rport, JAM1);
  701.         SetAfPt (rport, NULL, 0);
  702.         SetWrMsk (rport, (UBYTE) 0xff);
  703.         BNDRYOFF (rport);
  704.         x1 = gadgetp->LeftEdge;
  705.         y1 = gadgetp->TopEdge;
  706.         x2 = x1 + gadgetp->Width - 1;
  707.         y2 = y1 + gadgetp->Height - 1;
  708.  
  709.         RectFill (rport, x1, y1, x2, y2);
  710.  
  711.         SetAPen (rport, (UBYTE) save_apen);
  712.  
  713.         AddGList (windowp, gadgetp, -1, 1, current_requesterp);
  714.         refresh_gadget (gadgetp, windowp);
  715.     }
  716.     }
  717.     else /* if (!windowp) */
  718.     {
  719.     gadgetp->Flags &= ~GFLG_SELECTED;
  720.     }
  721. }
  722.  
  723. void gadget__disable (struct Gadget *gadgetp, struct Window *windowp)
  724. {
  725.     struct RastPort *rport;
  726.     short x1, y1, x2, y2;
  727.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  728.  
  729.     if (gadgetp->Flags & GFLG_DISABLED) return;
  730.  
  731.     if (!windowp)
  732.     {
  733.     gadgetp->Flags |= GFLG_DISABLED;
  734.     return;
  735.     }
  736.  
  737. /* #define OFF_GADGET_OK */
  738.  
  739. #ifdef OFF_GADGET_OK
  740.     OffGadget (gadgetp, windowp, current_requesterp);
  741. #else
  742.  
  743. /* I thought I had figured it all out, but another OffGadget bug fooled */
  744. /* even me.  A different gadget gets hosed.  So, here I am doing */
  745. /* it my way again. (I was already doing this for OnGadget and almost */
  746. /* everything else anyway...but I had figured OffGadget would be OK.) */
  747. /* Oh well.  (See additional lengthy comments written earlier above.) */
  748.  
  749.     RemoveGadget (windowp, gadgetp);
  750.     gadgetp->Flags |= GFLG_DISABLED;
  751.  
  752.     rport = (current_requesterp) ? current_requesterp->ReqLayer->rp :
  753.       windowp->RPort;
  754.  
  755.     save_apen = rport->FgPen;
  756.  
  757.     SetAPen (rport, (UBYTE) background_pen);
  758.     SetDrMd (rport, JAM1);
  759.     SetAfPt (rport, NULL, 0);
  760.     SetWrMsk (rport, (UBYTE) 0xff);
  761.     BNDRYOFF (rport);
  762.     x1 = gadgetp->LeftEdge;
  763.     y1 = gadgetp->TopEdge;
  764.     x2 = x1 + gadgetp->Width - 1;
  765.     y2 = y1 + gadgetp->Height - 1;
  766.     
  767.     RectFill (rport, x1, y1, x2, y2);
  768.     
  769.     SetAPen (rport, (UBYTE) save_apen);
  770.  
  771.     AddGList (windowp, gadgetp, -1, 1, current_requesterp);
  772.     refresh_gadget (gadgetp, windowp);
  773.  
  774. #endif /* OffGadget not OK */
  775.  
  776. }
  777.  
  778. void gadget__enable (struct Gadget *gadgetp, struct Window *windowp)
  779. {
  780.     struct RastPort *rport;
  781.     short x1, y1, x2, y2;
  782.     UBYTE save_apen;  /* I preserve this one, dunno if necessary */
  783.  
  784.     if (!(gadgetp->Flags & GFLG_DISABLED)) return;
  785.  
  786.     if (!windowp)
  787.     {
  788.     gadgetp->Flags |= GFLG_DISABLED;
  789.     return;
  790.     }
  791.  
  792. /* Yes, of course, OnGadget isn't smart enough for border gadgets */
  793.  
  794.     RemoveGadget (windowp, gadgetp);
  795.     gadgetp->Flags &= ~GFLG_DISABLED;
  796.  
  797.     rport = (current_requesterp) ? current_requesterp->ReqLayer->rp :
  798.       windowp->RPort;
  799.  
  800.     save_apen = rport->FgPen;
  801.  
  802.     SetAPen (rport, (UBYTE) background_pen);
  803.     SetDrMd (rport, JAM1);
  804.     SetAfPt (rport, NULL, 0);
  805.     SetWrMsk (rport, (UBYTE) 0xff);
  806.     BNDRYOFF (rport);
  807.     x1 = gadgetp->LeftEdge;
  808.     y1 = gadgetp->TopEdge;
  809.     x2 = x1 + gadgetp->Width - 1;
  810.     y2 = y1 + gadgetp->Height - 1;
  811.     
  812.     RectFill (rport, x1, y1, x2, y2);
  813.     
  814.     SetAPen (rport, (UBYTE) save_apen);
  815.  
  816.     AddGList (windowp, gadgetp, -1, 1, current_requesterp);
  817.     refresh_gadget (gadgetp, windowp);
  818. }
  819.  
  820.  
  821. void message_gadget__write (struct Gadget *gadgetp, char *message, struct
  822.                 Window *windowp)
  823. {
  824.     struct RastPort *rport;
  825.  
  826.     if (windowp) RemoveGadget (windowp, gadgetp);
  827.  
  828.     if (gadgetp->GadgetText) gfree (gadgetp->GadgetText);
  829.     gadgetp->GadgetText = button_text__new (message);
  830.     gadgetp->GadgetText->FrontPen = fill_text_pen;
  831.  
  832.     if (windowp)
  833.     {
  834.     short x1, y1, x2, y2;
  835.  
  836.     x1 = gadgetp->LeftEdge;
  837.     y1 = gadgetp->TopEdge;
  838.     x2 = x1 + gadgetp->Width - 1;
  839.     y2 = y1 + gadgetp->Height - 1;
  840.  
  841.     rport = (current_requesterp) ? current_requesterp->ReqLayer->rp :
  842.       windowp->RPort;
  843.  
  844.     RectFill (rport, x1, y1, x2, y2);
  845.     AddGList (windowp, gadgetp, -1, 1, current_requesterp);
  846.     refresh_gadget (gadgetp, windowp);
  847.     }
  848. }
  849.  
  850.  
  851. struct Requester *requester__new (void)
  852. {
  853.     struct Requester *requesterp;
  854.     short height = (max_rows * (FONT_SIZE + (2 * BUTTON_TOP_EDGE)))
  855.                      + ((max_rows - 1) * BUTTON_TOP_SPACE) +
  856.              + (2 * FIRST_REQUESTER_BUTTON_TOP);
  857.     short width = (Max_Columns * FONT_SIZE) + 
  858.       (2 * (FIRST_REQUESTER_BUTTON_LEFT + BUTTON_SIDE_EDGE));
  859.  
  860.     requesterp = gmalloc (sizeof (struct Requester), NOTHING_SPECIAL);
  861.     InitRequester (requesterp);
  862.     requesterp->BackFill = background_pen;
  863.     requesterp->ReqBorder = requester_border__new (height, width, shine_pen,
  864.                            shadow_pen);
  865.     requesterp->Width = width;
  866.     requesterp->Height = height;
  867.     requesterp->RelLeft = 0;
  868.     requesterp->RelTop = 0;
  869.     requesterp->Flags = POINTREL;
  870.     return requesterp;
  871. }
  872.  
  873. BOOLEAN requester__display (struct Requester *rp, struct Window *wp)
  874. {
  875.     if (Request (rp, wp))
  876.     {
  877.     current_requesterp = rp;
  878.     return TRUE;
  879.     }
  880.     return FALSE;
  881. }
  882.  
  883. void requester__remove (struct Requester *rp, struct Window *wp)
  884. {
  885.     current_requesterp = NULL;
  886.     EndRequest (rp, wp);
  887. }
  888.  
  889.  
  890. #endif  /* ifdef AMIGA */
  891.  
  892.