home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 500-599 / ff562.lza / Intuisup / Gadgets / source.lzh / gadgets1.c < prev    next >
C/C++ Source or Header  |  1991-10-25  |  34KB  |  1,227 lines

  1.         /*************************************
  2.          *                                   *
  3.          *            Gadgets v2.0           *
  4.          *   by Torsten Jürgeleit in 05/91   *
  5.          *                                   *
  6.          *          Routines - Part 1        *
  7.          *                                   *
  8.          *************************************/
  9.  
  10.     /* Includes */
  11.  
  12. #include <exec/types.h>
  13. #include <exec/memory.h>
  14. #include <devices/inputevent.h>
  15. #include <intuition/intuition.h>
  16. #include <functions.h>
  17. #include <string.h>
  18. #include "/render/render.h"
  19. #include "/texts/texts.h"
  20. #include "gadgets.h"
  21. #include "imports.h"
  22.  
  23.     /* Defines */
  24.  
  25. #define QUALIFIER_SHIFT        (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)
  26. #define QUALIFIER_ALT        (IEQUALIFIER_LALT | IEQUALIFIER_RALT)
  27.  
  28.     /* Static data */
  29.  
  30. STATIC struct VisibleGadgetLists  visible_gadget_lists = {
  31.    {   /* struct SignalSemaphore  vg_Semaphore */
  32.       {   /* struct Node  ss_Link */
  33.      NULL, NULL, NT_SEMAPHORE, 0, NULL
  34.       }, 0,
  35.       {   /* struct MinList  ss_WaitQueue */
  36.      (struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Tail,
  37.      NULL,
  38.      (struct MinNode *)&visible_gadget_lists.vg_Semaphore.ss_WaitQueue.mlh_Head
  39.       },
  40.       {   /* struct SemaphoreRequest  ss_MultipleLink */
  41.      {   /* struct MinNode  sr_Link */
  42.         NULL, NULL
  43.      }, NULL
  44.       }, NULL, -1
  45.    },
  46.    {   /* struct MinList  vg_MinList */
  47.       (struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Tail,
  48.       NULL,
  49.       (struct MinNode *)&visible_gadget_lists.vg_MinList.mlh_Head
  50.    }, 0
  51. };
  52.     /* Create gadget list */
  53.  
  54.    struct GadgetList  *
  55. create_gadgets(struct RenderInfo  *ri, struct GadgetData  *gd,
  56.                            SHORT hoffset, SHORT voffset)
  57. {
  58.    struct GadgetList  *gl;
  59.    BYTE   *gadget_buffer, *image_buffer = NULL;
  60.    USHORT data_entries;
  61.    ULONG  gl_size, gadget_buffer_size, image_buffer_size;
  62.  
  63.    if (ri && gd && (data_entries = count_gadget_data_entries(gd))) {
  64.       gl_size = sizeof(struct GadgetList) + (data_entries - 1) *
  65.                         sizeof(struct ExtendedGadget *);
  66.       if (gl = AllocMem(gl_size, (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
  67.      gl->gl_RenderInfo  = ri;
  68.      gl->gl_Data        = gd;
  69.      gl->gl_DataEntries = data_entries;
  70.      if ((gadget_buffer_size = get_gadget_buffer_size(gl)) &&
  71.             (gadget_buffer = AllocMem(gadget_buffer_size, (LONG)
  72.                            MEMF_PUBLIC | MEMF_CLEAR))) {
  73.         if (image_buffer_size = get_image_buffer_size(gl)) {
  74.            image_buffer = AllocMem(image_buffer_size, (LONG)
  75.                            MEMF_PUBLIC | MEMF_CHIP);
  76.         }
  77.         if (!image_buffer_size || image_buffer) {
  78.            /* init gadget list struct */
  79.            gl->gl_GadgetBuffer     = gadget_buffer;
  80.            gl->gl_GadgetBufferSize = gadget_buffer_size;
  81.            gl->gl_ImageBuffer      = image_buffer;
  82.            gl->gl_ImageBufferSize  = image_buffer_size;
  83.            init_gadgets(gl, hoffset, voffset);
  84.            return(gl);
  85.         }
  86.         FreeMem(gadget_buffer, gadget_buffer_size);
  87.      }
  88.      FreeMem(gl, gl_size);
  89.       }
  90.    }
  91.    return(NULL);
  92. }
  93.     /* Free gadget list */
  94.  
  95.    VOID
  96. free_gadgets(struct GadgetList  *gl)
  97. {
  98.    if (gl) {
  99.       if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  100.      remove_gadgets(gl);
  101.       }
  102.       FreeMem(gl->gl_GadgetBuffer, gl->gl_GadgetBufferSize);
  103.       if (gl->gl_ImageBufferSize) {
  104.      FreeMem(gl->gl_ImageBuffer, gl->gl_ImageBufferSize);
  105.       }
  106.       FreeMem(gl, (LONG)(sizeof(struct GadgetList) +
  107.            (gl->gl_DataEntries - 1) * sizeof(struct ExtendedGadget *)));
  108.    }
  109. }
  110.     /* Display gadget list */
  111.  
  112.    VOID
  113. display_gadgets(struct Window  *win, struct GadgetList  *gl)
  114. {
  115.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  116.    struct ExtendedGadget      *egad, *last_egad = NULL;
  117.    USHORT i, data_entries = gl->gl_DataEntries;
  118.  
  119.    if (win && gl && !(gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED)) {
  120.       gl->gl_Window = win;
  121.       gl->gl_Flags |= GADGET_LIST_FLAG_DISPLAYED;
  122.       ObtainSemaphore(&vg->vg_Semaphore);
  123.       AddTail((struct List *)&vg->vg_MinList, (struct Node *)
  124.                                &gl->gl_MinNode);
  125.       vg->vg_Count++;
  126.       ReleaseSemaphore(&vg->vg_Semaphore);
  127.       /* link gadget list */
  128.       for (i = 0; i < data_entries; i++) {
  129.      egad = gl->gl_Gadgets[i];
  130.      do {
  131.         if (last_egad) {
  132.            last_egad->eg_Gadget.NextGadget = &egad->eg_Gadget;
  133.         }
  134.         last_egad = egad;
  135.      } while (egad = egad->eg_NextGadget);
  136.       }
  137.       AddGList(win, &gl->gl_Gadgets[0]->eg_Gadget, -1L, -1L, (LONG)NULL);
  138.       refresh_gadgets(gl);
  139.    }
  140. }
  141.     /* Refresh gadget list */
  142.  
  143.    VOID
  144. refresh_gadgets(struct GadgetList  *gl)
  145. {
  146.    USHORT i, data_entries = gl->gl_DataEntries;
  147.  
  148.    if (gl && gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  149.       for (i = 0; i < data_entries; i++) {
  150.      refresh_gadget(gl->gl_Gadgets[i]);
  151.       }
  152.    }
  153. }
  154.     /* Set gadget attributes */
  155.  
  156.    ULONG
  157. set_gadget_attributes(struct GadgetList  *gl, USHORT data_entry,
  158.              ULONG flags, ULONG data1, ULONG data2, VOID *data3)
  159. {
  160.    struct Window          *win = gl->gl_Window;
  161.    struct RastPort        *rp;
  162.    struct GadgetData      *gd;
  163.    struct ExtendedGadget  *egad, *save_egad;
  164.    struct Gadget          *gad = NULL;
  165.    struct StringInfo      *sinfo;
  166.    struct List            *list;
  167.    struct Node            *node;
  168.    struct MXData          *mx;
  169.    struct SliderData      *sl;
  170.    struct ScrollerData    *sc;
  171.    struct CycleData       *cy;
  172.    struct CountData       *co;
  173.    struct ListViewData    *lv;
  174.    struct PaletteData     *pd;
  175.    VOID   *data;
  176.    UBYTE  displayed;
  177.    BYTE   *buffer, *input, **text;
  178.    ULONG  min, max, num, value = 0;
  179.    USHORT i, type;
  180.  
  181.    if (gl && data_entry < gl->gl_DataEntries) {
  182.       /* get gadget data */
  183.       gd   = gl->gl_Data + data_entry;
  184.       type = gd->gd_Type;
  185.       egad = save_egad = gl->gl_Gadgets[data_entry];
  186.       gad  = &egad->eg_Gadget;
  187.       data = (VOID *)(egad + 1);
  188.       if (data1 != USE_CURRENT_VALUE || data2 != USE_CURRENT_VALUE ||
  189.                        data3 != (VOID *)USE_CURRENT_VALUE) {
  190.      switch (type) {
  191.         case GADGET_DATA_TYPE_BUTTON :
  192.            if (gad->Activation & TOGGLESELECT) {
  193.           if (gad->Flags & SELECTED) {
  194.              value = 1;
  195.           }
  196.           if (data1 != USE_CURRENT_VALUE) {
  197.              if (data1) {
  198.             gad->Flags |= SELECTED;
  199.              } else {
  200.             gad->Flags &= ~SELECTED;
  201.              }
  202.              change_gadget(egad);
  203.           }
  204.            }
  205.            break;
  206.         case GADGET_DATA_TYPE_CHECK :
  207.            if (gad->Flags & SELECTED) {
  208.           value = 1;
  209.            }
  210.            if (data1 != USE_CURRENT_VALUE) {
  211.           if (data1) {
  212.              gad->Flags |= SELECTED;
  213.           } else {
  214.              gad->Flags &= ~SELECTED;
  215.           }
  216.           change_gadget(egad);
  217.            }
  218.            break;
  219.         case GADGET_DATA_TYPE_MX :
  220.            mx    = data;
  221.            value = mx->mx_ActiveEntry;
  222.            if (data2 != USE_CURRENT_VALUE) {
  223.           max = mx->mx_TextEntries;
  224.           num = data2;
  225.           if (num >= max) {
  226.              num = max - 1;   /* activate last entry */
  227.           }
  228.           mx->mx_ActiveEntry = num;
  229.           change_gadget(egad);
  230.            }
  231.            break;
  232.         case GADGET_DATA_TYPE_STRING :
  233.         case GADGET_DATA_TYPE_INTEGER :
  234.            sinfo  = (struct StringInfo *)gad->SpecialInfo;
  235.            buffer = (BYTE *)sinfo->Buffer;
  236.            if (type == GADGET_DATA_TYPE_STRING) {
  237.           value = (ULONG)buffer;
  238.            } else {
  239.           value = sinfo->LongInt;
  240.            }
  241.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  242.           max   = sinfo->MaxChars;
  243.           input = data3;
  244.           if (type == GADGET_DATA_TYPE_STRING) {
  245.              if (gd->gd_Flags &
  246.                      GADGET_DATA_FLAG_STRING_UNSIGNED_DEC) {
  247.             if ((LONG)input != -1L) {
  248.                min = convert_unsigned_dec((ULONG)input, buffer);
  249.             } else {
  250.                min = 0;
  251.             }
  252.              } else {
  253.             if (gd->gd_Flags &
  254.                        GADGET_DATA_FLAG_STRING_SIGNED_DEC) {
  255.                if ((LONG)input != -1L) {
  256.                   min = convert_signed_dec((ULONG)input, buffer);
  257.                } else {
  258.                   min = 0;
  259.                }
  260.             } else {
  261.                if (gd->gd_Flags & GADGET_DATA_FLAG_STRING_HEX) {
  262.                   if ((LONG)input != -1L) {
  263.                  min = convert_hex((ULONG)input, buffer);
  264.                   } else {
  265.                  min = 0;
  266.                   }
  267.                } else {
  268.                   if (gd->gd_Flags &
  269.                           GADGET_DATA_FLAG_STRING_BIN) {
  270.                  if ((LONG)input != -1L) {
  271.                     min = convert_bin((ULONG)input, buffer);
  272.                  } else {
  273.                     min = 0;
  274.                  }
  275.                   } else {
  276.                  if (input) {
  277.                     if ((min = strlen(input)) > max) {
  278.                        min = max;
  279.                     }
  280.                     strncpy(buffer, input, (size_t)min);
  281.                  } else {
  282.                     min = 0;
  283.                  }
  284.                   }
  285.                }
  286.             }
  287.              }
  288.           } else {
  289.              if ((LONG)input != -1L) {
  290.             min = convert_unsigned_dec((ULONG)input, buffer);
  291.              } else {
  292.             min = 0;
  293.              }
  294.           }
  295.           *(buffer + min)  = '\0';   /* mark end of string */
  296.           sinfo->BufferPos = 0;
  297.           change_gadget(egad);
  298.            }
  299.            break;
  300.         case GADGET_DATA_TYPE_SLIDER :
  301.            sl    = data;
  302.            value = sl->sl_Level;
  303.            if (data1 != USE_CURRENT_VALUE) {
  304.           min = sl->sl_Min = data1;
  305.            } else {
  306.           min = sl->sl_Min;
  307.            }
  308.            if (data2 != USE_CURRENT_VALUE) {
  309.           max = sl->sl_Max = data2;
  310.            } else {
  311.           max = sl->sl_Max;
  312.            }
  313.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  314.           num = (ULONG)data3;
  315.            } else {
  316.           num = sl->sl_Level;
  317.            }
  318.            if ((LONG)num < (LONG)min) {
  319.           num = min;
  320.            } else {
  321.           if ((LONG)num > (LONG)max) {
  322.              num = max;
  323.           }
  324.            }
  325.            sl->sl_Level = num;
  326.            change_gadget(egad);
  327.            break;
  328.         case GADGET_DATA_TYPE_SCROLLER :
  329.            sc    = data;
  330.            value = sc->sc_Top;
  331.            if (data1 != USE_CURRENT_VALUE) {
  332.           min = sc->sc_Visible = data1;
  333.            } else {
  334.           min = sc->sc_Visible;
  335.            }
  336.            if (data2 != USE_CURRENT_VALUE) {
  337.           max = sc->sc_Total = data2;
  338.            } else {
  339.           max = sc->sc_Total;
  340.            }
  341.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  342.           num = (ULONG)data3;
  343.            } else {
  344.           num = sc->sc_Top;
  345.            }
  346.            if (num >= max || (max - num) < min) {
  347.           num = (max > min ? max - min : min - max);
  348.            }
  349.            sc->sc_Top = num;
  350.            change_gadget(egad);
  351.            break;
  352.         case GADGET_DATA_TYPE_CYCLE :
  353.            cy    = data;
  354.            value = cy->cy_ActiveEntry;
  355.            if (data2 != USE_CURRENT_VALUE) {
  356.           text = cy->cy_TextArray;
  357.           max  = cy->cy_TextEntries;
  358.           num  = data2;
  359.           if (num > max) {
  360.              num = max;   /* activate last entry */
  361.           }
  362.           cy->cy_ActiveEntry = num;
  363.           change_gadget(egad);
  364.            }
  365.            break;
  366.         case GADGET_DATA_TYPE_COUNT :
  367.            co    = data;
  368.            value = co->co_Value;
  369.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  370.           min = co->co_Min;
  371.           max = co->co_Max;
  372.           num = (ULONG)data3;
  373.           if ((LONG)num < (LONG)min) {
  374.              num = min;
  375.           } else {
  376.              if ((LONG)num > (LONG)max) {
  377.             num = max;
  378.              }
  379.           }
  380.           co->co_Value = num;
  381.           change_gadget(egad);
  382.            }
  383.            break;
  384.         case GADGET_DATA_TYPE_LISTVIEW :
  385.            lv    = data;
  386.            value = lv->lv_TopEntry;
  387.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  388.           max  = 0;
  389.           num  = 0;
  390.           list = data3;
  391.           if (list) {
  392.              /* count list nodes */
  393.              node = list->lh_Head;
  394.              while (node = node->ln_Succ) {
  395.             max++;
  396.              }
  397.           }
  398.           lv->lv_List        = list;
  399.           lv->lv_ListEntries = max;
  400.            }
  401.            if (data2 != USE_CURRENT_VALUE || (ULONG)data3 !=
  402.                             USE_CURRENT_VALUE) {
  403.           list = lv->lv_List;
  404.           min  = lv->lv_VisibleEntries;
  405.           max  = lv->lv_ListEntries;
  406.           node = NULL;
  407.           /* search top list node */
  408.           if (max) {
  409.              if (data2 != USE_CURRENT_VALUE) {
  410.             num = data2;
  411.              } else {
  412.             num = lv->lv_TopEntry;
  413.              }
  414.              if (num && max > min) {
  415.             if (num > max || (max - num) < min) {
  416.                num  = max - min;
  417.                node = list->lh_TailPred;
  418.                for (i = max - num - 1; i; i--) {
  419.                   node = node->ln_Pred;
  420.                }
  421.             } else {
  422.                node = list->lh_Head;
  423.                for (i = 0; i < num; i++) {
  424.                   node = node->ln_Succ;
  425.                }
  426.             }
  427.              } else {
  428.             num  = 0;
  429.             node = list->lh_Head;
  430.              }
  431.           }
  432.           /* init list view data */
  433.           lv->lv_TopEntry = num;
  434.           lv->lv_TopNode  = node;
  435.           change_gadget(egad);   /* before changing list entry gadget flags !!! */
  436.           /* set GADGHNONE flag for all entry gadgets without list node */
  437.           if (!(lv->lv_Flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY)) {
  438.              egad = egad->eg_NextGadget->eg_NextGadget->eg_NextGadget;   /* ptr to first entry gadget */
  439.              for (i = 0; i < min; i++, num++) {
  440.             gad = &egad->eg_Gadget;
  441.             if (num < max) {
  442.                gad->Flags = (gad->Flags & ~GADGHIGHBITS) |
  443.                                   GADGHCOMP;
  444.             } else {
  445.                gad->Flags = (gad->Flags & ~GADGHIGHBITS) |
  446.                                   GADGHNONE;
  447.             }
  448.             egad = egad->eg_NextGadget;
  449.              }
  450.              egad = save_egad;
  451.           }
  452.            }
  453.            break;
  454.         case GADGET_DATA_TYPE_PALETTE :
  455.            pd    = data;
  456.            value = pd->pd_ActiveColor;
  457.            if ((ULONG)data3 != USE_CURRENT_VALUE) {
  458.           min = pd->pd_ColorOffset;
  459.           max = pd->pd_MaxColors;
  460.           num = (ULONG)data3;
  461.           if (num < min) {
  462.              num = min;
  463.           } else {
  464.              if (num >= (max + min)) {
  465.             num = max + min - 1;
  466.              }
  467.           }
  468.           pd->pd_ActiveColor = num;
  469.           change_gadget(egad);
  470.            }
  471.            break;
  472.      }
  473.       }
  474.       /* toggle able state of gadget */
  475.       if (((flags & GADGET_DATA_FLAG_DISABLED) && !(gad->Flags &
  476.           GADGDISABLED)) || (!(flags & GADGET_DATA_FLAG_DISABLED) &&
  477.                          (gad->Flags & GADGDISABLED))) {
  478.      if (displayed = gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  479.         rp = win->RPort;
  480.         SetDrMd(rp, (LONG)JAM1);
  481.         SetAPen(rp, (LONG)gl->gl_RenderInfo->ri_BackPen);
  482.      }
  483.      do {
  484.         gad = &egad->eg_Gadget;
  485.         if (gad->Flags & GADGDISABLED) {
  486.            gad->Flags &= ~GADGDISABLED;
  487.            /* clear ghosted gadget select box */
  488.            if (displayed) {
  489.           RectFill(rp, (LONG)gad->LeftEdge, (LONG)gad->TopEdge,
  490.                   (LONG)(gad->LeftEdge + gad->Width - 1), (LONG)
  491.                       (gad->TopEdge + gad->Height - 1));
  492.            }
  493.         } else {
  494.            gad->Flags |= GADGDISABLED;
  495.         }
  496.      } while (egad = egad->eg_NextGadget);
  497.      refresh_gadget(save_egad);
  498.       }
  499.    }
  500.    return(value);
  501. }
  502.     /* Activate string or integer imput gadget */
  503.  
  504.    VOID
  505. activate_input_gadget(struct GadgetList  *gl, USHORT data_entry)
  506. {
  507.    struct GadgetData  *gd;
  508.    struct Gadget      *gad;
  509.    UBYTE type;
  510.  
  511.    if (data_entry < gl->gl_DataEntries) {
  512.       gd   = gl->gl_Data + data_entry;
  513.       type = gd->gd_Type;
  514.       if (type == GADGET_DATA_TYPE_STRING ||
  515.                      type == GADGET_DATA_TYPE_INTEGER) {
  516.      gad = &gl->gl_Gadgets[data_entry]->eg_Gadget;
  517.      if (gad->Flags & GADGDISABLED) {
  518.         if (gd->gd_Flags & GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE) {
  519.            /* !!! recurrence (in german: Rekursion) !!! */
  520.            activate_input_gadget(gl, (USHORT)
  521.               gd->gd_SpecialData.gd_InputData.gd_InputActivateNext);
  522.         }
  523.      } else {
  524.         ActivateGadget(gad, gl->gl_Window, (LONG)NULL);
  525.      }
  526.       }
  527.    }
  528. }
  529.     /* Return gadget address */
  530.  
  531.    struct Gadget *
  532. gadget_address(struct GadgetList  *gl, USHORT data_entry)
  533. {
  534.    struct Gadget  *gad;
  535.  
  536.    if (data_entry >= gl->gl_DataEntries) {
  537.       gad = NULL;
  538.    } else {
  539.       gad = &gl->gl_Gadgets[data_entry]->eg_Gadget;
  540.    }
  541.    return(gad);
  542. }
  543.     /* Remove gadget list from display */
  544.  
  545.    VOID
  546. remove_gadgets(struct GadgetList  *gl)
  547. {
  548.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  549.    struct Window              *win = gl->gl_Window;
  550.    struct ExtendedGadget      *egad;
  551.    USHORT i, data_entries = gl->gl_DataEntries;
  552.  
  553.    if (gl && data_entries && gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  554.       ObtainSemaphore(&vg->vg_Semaphore);
  555.       Remove((struct Node *)&gl->gl_MinNode);
  556.       vg->vg_Count--;
  557.       ReleaseSemaphore(&vg->vg_Semaphore);
  558.       for (i = 0; i < data_entries; i++) {
  559.      egad = gl->gl_Gadgets[i];
  560.      do {
  561.         RemoveGList(win, &egad->eg_Gadget, 1L);
  562.      } while (egad = egad->eg_NextGadget);
  563.       }
  564.       gl->gl_Flags &= ~GADGET_LIST_FLAG_DISPLAYED;
  565.    }
  566. }
  567.     /* Get intuition msg and perform any action to isup gadgets */
  568.  
  569.    struct IntuiMessage *
  570. get_msg(struct MsgPort  *uport)
  571. {
  572.    struct IntuiMessage    *real_imsg, *imsg = NULL;
  573.    struct GadgetList      *gl;
  574.    struct ExtendedGadget  *egad;
  575.  
  576.    if (uport) {
  577.       while (imsg == NULL && (real_imsg = (struct IntuiMessage *)
  578.                                GetMsg(uport))) {
  579.      switch (real_imsg->Class) {
  580.         case GADGETDOWN :
  581.            egad = (struct ExtendedGadget *)real_imsg->IAddress;
  582.            if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
  583.           imsg = perform_gadget_action(egad, real_imsg);
  584.           if ((egad->eg_Gadget.Activation & FOLLOWMOUSE) ||
  585.                   egad->eg_Gadget.Activation == (GADGIMMEDIATE |
  586.                                    RELVERIFY)) {
  587.              /* save active gadget and set auto repeat delay counter */
  588.              gl                     = egad->eg_GadgetList;
  589.              gl->gl_ActiveGadget    = egad;
  590.              gl->gl_AutoRepeatDelay = ARROW_AUTO_REPEAT_START_DELAY;
  591.           }
  592.            } else {
  593.           egad = NULL;   /* return imsg later */
  594.            }
  595.            break;
  596.         case GADGETUP :
  597.            egad = (struct ExtendedGadget *)real_imsg->IAddress;
  598.            if (egad->eg_Gadget.MutualExclude == ISUP_ID) {
  599.           imsg = perform_gadget_action(egad, real_imsg);
  600.           /* reset saved active gadget */
  601.           egad->eg_GadgetList->gl_ActiveGadget = NULL;
  602.             } else {
  603.           egad = NULL;   /* return imsg later */
  604.            }
  605.            break;
  606.         case MOUSEMOVE :
  607.            if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
  608.           imsg = perform_gadget_action(egad, real_imsg);
  609.            }
  610.            break;
  611.         case INTUITICKS :
  612.            if ((egad = get_active_gadget(real_imsg->IDCMPWindow))
  613.                     && (egad->eg_Gadget.Flags &    SELECTED)) {
  614.           if (egad->eg_Gadget.Activation == (GADGIMMEDIATE |
  615.                                    RELVERIFY)) {
  616.              /* check auto repeat delay counter */
  617.              gl = egad->eg_GadgetList;
  618.              if (gl->gl_AutoRepeatDelay) {
  619.             gl->gl_AutoRepeatDelay--;
  620.              } else {
  621.             imsg = perform_gadget_action(egad, real_imsg);
  622.              }
  623.           }
  624.            }
  625.            break;
  626.         case VANILLAKEY :
  627.            if (egad = get_hot_key_gadget(real_imsg->IDCMPWindow,
  628.                              real_imsg->Code)) {
  629.           if (!(egad->eg_Gadget.Flags & GADGDISABLED)) {
  630.              imsg = perform_hot_key_action(egad, real_imsg);
  631.           }
  632.            }
  633.            break;
  634.         default :
  635.            if (egad = get_active_gadget(real_imsg->IDCMPWindow)) {
  636.           egad->eg_GadgetList->gl_ActiveGadget = NULL;
  637.           egad = NULL;   /* return imsg later */
  638.            }
  639.            break;
  640.      }
  641.      if (!imsg) {
  642.         /* if isup msg then reply it, else return it */
  643.         if (egad) {
  644.            ReplyMsg((struct Message *)real_imsg);
  645.         } else {
  646.            imsg = real_imsg;
  647.         }
  648.      }
  649.       }
  650.    }
  651.    return(imsg);
  652. }
  653.     /* Reply intuition message and free ISUP message if any */
  654.  
  655.    VOID
  656. reply_msg(struct IntuiMessage  *imsg)
  657. {
  658.    struct IntuiMessage  *real_imsg;
  659.  
  660.    if (imsg) {
  661.       if (imsg->Class == ISUP_ID) {
  662.      real_imsg = *(struct IntuiMessage **)(imsg + 1);   /* real IntuiMessage direct after ISUP intuition message */
  663.      FreeMem(imsg, (LONG)(sizeof(struct IntuiMessage) +
  664.                         sizeof(struct IntuiMessage *)));
  665.      imsg = real_imsg;
  666.       }
  667.       ReplyMsg((struct Message *)imsg);
  668.    }
  669. }
  670.     /* Perform ISUP gadget action */
  671.  
  672.    STATIC struct IntuiMessage *
  673. perform_gadget_action(struct ExtendedGadget  *egad,
  674.                         struct IntuiMessage  *real_imsg)
  675. {
  676.    struct IntuiMessage    *imsg = NULL;
  677.    struct Gadget          *gad = &egad->eg_Gadget;
  678.    struct GadgetList      *gl = egad->eg_GadgetList;
  679.    USHORT data_entry = egad->eg_DataEntry;
  680.    struct GadgetData      *gd = gl->gl_Data + data_entry;
  681.    struct ExtendedGadget  *real_egad = gl->gl_Gadgets[data_entry];
  682.    struct MXData          *mx;
  683.    struct SliderData      *sl;
  684.    struct ScrollerData    *sc;
  685.    struct CycleData       *cy;
  686.    struct ListViewData    *lv;
  687.    struct PaletteData     *pd;
  688.    struct Node            *node;
  689.    VOID   *data = (VOID *)(real_egad + 1);
  690.    ULONG  min, max, num, value = 0, class = real_imsg->Class,
  691.       qualifier = real_imsg->Qualifier;
  692.    USHORT i, next_input, type = egad->eg_Type;
  693.  
  694.    switch (type) {
  695.       case EXTENDED_GADGET_TYPE_BUTTON :
  696.      if ((gd->gd_Flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) &&
  697.                             gad->Flags & SELECTED) {
  698.         value = 1;
  699.      }
  700.      change_gadget(real_egad);
  701.      break;
  702.       case EXTENDED_GADGET_TYPE_CHECK :
  703.      if (gad->Flags & SELECTED) {
  704.         value = 1;
  705.      }
  706.      break;
  707.       case EXTENDED_GADGET_TYPE_MX :
  708.      mx = data;
  709.      if (mx->mx_ActiveEntry != egad->eg_Gadget.GadgetID) {
  710.         mx->mx_ActiveEntry = value = egad->eg_Gadget.GadgetID;
  711.      } else {
  712.         real_imsg = NULL;
  713.      }
  714.      change_gadget(real_egad);
  715.      break;
  716.       case EXTENDED_GADGET_TYPE_STRING :
  717.       case EXTENDED_GADGET_TYPE_INTEGER :
  718.      if (!(qualifier & QUALIFIER_ALT) && (gd->gd_Flags &
  719.                     GADGET_DATA_FLAG_INPUT_AUTO_ACTIVATE)) {
  720.         if (qualifier & QUALIFIER_SHIFT) {
  721.            next_input = gd->gd_SpecialData.gd_InputData.gd_InputActivatePrev;
  722.         } else {
  723.            next_input = gd->gd_SpecialData.gd_InputData.gd_InputActivateNext;
  724.         }
  725.         activate_input_gadget(gl, next_input);
  726.      }
  727.      if (type == EXTENDED_GADGET_TYPE_STRING) {
  728.         value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->Buffer;
  729.      } else {
  730.         value = (ULONG)((struct StringInfo *)gad->SpecialInfo)->LongInt;
  731.      }
  732.      break;
  733.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  734.      if (class == GADGETUP) {
  735.         change_gadget(real_egad);
  736.         real_imsg = NULL;
  737.      } else {
  738.         sl  = data;
  739.         min = sl->sl_Min;
  740.         max = (LONG)sl->sl_Max - (LONG)min;
  741.         if (sl->sl_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  742.            num = max - ((LONG)get_prop_pos(max + 1, 1L,
  743.                ((struct PropInfo *)gad->SpecialInfo)->VertPot) -
  744.                                  (LONG)min);
  745.         } else {
  746.            num = (LONG)get_prop_pos(max + 1, 1L, ((struct PropInfo *)
  747.                    gad->SpecialInfo)->HorizPot) + (LONG)min;
  748.         }
  749.         if (sl->sl_Level != num) {
  750.            sl->sl_Level = value = num;
  751.         } else {
  752.            real_imsg = NULL;
  753.         }
  754.      }
  755.      break;
  756.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  757.      if (class == GADGETUP) {
  758.         change_gadget(real_egad);
  759.         real_imsg = NULL;
  760.      } else {
  761.         sc  = data;
  762.         min = sc->sc_Visible;
  763.         max = sc->sc_Total;
  764.         if (sc->sc_Flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  765.            num = get_prop_pos(max, min, ((struct PropInfo *)
  766.                         gad->SpecialInfo)->VertPot);
  767.         } else {
  768.            num = get_prop_pos(max, min, ((struct PropInfo *)
  769.                            gad->SpecialInfo)->HorizPot);
  770.         }
  771.         if (sc->sc_Top != num) {
  772.            sc->sc_Top = value = num;
  773.         } else {
  774.            real_imsg = NULL;
  775.         }
  776.      }
  777.      break;
  778.       case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
  779.       case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
  780.      if (class == GADGETUP) {
  781.         real_imsg = NULL;
  782.      } else {
  783.         sc  = data;
  784.         num = sc->sc_Top;
  785.         if (num > 0) {
  786.            sc->sc_Top = value = num - 1;
  787.            change_gadget(real_egad);
  788.         } else {
  789.            real_imsg = NULL;
  790.         }
  791.      }
  792.      break;
  793.       case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
  794.       case EXTENDED_GADGET_TYPE_SCROLLER_UP :
  795.      if (class == GADGETUP) {
  796.         real_imsg = NULL;
  797.      } else {
  798.         sc  = data;
  799.         num = sc->sc_Top;
  800.         min = sc->sc_Visible;
  801.         max = sc->sc_Total;
  802.         num++;
  803.         if (num < max && (max - num) >= min) {
  804.            sc->sc_Top = value = num;
  805.            change_gadget(real_egad);
  806.         } else {
  807.            real_imsg = NULL;
  808.         }
  809.      }
  810.      break;
  811.       case EXTENDED_GADGET_TYPE_CYCLE :
  812.      cy  = data;
  813.      max = cy->cy_TextEntries;
  814.      num = cy->cy_ActiveEntry;
  815.      if (real_imsg->Qualifier & QUALIFIER_SHIFT) {
  816.         if (num > 0) {
  817.            num--;
  818.         } else {
  819.            num = max - 1;
  820.         }
  821.      } else {
  822.         if (num < (max - 1)) {
  823.            num++;
  824.         } else {
  825.            num = 0;
  826.         }
  827.      }
  828.      cy->cy_ActiveEntry = value = num;
  829.      change_gadget(real_egad);
  830.      break;
  831.       case EXTENDED_GADGET_TYPE_COUNT :
  832.      change_count_gadget(real_egad);
  833.      value = ((struct CountData *)data)->co_Value;
  834.      break;
  835.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  836.      if (class == GADGETUP) {
  837.         change_gadget(real_egad);
  838.      } else {
  839.         lv  = data;
  840.         min = lv->lv_VisibleEntries;
  841.         max = lv->lv_ListEntries;
  842.         num = get_prop_pos(max, min, ((struct PropInfo *)
  843.                         gad->SpecialInfo)->VertPot);
  844.         if ((min = lv->lv_TopEntry) != num) {
  845.            node = lv->lv_TopNode;
  846.            if (min > num) {
  847.           for (i = min - num; i > 0; i--) {
  848.              node = node->ln_Pred;
  849.           }
  850.            } else {
  851.           for (i = num - min; i > 0; i--) {
  852.              node = node->ln_Succ;
  853.           }
  854.            }
  855.            lv->lv_TopNode  = node;
  856.            lv->lv_TopEntry = num;
  857.            if (gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED) {
  858.           print_list_view_text(egad);
  859.            }
  860.         }
  861.      }
  862.      real_imsg = NULL;
  863.      break;
  864.       case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
  865.      if (class != GADGETUP) {
  866.         lv  = data;
  867.         num = lv->lv_TopEntry;
  868.         if (num > 0) {
  869.            lv->lv_TopNode  = lv->lv_TopNode->ln_Pred;
  870.            lv->lv_TopEntry = value = num - 1;
  871.            change_gadget(real_egad);
  872.         }
  873.      }
  874.      real_imsg = NULL;
  875.      break;
  876.       case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
  877.      if (class != GADGETUP) {
  878.         lv  = data;
  879.         min = lv->lv_VisibleEntries;
  880.         max = lv->lv_ListEntries;
  881.         num = lv->lv_TopEntry + 1;
  882.         if (num < max && (max - num) >= min) {
  883.            lv->lv_TopNode  = lv->lv_TopNode->ln_Succ;
  884.            lv->lv_TopEntry = value = num;
  885.            change_gadget(real_egad);
  886.         }
  887.      }
  888.      real_imsg = NULL;
  889.      break;
  890.       case EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY :
  891.      lv  = data;
  892.      max = lv->lv_ListEntries;
  893.      num = lv->lv_TopEntry + egad->eg_Gadget.GadgetID;
  894.      if (num < max) {
  895.         value = num;
  896.      } else {
  897.         real_imsg = NULL;
  898.      }
  899.      break;
  900.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  901.      real_imsg = NULL;
  902.      break;
  903.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  904.      pd  = data;
  905.      num = egad->eg_Gadget.GadgetID;
  906.      if (num != pd->pd_ActiveColor) {
  907.         pd->pd_ActiveColor = value = num;
  908.         change_gadget(real_egad);
  909.      } else {
  910.         real_imsg = NULL;
  911.      }
  912.      break;
  913.    }
  914.    if (real_imsg) {
  915.       imsg = create_intui_message(real_imsg, gl, data_entry, value);
  916.    }
  917.    return(imsg);
  918. }
  919.     /* Perform hot key gadget action */
  920.  
  921.    STATIC struct IntuiMessage *
  922. perform_hot_key_action(struct ExtendedGadget  *egad,
  923.                         struct IntuiMessage  *real_imsg)
  924. {
  925.    struct IntuiMessage    *imsg = NULL;
  926.    struct Gadget          *gad = &egad->eg_Gadget;
  927.    struct GadgetList      *gl = egad->eg_GadgetList;
  928.    struct Window          *win = gl->gl_Window;
  929.    struct RastPort        *rp = win->RPort;
  930.    USHORT data_entry = egad->eg_DataEntry;
  931.    struct GadgetData      *gd = gl->gl_Data + data_entry;
  932.    struct ExtendedGadget  *real_egad = gl->gl_Gadgets[data_entry];
  933.    struct MXData          *mx;
  934.    struct SliderData      *sl;
  935.    struct ScrollerData    *sc;
  936.    struct CycleData       *cy;
  937.    struct CountData       *co;
  938.    struct ListViewData    *lv;
  939.    struct PaletteData     *pd;
  940.    struct Node            *node;
  941.    VOID   *data = (VOID *)(real_egad + 1);
  942.    USHORT draw_mode, displayed = gl->gl_Flags & GADGET_LIST_FLAG_DISPLAYED;
  943.    ULONG  min, max, num, value = 0, qualifier = real_imsg->Qualifier &
  944.                                 QUALIFIER_SHIFT;
  945.    switch (egad->eg_Type) {
  946.       case EXTENDED_GADGET_TYPE_BUTTON :
  947.      if (gd->gd_Flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) {
  948.         if (gad->Flags & SELECTED) {
  949.            gad->Flags &= ~SELECTED;
  950.         } else {
  951.            gad->Flags |= SELECTED;
  952.            value       = 1;
  953.         }
  954.      } else {
  955.         if (displayed) {
  956.            gad->Flags |= SELECTED;
  957.            change_gadget(real_egad);
  958.            timer_delay(0L, 100000L);
  959.            if ((gad->Flags & GADGHIGHBITS) == GADGHCOMP) {
  960.           /* if HIGHCOMP then invert gadget select box manually */
  961.           draw_mode = rp->DrawMode;
  962.           SetDrMd(win->RPort, (LONG)COMPLEMENT);
  963.           RectFill(win->RPort, (LONG)gad->LeftEdge, (LONG)
  964.                gad->TopEdge, (LONG)(gad->LeftEdge + gad->Width - 1),
  965.                     (LONG)(gad->TopEdge + gad->Height - 1));
  966.           SetDrMd(win->RPort, (LONG)draw_mode);   /* restore old draw mode */
  967.            }
  968.            gad->Flags &= ~SELECTED;
  969.         }
  970.      }
  971.      change_gadget(real_egad);
  972.      break;
  973.       case EXTENDED_GADGET_TYPE_CHECK :
  974.      if (gad->Flags & SELECTED) {
  975.         gad->Flags &= ~SELECTED;
  976.      } else {
  977.         gad->Flags |= SELECTED;
  978.         value       = 1;
  979.      }
  980.      change_gadget(real_egad);
  981.      break;
  982.       case EXTENDED_GADGET_TYPE_MX :
  983.      mx  = data;
  984.      max = mx->mx_TextEntries;
  985.      num = mx->mx_ActiveEntry;
  986.      if (qualifier) {
  987.         if (num > 0) {
  988.            num--;
  989.         } else {
  990.            num = max - 1;
  991.         }
  992.      } else {
  993.         if (num < (max - 1)) {
  994.            num++;
  995.         } else {
  996.            num = 0;
  997.         }
  998.      }
  999.      mx->mx_ActiveEntry = value = num;
  1000.      change_gadget(real_egad);
  1001.      break;
  1002.       case EXTENDED_GADGET_TYPE_STRING :
  1003.       case EXTENDED_GADGET_TYPE_INTEGER :
  1004.      activate_input_gadget(gl, data_entry);
  1005.      real_imsg = NULL;
  1006.      break;
  1007.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  1008.      sl  = data;
  1009.      min = sl->sl_Min;
  1010.      max = sl->sl_Max;
  1011.      num = sl->sl_Level;
  1012.      if (qualifier) {
  1013.         if ((LONG)num > (LONG)min) {
  1014.            num--;
  1015.         } else {
  1016.            real_imsg = NULL;
  1017.         }
  1018.      } else {
  1019.         if ((LONG)num < (LONG)max) {
  1020.            num++;
  1021.         } else {
  1022.            real_imsg = NULL;
  1023.         }
  1024.      }
  1025.      if (real_imsg) {
  1026.         sl->sl_Level = value = num;
  1027.         change_gadget(real_egad);
  1028.      }
  1029.      break;
  1030.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  1031.      sc  = data;
  1032.      min = sc->sc_Visible;
  1033.      max = sc->sc_Total;
  1034.      num = sc->sc_Top;
  1035.      if (qualifier) {
  1036.         if (num > 0) {
  1037.            num--;
  1038.         } else {
  1039.            real_imsg = NULL;
  1040.         }
  1041.      } else {
  1042.         if (num < (max - min)) {
  1043.            num++;
  1044.         } else {
  1045.            real_imsg = NULL;
  1046.         }
  1047.      }
  1048.      if (real_imsg) {
  1049.         sc->sc_Top = value = num;
  1050.         change_gadget(real_egad);
  1051.      }
  1052.      break;
  1053.       case EXTENDED_GADGET_TYPE_CYCLE :
  1054.      cy  = data;
  1055.      max = cy->cy_TextEntries;
  1056.      num = cy->cy_ActiveEntry;
  1057.      if (qualifier) {
  1058.         if (num > 0) {
  1059.            num--;
  1060.         } else {
  1061.            num = max - 1;
  1062.         }
  1063.      } else {
  1064.         if (num < (max - 1)) {
  1065.            num++;
  1066.         } else {
  1067.            num = 0;
  1068.         }
  1069.      }
  1070.      cy->cy_ActiveEntry = value = num;
  1071.      change_gadget(real_egad);
  1072.      break;
  1073.       case EXTENDED_GADGET_TYPE_COUNT :
  1074.      co  = data;
  1075.      min = co->co_Min;
  1076.      max = co->co_Max;
  1077.      num = co->co_Value;
  1078.      if (qualifier) {
  1079.         if ((LONG)num > (LONG)min) {
  1080.            num--;
  1081.         } else {
  1082.            real_imsg = NULL;
  1083.         }
  1084.      } else {
  1085.         if ((LONG)num < (LONG)max) {
  1086.            num++;
  1087.         } else {
  1088.            real_imsg = NULL;
  1089.         }
  1090.      }
  1091.      if (real_imsg) {
  1092.         co->co_Value = value = num;
  1093.         change_gadget(real_egad);
  1094.      }
  1095.      break;
  1096.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  1097.      lv   = data;
  1098.      min  = lv->lv_VisibleEntries;
  1099.      max  = lv->lv_ListEntries;
  1100.      num  = lv->lv_TopEntry;
  1101.      node = lv->lv_TopNode;
  1102.      if (qualifier) {
  1103.         if (num-- > 0) {
  1104.            node = node->ln_Pred;
  1105.         } else {
  1106.            real_imsg = NULL;
  1107.         }
  1108.      } else {
  1109.         if (++num < max && (max - num) >= min) {
  1110.            node = node->ln_Succ;
  1111.         } else {
  1112.            real_imsg = NULL;
  1113.         }
  1114.      }
  1115.      if (real_imsg) {
  1116.         lv->lv_TopNode  = node;
  1117.         lv->lv_TopEntry = value = num;
  1118.         change_gadget(real_egad);
  1119.         real_imsg = NULL;
  1120.      }
  1121.      break;
  1122.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  1123.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  1124.      pd  = data;
  1125.      min = pd->pd_ColorOffset;
  1126.      max = pd->pd_MaxColors;
  1127.      num = pd->pd_ActiveColor;
  1128.      if (qualifier) {
  1129.         if ((LONG)num > (LONG)min) {
  1130.            num--;
  1131.         } else {
  1132.            num = min + max - 1;
  1133.         }
  1134.      } else {
  1135.         if ((LONG)num < (LONG)(min + max - 1)) {
  1136.            num++;
  1137.         } else {
  1138.            num = min;
  1139.         }
  1140.      }
  1141.      pd->pd_ActiveColor = value = num;
  1142.      change_gadget(real_egad);
  1143.      break;
  1144.    }
  1145.    if (real_imsg) {
  1146.       imsg = create_intui_message(real_imsg, gl, data_entry, value);
  1147.    }
  1148.    return(imsg);
  1149. }
  1150.     /* Create special ISUP intui message */
  1151.  
  1152.    STATIC struct IntuiMessage *
  1153. create_intui_message(struct IntuiMessage  *real_imsg, struct GadgetList  *gl,
  1154.                          USHORT data_entry,    ULONG value)
  1155. {
  1156.    struct IntuiMessage  *imsg = NULL;
  1157.  
  1158.    if (!(imsg = AllocMem((LONG)(sizeof(struct IntuiMessage) +
  1159.      sizeof(struct IntuiMessage *)), (LONG)MEMF_PUBLIC | MEMF_CLEAR))) {
  1160.       imsg = real_imsg;
  1161.    } else {
  1162.       imsg->Class       = ISUP_ID;
  1163.       imsg->Code        = data_entry;
  1164.       imsg->IAddress    = (APTR)value;
  1165.       imsg->SpecialLink = (struct IntuiMessage *)gl;
  1166.       *(struct IntuiMessage **)(imsg + 1) = real_imsg;   /* real IntuiMessage direct after ISUP intuition message */
  1167.    }
  1168.    return(imsg);
  1169. }
  1170.     /* Get active gadget for given window */
  1171.  
  1172.    STATIC struct ExtendedGadget *
  1173. get_active_gadget(struct Window  *win)
  1174. {
  1175.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1176.    struct GadgetList          *gl;
  1177.    struct ExtendedGadget      *egad = NULL;
  1178.    USHORT i, count;
  1179.  
  1180.    ObtainSemaphore(&vg->vg_Semaphore);
  1181.    if (count = vg->vg_Count) {
  1182.       gl = (struct GadgetList *)vg->vg_MinList.mlh_Head;
  1183.       for (i = 0; i < count; i++) {
  1184.      if (gl->gl_Window == win && gl->gl_ActiveGadget) {
  1185.         egad = gl->gl_ActiveGadget;
  1186.         break;
  1187.      }
  1188.      gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1189.       }
  1190.    }
  1191.    ReleaseSemaphore(&vg->vg_Semaphore);
  1192.    return(egad);
  1193. }
  1194.     /* Get hot key gadget for given window */
  1195.  
  1196.    STATIC struct ExtendedGadget *
  1197. get_hot_key_gadget(struct Window  *win, USHORT hot_key)
  1198. {
  1199.    struct VisibleGadgetLists  *vg = &visible_gadget_lists;
  1200.    struct GadgetList          *gl;
  1201.    struct ExtendedGadget      *egad, *result_egad = NULL;
  1202.    USHORT i, j, count, data_entries;
  1203.    BOOL   found = FALSE;
  1204.  
  1205.    ObtainSemaphore(&vg->vg_Semaphore);
  1206.    if (count = vg->vg_Count) {
  1207.       hot_key = toupper(hot_key);
  1208.       gl = (struct GadgetList *)vg->vg_MinList.mlh_Head;
  1209.       for (i = 0; i < count && found == FALSE; i++) {
  1210.      if (gl->gl_Window == win) {
  1211.         data_entries = gl->gl_DataEntries;
  1212.         for (j = 0; j < data_entries && found == FALSE; j++) {
  1213.            egad = gl->gl_Gadgets[j];
  1214.            if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOT_KEY &&
  1215.                       toupper(egad->eg_Hotkey) == hot_key) {
  1216.           result_egad = egad;
  1217.           found       = TRUE;
  1218.            }
  1219.         }
  1220.      }
  1221.      gl = (struct GadgetList *)gl->gl_MinNode.mln_Succ;
  1222.       }
  1223.    }
  1224.    ReleaseSemaphore(&vg->vg_Semaphore);
  1225.    return(result_egad);
  1226. }
  1227.