home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff368.lzh / ListWindow / listwin_pak.c < prev    next >
C/C++ Source or Header  |  1990-08-15  |  24KB  |  964 lines

  1. /***************************************************************************
  2.  * listwin_pak.c -general-purpose dynamic list-window functions to make    *
  3.  *                programming alot easier.                                 *
  4.  *                (c) 1990 VIDEOWORKS Computer Applications                *
  5.  *                All rights reserved.                                     *
  6.  *                129 Orchard Avenue, Rocky Mount, VA 24151                *                                         *
  7.  *                (703) 483-8219 / 489-3863                                *
  8.  *                                                                         *
  9.  *                Designed and Developed by Paul T. Miller                 *
  10.  *                                                                         *
  11.  * Program Name:  N/A                                                      *
  12.  * Version:       1                                                        *
  13.  * Revision:      0                                                        *
  14.  *-------------------------------------------------------------------------*
  15.  * File: (listwin_pak.c) dynamic list-window package routines              *
  16.  *-------------------------------------------------------------------------*
  17.  * Modification History                                                    *
  18.  * Date     Author   Comment                                               *
  19.  * -------- ------   -------                                               *
  20.  * 06-13-90    PTM   Created.
  21.  * 06-14-90    PTM   Name selection, resizing, scrolling.
  22.  * 06-15-90    PTM   List Sorting. return selected name in a buffer+code
  23.  * 06-15-90    PTM   SHIFT+Key list indexing
  24.  * 06-18-90    PTM   Remove name gadgets - make MOUSEDOWN/position events
  25.  * 06-22-90    PTM   NameList structure/text pointer routines
  26.  * 06-23-90    PTM   Name adding/removing from name lists
  27.  ***************************************************************************/
  28.  
  29. #include <exec/types.h>
  30. #include <exec/memory.h>
  31. #include <devices/inputevent.h>
  32. #include <proto/intuition.h>
  33. #include <clib/macros.h>
  34. #include <ctype.h>
  35. #include "listwin_pak.h"
  36.  
  37. /* ListWindow Gadget constants */
  38. #define ARROW_WIDTH     16
  39. #define ARROW_HEIGHT    13
  40. #define NAME_GAD_HEIGHT 10
  41. #define SIZE_GAD_HEIGHT 8
  42.  
  43. #define PROP_ID         900
  44. #define ARROW_UP_ID     901
  45. #define ARROW_DOWN_ID   902
  46.  
  47. #define UP_ARROW        0x4c
  48. #define DOWN_ARROW      0x4d
  49. #define LEFT_ARROW      0x4f
  50. #define RIGHT_ARROW     0x4e
  51.  
  52. #define SHIFT_KEY       (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)
  53.  
  54. UWORD chip uparrow_data[1][13][1] = {
  55.     {
  56.         0xffff,0xc003,0xc183,0xc3c3,0xc7e3,0xcff3,0xdffb,0xc3c3,
  57.         0xc3c3,0xc3c3,0xc3c3,0xc003,0xffff
  58.     }
  59. };
  60.  
  61. UWORD chip downarrow_data[1][13][1] = {
  62.     {
  63.         0xffff,0xc003,0xc3c3,0xc3c3,0xc3c3,0xc3c3,0xdffb,0xcff3,
  64.         0xc7e3,0xc3c3,0xc183,0xc003,0xffff
  65.     }
  66. };
  67.  
  68. struct ConsoleDevice *ConsoleDevice = NULL;
  69. struct IOStdReq       ioreq;
  70.  
  71. InitListWindowPackage()
  72. {
  73.    if (OpenDevice("console.device", -1L, (struct IORequest *)&ioreq, 0L))
  74.       return(NULL);
  75.    ConsoleDevice = (struct ConsoleDevice *)ioreq.io_Device;
  76.  
  77.    return(1);
  78. }
  79.  
  80. void CloseListWindowPackage()
  81. {
  82.    if (ConsoleDevice) CloseDevice((struct IORequest *)&ioreq);
  83.    ConsoleDevice = NULL;
  84. }
  85.  
  86. struct Window *OpenListWindow(nw)
  87. struct NewWindow *nw;
  88. {
  89.    struct Window *win;
  90.  
  91.    win = OpenWindow(nw);
  92.    if (win)
  93.    {
  94.       if (MakeListWindow(win))
  95.          return(win);
  96.    }
  97.    return(NULL);
  98. }
  99.  
  100. MakeListWindow(win)
  101. struct Window *win;
  102. {
  103.    struct ListWindow *lw;
  104.    ULONG IDCMPflags;
  105.  
  106.    if (!win) return(NULL);
  107.  
  108.    /* make sure the correct IDCMP bits are set */
  109.    IDCMPflags = RAWKEY | MOUSEMOVE | GADGETUP | GADGETDOWN | MOUSEBUTTONS;
  110.    if (win->Flags & WINDOWSIZING)
  111.       IDCMPflags |= NEWSIZE;
  112.    if (win->Flags & WINDOWCLOSE)
  113.       IDCMPflags |= CLOSEWINDOW;
  114.  
  115.    IDCMPflags |= win->IDCMPFlags;
  116.  
  117.    ReportMouse(win, 1);
  118.    ModifyIDCMP(win, IDCMPflags);
  119.  
  120.    lw = (struct ListWindow *)AllocMem(LISTWINDOW_SIZE, MEMF_CLEAR);
  121.    if (!lw)
  122.    {
  123.       CloseListWindow(win);
  124.       return(NULL);
  125.    }
  126.    lw->Window = win;
  127.  
  128.    win->UserData = (BYTE *)lw;
  129.  
  130.    if (!AllocateListWinGads(lw))
  131.    {
  132.       CloseListWindow(win);
  133.       return(NULL);
  134.    }
  135.    return(1);
  136. }
  137.  
  138. void CloseListWindow(win)
  139. struct Window *win;
  140. {
  141.    if (win)
  142.    {
  143.       FreeListWindow(win);
  144.       CloseWindow(win);
  145.    }
  146. }
  147.  
  148. void FreeListWindow(win)
  149. struct Window *win;
  150. {
  151.    struct ListWindow *lw;
  152.  
  153.    if (win)
  154.    {
  155.       lw = (struct ListWindow *)win->UserData;
  156.       if (lw)
  157.       {
  158.          FreeListWinGads(lw);
  159.          if (lw->NameList) FreeNameList(lw->NameList);
  160.          FreeMem(lw, LISTWINDOW_SIZE);
  161.       }
  162.    }
  163. }
  164.  
  165. AllocateListWinGads(lw)
  166. struct ListWindow *lw;
  167. {
  168.    struct Gadget *gad;
  169.    struct Image *image;
  170.    struct PropInfo *pinfo;
  171.    SHORT barheight;
  172.  
  173.    if (!lw || !lw->Window) return(NULL);
  174.    barheight = lw->Window->BorderTop;
  175.  
  176.    /* allocate and initialize the up-arrow gadget */
  177.    gad = (struct Gadget *)AllocMem(sizeof(struct Gadget), MEMF_CLEAR);
  178.    if (!gad) return(NULL);
  179.  
  180.    gad->LeftEdge = -(ARROW_WIDTH-1);
  181.    gad->TopEdge = barheight - 1;
  182.    gad->Width = ARROW_WIDTH;
  183.    gad->Height = ARROW_HEIGHT;
  184.    gad->GadgetType = BOOLGADGET;
  185.    gad->Flags = GADGIMAGE|GADGHCOMP|GRELRIGHT;
  186.    gad->Activation = GADGIMMEDIATE|RELVERIFY;
  187.    gad->GadgetText = NULL;
  188.    gad->SelectRender = NULL;
  189.    gad->GadgetID = ARROW_UP_ID;
  190.  
  191.    lw->UpGad = gad;
  192.  
  193.    image = (struct Image *)AllocMem(sizeof(struct Image), MEMF_CLEAR);
  194.    if (!image) return(NULL);
  195.  
  196.    image->Width = ARROW_WIDTH;
  197.    image->Height = ARROW_HEIGHT;
  198.    image->Depth = 1;
  199.    image->ImageData = (USHORT *)&uparrow_data[0];
  200.    image->PlanePick = 0x01;
  201.  
  202.    lw->UpGad->GadgetRender = (APTR)image;
  203.  
  204.    /* allocate and initialize the down-arrow gadget */
  205.    gad = (struct Gadget *)AllocMem(sizeof(struct Gadget), MEMF_CLEAR);
  206.    if (!gad) return(NULL);
  207.  
  208.    movmem(lw->UpGad, gad, sizeof(struct Gadget));
  209.    gad->LeftEdge = -(ARROW_WIDTH-1);
  210.    gad->TopEdge = -ARROW_HEIGHT;
  211.    if (lw->Window->Flags & WINDOWSIZING)
  212.       gad->TopEdge -= SIZE_GAD_HEIGHT;
  213.    gad->Flags |= GRELBOTTOM;
  214.    gad->GadgetID = ARROW_DOWN_ID;
  215.  
  216.    lw->DownGad = gad;
  217.  
  218.    image = (struct Image *)AllocMem(sizeof(struct Image), MEMF_CLEAR);
  219.    if (!image) return(NULL);
  220.  
  221.    image->Width = ARROW_WIDTH;
  222.    image->Height = ARROW_HEIGHT;
  223.    image->Depth = 1;
  224.    image->ImageData = (USHORT *)&downarrow_data[0];
  225.    image->PlanePick = 0x01;
  226.  
  227.    lw->DownGad->GadgetRender = (APTR)image;
  228.  
  229.    /* allocate and initialize the proportional gadget */
  230.    gad = (struct Gadget *)AllocMem(sizeof(struct Gadget), MEMF_CLEAR);
  231.    if (!gad) return(NULL);
  232.  
  233.    gad->LeftEdge = -(ARROW_WIDTH-1);
  234.    gad->TopEdge = barheight + ARROW_HEIGHT - 1;
  235.    gad->Width = ARROW_WIDTH;
  236.    gad->Height = -(ARROW_HEIGHT*2 + barheight);
  237.    if (lw->Window->Flags & WINDOWSIZING)
  238.       gad->Height -= SIZE_GAD_HEIGHT;
  239.    gad->GadgetType = PROPGADGET;
  240.    gad->Flags = GRELRIGHT|GRELHEIGHT;
  241.    gad->Activation = GADGIMMEDIATE|FOLLOWMOUSE|RELVERIFY;
  242.    gad->GadgetText = NULL;
  243.    gad->SelectRender = NULL;
  244.    gad->GadgetID = PROP_ID;
  245.  
  246.    lw->PropGad = gad;
  247.  
  248.    /* allocate the PropGadget slider image */
  249.    image = (struct Image *)AllocMem(sizeof(struct Image), MEMF_CLEAR);
  250.    if (!image) return(NULL);
  251.  
  252.    lw->PropGad->GadgetRender = (APTR)image;
  253.  
  254.    pinfo = (struct PropInfo *)AllocMem(sizeof(struct PropInfo), MEMF_CLEAR);
  255.    if (!pinfo) return(NULL);
  256.  
  257.    pinfo->Flags = AUTOKNOB|FREEVERT;
  258.    pinfo->VertPot = 1;
  259.    pinfo->HorizBody = MAXBODY;
  260.    pinfo->VertBody = MAXBODY;
  261.  
  262.    lw->PropGad->SpecialInfo = (APTR)pinfo;
  263.  
  264.    lw->UpGad->NextGadget = lw->DownGad;
  265.    lw->DownGad->NextGadget = lw->PropGad;
  266.    lw->PropGad->NextGadget = NULL;
  267.  
  268.    AddGList(lw->Window, lw->UpGad, -1, 3, NULL);
  269.    RefreshGList(lw->UpGad, lw->Window, NULL, 3);
  270.  
  271.    return(1);
  272. }
  273.  
  274. void FreeListWinGads(lw)
  275. struct ListWindow *lw;
  276. {
  277.    struct Gadget *gad;
  278.    struct Image *image;
  279.    struct PropInfo *pinfo;
  280.  
  281.    if (!lw) return;
  282.  
  283.    RemoveGList(lw->Window, lw->UpGad, 3);
  284.  
  285.    if (gad = lw->UpGad)
  286.    {
  287.       image = (struct Image *)gad->GadgetRender;
  288.       if (image) FreeMem(image, sizeof(struct Image));
  289.       FreeMem(gad, sizeof(struct Gadget));
  290.       lw->UpGad = NULL;
  291.    }
  292.    if (gad = lw->DownGad)
  293.    {
  294.       image = (struct Image *)gad->GadgetRender;
  295.       if (image) FreeMem(image, sizeof(struct Image));
  296.       FreeMem(gad, sizeof(struct Gadget));
  297.       lw->DownGad = NULL;
  298.    }
  299.    if (gad = lw->PropGad)
  300.    {
  301.       image = (struct Image *)gad->GadgetRender;
  302.       if (image) FreeMem(image, sizeof(struct Image));
  303.       pinfo = (struct PropInfo *)gad->SpecialInfo;
  304.       if (pinfo) FreeMem(pinfo, sizeof(struct PropInfo));
  305.       FreeMem(gad, sizeof(struct Gadget));
  306.       lw->PropGad = NULL;
  307.    }
  308. }
  309.  
  310. InitListWindow(win, namelist, names, pos)
  311. struct Window *win;
  312. UBYTE **namelist;
  313. SHORT names, pos;
  314. {
  315.    struct ListWindow *lw;
  316.    struct NameList *nlist = NULL;
  317.  
  318.    lw = (struct ListWindow *)win->UserData;
  319.    if (!win || !lw) return(NULL);
  320.  
  321.    /* application supplied a string pointer array, so allocate a NameList */
  322.    if (namelist)
  323.    {
  324.       if (!lw->NameList)
  325.       {
  326.          nlist = AllocateNameList(names);
  327.          if (!nlist)
  328.             return(NULL);
  329.       }
  330.       else
  331.          nlist = lw->NameList;
  332.       SetNameList(nlist, namelist, names);
  333.    }
  334.  
  335.    lw->Overlap = 1;
  336.    lw->SlotHeight = NAME_GAD_HEIGHT;
  337.  
  338.    SetListWindowNameList(win, nlist, pos);
  339.  
  340.    return(1);
  341. }
  342.  
  343. void SetListWindowNameList(win, nlist, pos)
  344. struct Window *win;
  345. struct NameList *nlist;
  346. SHORT pos;
  347. {
  348.    struct ListWindow *lw;
  349.  
  350.    lw = (struct ListWindow *)win->UserData;
  351.    if (!win || !lw) return;
  352.  
  353.    lw->NameList = nlist;
  354.    lw->Selected = -1;
  355.  
  356.    if (lw->NameList)
  357.    {
  358.       lw->TotalNames = nlist->Names;
  359.       SortNameList(lw->NameList);
  360.    }
  361.    else
  362.       lw->TotalNames = 0;
  363.  
  364.    SetNameListPos(win, pos);
  365. }
  366.  
  367. void SetNameListPos(win, pos)
  368. struct Window *win;
  369. SHORT pos;
  370. {
  371.    struct ListWindow *lw;
  372.    SHORT i, x, y, w, h;
  373.    static struct IntuiText itext = {1, 0, JAM1, 1, 1, NULL, (UBYTE *)NULL, NULL};
  374.  
  375.    lw = (struct ListWindow *)win->UserData;
  376.  
  377.    if (!win || !lw) return;
  378.  
  379.    /* clear the name area */
  380.    x = win->BorderLeft;
  381.    y = win->BorderTop;
  382.    w = win->Width - ARROW_WIDTH - 6;
  383.    h = win->Height - y - 2;
  384.    lw->SlotWidth = w;                     /* find width of each name */
  385.    lw->VisibleNum = h / lw->SlotHeight;   /* find total number of slots */
  386.  
  387.    SetDrMd(win->RPort, JAM1);
  388.    FillBox(win->RPort, x, y, w, h, 0);
  389.  
  390.    /* now, if there are no names, just leave */
  391.    if (!lw->NameList || lw->NameList->Names == 0) return;
  392.  
  393.    lw->TopNum = pos;
  394.    lw->Hidden = MAX(lw->TotalNames - lw->VisibleNum, 0);
  395.  
  396.    if (lw->TopNum > lw->Hidden)
  397.       lw->TopNum = lw->Hidden;
  398.  
  399.    if (lw->TopNum < 0) lw->TopNum = 0;
  400.  
  401.    for (i = 0; i < lw->VisibleNum; i++)
  402.    {
  403.       h = i + lw->TopNum;     /* name offset within list */
  404.       y = (i * lw->SlotHeight) + win->BorderTop;   /* in-window position */
  405.  
  406.       if (i < lw->TotalNames && lw->NameList->NamePtrs[i])
  407.       {
  408.          itext.IText = lw->NameList->NamePtrs[h];
  409.          PrintIText(win->RPort, &itext, x, y);
  410.          if (i == lw->Selected)
  411.          {
  412.             SetDrMd(win->RPort, COMPLEMENT);
  413.             FillBox(win->RPort, x, y, lw->SlotWidth, lw->SlotHeight-1, 1);
  414.          }
  415.       }
  416.    }
  417.    SetListWindowPropGad(lw);
  418. }
  419.  
  420. void SetListWindowPropGad(lw)
  421. struct ListWindow *lw;
  422. {
  423.    UWORD VertBody, VertPot;
  424.  
  425.    if (!lw) return;
  426.  
  427.    if (lw->Hidden > 0 && lw->TotalNames > lw->Overlap)
  428.       VertBody = (UWORD)(((ULONG)(lw->VisibleNum - lw->Overlap) * MAXBODY)/
  429.          (lw->TotalNames - lw->Overlap));
  430.    else
  431.       VertBody = MAXBODY;
  432.  
  433.    if (lw->Hidden > 0)
  434.       VertPot = (UWORD)(((ULONG)lw->TopNum * MAXPOT) / lw->Hidden);
  435.    else
  436.       VertPot = 0;
  437.  
  438.    NewModifyProp(lw->PropGad, lw->Window, NULL, AUTOKNOB|FREEVERT,
  439.       MAXPOT, VertPot, MAXBODY, VertBody, 1);
  440. }
  441.  
  442. UWORD GetListWindowPropValue(win)
  443. struct Window *win;
  444. {
  445.    struct ListWindow *lw;
  446.    struct PropInfo *pinfo;
  447.    UWORD topline;
  448.  
  449.    lw = (struct ListWindow *)win->UserData;
  450.    if (!win || !lw) return(NULL);
  451.  
  452.    pinfo = (struct PropInfo *)lw->PropGad->SpecialInfo;
  453.  
  454.    topline = (UWORD)((((ULONG)lw->Hidden * pinfo->VertPot) + (MAXPOT/2))/
  455.       MAXPOT);
  456.  
  457.    return(topline);
  458. }
  459.  
  460. HandleListWindow(message, buffer)
  461. struct IntuiMessage *message;
  462. UBYTE *buffer;
  463. {
  464.    struct Window *win;
  465.    ULONG class;
  466.    USHORT code, qualifier;
  467.    struct Gadget *gadget;
  468.    struct ListWindow *lw;
  469.    SHORT num, mx, my;
  470.    USHORT step = 1;
  471.  
  472.    if (!message) return(LISTWINDOW_NONE);
  473.  
  474.    win = message->IDCMPWindow;
  475.    class = message->Class;
  476.    code = message->Code;
  477.    qualifier = message->Qualifier;
  478.    gadget = (struct Gadget *)message->IAddress;
  479.    mx = message->MouseX;
  480.    my = message->MouseY;
  481.  
  482.    lw = (struct ListWindow *)win->UserData;
  483.    if (!win || !lw) return(LISTWINDOW_NONE);
  484.  
  485.    if (qualifier & SHIFT_KEY)
  486.       step = lw->VisibleNum - 1;
  487.  
  488.    switch (class)
  489.    {
  490.       case CLOSEWINDOW:
  491.          return(CLOSE_LISTWINDOW);
  492.          break;
  493.       case RAWKEY:
  494.          if (!ConsoleDevice) break;
  495.          num = HandleListWindowRawKey(win, code, qualifier, (APTR)gadget);
  496.          if (num > -1)
  497.          {
  498.             strcpy(buffer, lw->NameList->NamePtrs[num + lw->TopNum]);
  499.             return(GOT_NAME);
  500.          }
  501.          break;
  502.       case NEWSIZE:
  503.          ResizeListWindow(win);
  504.          break;
  505.       case GADGETDOWN:
  506.          num = HandleListWindowGadgetDown(win, gadget, step);
  507.          if (num > -1)
  508.          {
  509.             strcpy(buffer, lw->NameList->NamePtrs[num + lw->TopNum]);
  510.             return(GOT_NAME);
  511.          }
  512.          break;
  513.       case MOUSEBUTTONS:
  514.          switch (code)
  515.          {
  516.             case SELECTDOWN:
  517.                num = GetListNameSlot(win, mx, my);
  518.                if (num > -1)
  519.                {
  520.                   strcpy(buffer, lw->NameList->NamePtrs[num + lw->TopNum]);
  521.                   return(GOT_NAME);
  522.                }
  523.                break;
  524.             case SELECTUP:
  525.                break;
  526.          }
  527.          break;
  528.    }
  529.    return(LISTWINDOW_NONE);
  530. }
  531.  
  532. SHORT HandleListWindowRawKey(win, code, qualifier, address)
  533. struct Window *win;
  534. USHORT code, qualifier;
  535. APTR address;
  536. {
  537.    struct ListWindow *lw;
  538.    LONG numchars;
  539.    UBYTE buffer[10];
  540.    USHORT step = 1;
  541.  
  542.    lw = (struct ListWindow *)win->UserData;
  543.  
  544.    if (!win || !lw) return(-1);
  545.  
  546.    buffer[0] = '\0';
  547.    numchars = ConvertRawKey(code, qualifier, address, buffer, 10);
  548.  
  549.    if (numchars == 0)
  550.       return(-1);
  551.  
  552.    if (numchars == 1)
  553.       return(HandleListWindowKey(win, buffer[0]));
  554.  
  555.    if (qualifier & SHIFT_KEY)
  556.       step = lw->VisibleNum - 1;
  557.  
  558.    switch (code)
  559.    {
  560.       case UP_ARROW:
  561.          return(HandleListWindowGadgetDown(win, lw->UpGad, step));
  562.          break;
  563.       case DOWN_ARROW:
  564.          return(HandleListWindowGadgetDown(win, lw->DownGad, step));
  565.          break;
  566.       case LEFT_ARROW:
  567.          if (lw->TopNum == 0)
  568.             break;
  569.          SetNameListPos(win, 0);
  570.          return(lw->Selected);
  571.          break;
  572.       case RIGHT_ARROW:
  573.          if (lw->TopNum == lw->TotalNames - lw->VisibleNum)
  574.             break;
  575.          SetNameListPos(win, (SHORT)(lw->TotalNames - lw->VisibleNum));
  576.          return(lw->Selected);
  577.          break;
  578.    }
  579.    return(-1);
  580. }
  581.  
  582. SHORT HandleListWindowKey(win, key)
  583. struct Window *win;
  584. UBYTE key;
  585. {
  586.    struct ListWindow *lw;
  587.    UBYTE *string, *string2;
  588.    USHORT i;
  589.  
  590.    lw = (struct ListWindow *)win->UserData;
  591.  
  592.    if (!win || !lw) return(-1);
  593.  
  594.    if (key && isupper(key))
  595.    {
  596.       string = lw->NameList->NamePtrs[lw->TopNum];     /* already there */
  597.       if (key == toupper(string[0]))
  598.          return(-1);
  599.  
  600.       for (i = 0; i < lw->TotalNames; i++)
  601.       {
  602.          string = lw->NameList->NamePtrs[i];
  603.  
  604.          if (key == toupper(string[0]))
  605.          {
  606.             SetNameListPos(win, i);
  607.             return(lw->Selected);
  608.             break;
  609.          }
  610.          if (i < lw->TotalNames - 1)
  611.          {
  612.             string2 = lw->NameList->NamePtrs[i+1];
  613.             if (toupper(string[0]) < key && key < toupper(string2[0]))
  614.                key = toupper(string2[0]);
  615.          }
  616.       }
  617.       /* if letter not in list, must be near end, so just show last page */
  618.       SetNameListPos(win, (SHORT)(lw->TotalNames - lw->VisibleNum));
  619.       return(lw->Selected);
  620.    }
  621.    return(-1);
  622. }
  623.  
  624. SHORT HandleListWindowGadgetDown(win, gad, step)
  625. struct Window *win;
  626. struct Gadget *gad;
  627. USHORT step;
  628. {
  629.    struct ListWindow *lw;
  630.    struct IntuiMessage *message;
  631.    ULONG class;
  632.    UBYTE mousemoved = NULL;
  633.    SHORT num;
  634.  
  635.    lw = (struct ListWindow *)win->UserData;
  636.  
  637.    if (!win || !lw || !gad) return(-1);
  638.    if (!lw->NameList) return(-1);
  639.  
  640.    switch (gad->GadgetID)
  641.    {
  642.       case ARROW_UP_ID:
  643.          if (lw->TopNum == 0)
  644.             return(-1);
  645.          lw->TopNum -= step;
  646.          SetNameListPos(win, lw->TopNum);
  647.          break;
  648.       case ARROW_DOWN_ID:
  649.          if (lw->TopNum == lw->TotalNames - lw->VisibleNum)
  650.             return(-1);
  651.          lw->TopNum += step;
  652.          SetNameListPos(win, lw->TopNum);
  653.          break;
  654.       case PROP_ID:
  655.          while (1)
  656.          {
  657.             WaitPort(win->UserPort);
  658.             while (message = (struct IntuiMessage *)GetMsg(win->UserPort))
  659.             {
  660.                class = message->Class;
  661.                ReplyMsg((struct Message *)message);
  662.  
  663.                switch (class)
  664.                {
  665.                   case GADGETUP:
  666.                      num = GetListWindowPropValue(win);
  667.                      if (num != lw->TopNum)
  668.                         SetNameListPos(win, num);
  669.                      return(lw->Selected);
  670.                      break;
  671.                   case MOUSEMOVE:
  672.                      mousemoved = 1;
  673.                      break;
  674.                }
  675.             }
  676.             if (mousemoved)
  677.             {
  678.                mousemoved = NULL;
  679.                num = GetListWindowPropValue(win);
  680.                if (num != lw->TopNum)
  681.                   SetNameListPos(win, num);
  682.             }
  683.          }
  684.          break;
  685.    }
  686.    return(lw->Selected);
  687. }
  688.  
  689. SHORT GetListNameSlot(win, mx, my)
  690. struct Window *win;
  691. SHORT mx, my;
  692. {
  693.    struct ListWindow *lw;
  694.    SHORT name;
  695.  
  696.    lw = (struct ListWindow *)win->UserData;
  697.  
  698.    if (!lw->NameList || lw->NameList->Names == 0)
  699.       return(-1);
  700.  
  701.    name = (my - win->BorderTop) / lw->SlotHeight;
  702.    if (name >= lw->TotalNames)
  703.       return(-1);
  704.  
  705.    /* same name clicked twice, so turn it off */
  706.    if (name == lw->Selected)
  707.    {
  708.       lw->Selected = -1;
  709.       SetNameListPos(win, lw->TopNum);
  710.       return(-1);
  711.    }
  712.  
  713.    lw->Selected = name;
  714.    SetNameListPos(win, lw->TopNum);
  715.    return(name);
  716. }
  717.  
  718. LONG ConvertRawKey(code, qualifier, address, buffer, buflen)
  719. USHORT code, qualifier;
  720. APTR address;
  721. UBYTE *buffer;
  722. USHORT buflen;
  723. {
  724.    static struct InputEvent ievent = {NULL, IECLASS_RAWKEY, 0, 0, 0};
  725.  
  726.    ievent.ie_Code = code;
  727.    ievent.ie_Qualifier = qualifier;
  728.    ievent.ie_position.ie_addr = *((APTR*)address);
  729.  
  730.    return(RawKeyConvert(&ievent, buffer, buflen, NULL));
  731. }
  732.  
  733. void ResizeListWindow(win)
  734. struct Window *win;
  735. {
  736.    struct ListWindow *lw;
  737.  
  738.    lw = (struct ListWindow *)win->UserData;
  739.  
  740.    if (!win || !lw) return;
  741.  
  742.    lw->Selected = -1;
  743.    SetNameListPos(win, lw->TopNum);
  744. }
  745.  
  746. struct NameList *AllocateNameList(names)
  747. SHORT names;
  748. {
  749.    struct NameList *nlist;
  750.  
  751.    nlist = (struct NameList *)AllocMem(NAMELIST_SIZE, MEMF_CLEAR);
  752.    if (!nlist) return(NULL);
  753.  
  754.    if (!AllocateNameListPtrs(nlist, names))
  755.    {
  756.       FreeMem(nlist, NAMELIST_SIZE);
  757.       return(NULL);
  758.    }
  759.    return(nlist);
  760. }
  761.  
  762. void FreeNameList(nlist)
  763. struct NameList *nlist;
  764. {
  765.    if (nlist)
  766.    {
  767.       FreeNameListPtrs(nlist);
  768.       FreeMem(nlist, NAMELIST_SIZE);
  769.    }
  770. }
  771.  
  772. /* allocate an array of pointers to text strings and set to the specified
  773.    NameList structure */
  774. AllocateNameListPtrs(nlist, names)
  775. struct NameList *nlist;
  776. ULONG names;
  777. {
  778.    UBYTE **array;
  779.  
  780.    array = (UBYTE **)AllocMem(sizeof(APTR)*names, MEMF_CLEAR);
  781.    if (!array)
  782.       return(NULL);
  783.  
  784.    nlist->NamePtrs = array;
  785.    nlist->Names = 0;
  786.    nlist->MaxNames = names;
  787.  
  788.    return(1);
  789. }
  790.  
  791. void FreeNameListPtrs(nlist)
  792. struct NameList *nlist;
  793. {
  794.    if (nlist->NamePtrs)
  795.    {
  796.       FreeMem(nlist->NamePtrs, sizeof(APTR)*nlist->MaxNames);
  797.       nlist->NamePtrs = NULL;
  798.       nlist->Names = 0;
  799.       nlist->MaxNames = 0;
  800.    }
  801. }
  802.  
  803. /* change the maximum number of the specified NameList's text pointers */
  804. ResizeNameList(nlist, size)
  805. struct NameList *nlist;
  806. ULONG size;
  807. {
  808.    UBYTE **array;
  809.    ULONG names;
  810.  
  811.    if (nlist->MaxNames == size)     /* same size! */
  812.       return(1);
  813.  
  814.    array = nlist->NamePtrs;      /* save pointer to old array */
  815.    names = nlist->Names;         /* ...and the used number of slots */
  816.  
  817.    nlist->NamePtrs = (UBYTE **)AllocMem(sizeof(APTR)*size, MEMF_CLEAR);
  818.    if (!nlist->NamePtrs)
  819.    {
  820.       nlist->NamePtrs = array;
  821.       return(NULL);
  822.    }
  823.    nlist->MaxNames = size;       /* set namelist to new number */
  824.    SetNameList(nlist, array, names);      /* now copy names from old array */
  825.    FreeMem(array, sizeof(APTR) * names);  /* free old array */
  826.  
  827.    return(1);
  828. }
  829.  
  830. void SetNameList(nlist, namelist, names)
  831. struct NameList *nlist;
  832. UBYTE **namelist;
  833. ULONG names;
  834. {
  835.    register int i;
  836.  
  837.    if (nlist && namelist)
  838.    {
  839.       for (i = 0; i < names; i++)
  840.       {
  841.          if (i >= nlist->MaxNames)
  842.          {
  843.             nlist->Names = nlist->MaxNames;
  844.             return;
  845.          }
  846.          nlist->NamePtrs[i] = namelist[i];
  847.       }
  848.       nlist->Names = names;
  849.    }
  850. }
  851.  
  852. void SortNameList(nlist)
  853. struct NameList *nlist;
  854. {
  855.    /* Lattice-C v5.04 built-in sort */
  856.    tqsort(nlist->NamePtrs, nlist->Names);
  857. }
  858.  
  859. void AddName(nlist, name)
  860. struct NameList *nlist;
  861. UBYTE *name;
  862. {
  863.    if (nlist->Names == nlist->MaxNames)
  864.    {
  865.       if (!ResizeNameList(nlist, nlist->MaxNames + 5))
  866.          return;
  867.    }
  868.    nlist->NamePtrs[nlist->Names] = name;
  869.    nlist->Names++;
  870.    SortNameList(nlist);
  871. }
  872.  
  873. void RemoveName(nlist, name)
  874. struct NameList *nlist;
  875. UBYTE *name;
  876. {
  877.    register int i;
  878.  
  879.    for (i = 0; i < nlist->Names; i++)
  880.       if (strcmp(nlist->NamePtrs[i], name) == NULL)
  881.       {
  882.          while (i < nlist->Names)
  883.          {
  884.             nlist->NamePtrs[i] = nlist->NamePtrs[i+1];
  885.             i++;
  886.          }
  887.          nlist->Names--;
  888.          SortNameList(nlist);
  889.          break;
  890.       }
  891. }
  892.  
  893. void AddListWindowName(win, name)
  894. struct Window *win;
  895. UBYTE *name;
  896. {
  897.    struct ListWindow *lw;
  898.  
  899.    lw = (struct ListWindow *)win->UserData;
  900.    if (!win || !lw) return;
  901.  
  902.    AddName(lw->NameList, name);
  903.  
  904.    lw->TotalNames = lw->NameList->Names;
  905.  
  906.    SetNameListPos(win, lw->TopNum);
  907. }
  908.  
  909. void RemoveListWindowName(win, name)
  910. struct Window *win;
  911. UBYTE *name;
  912. {
  913.    struct ListWindow *lw;
  914.  
  915.    lw = (struct ListWindow *)win->UserData;
  916.    if (!win || !lw) return;
  917.    if (!lw->NameList || lw->NameList->Names == 0) return;
  918.  
  919.    RemoveName(lw->NameList, name);
  920.  
  921.    lw->TotalNames = lw->NameList->Names;
  922.  
  923.    SetNameListPos(win, lw->TopNum);
  924. }
  925.  
  926. void SelectListWindowName(win, name)
  927. struct Window *win;
  928. UBYTE *name;
  929. {
  930.    struct ListWindow *lw;
  931.    register int i;
  932.  
  933.    lw = (struct ListWindow *)win->UserData;
  934.    if (!win || !lw) return;
  935.  
  936.    if (!lw->NameList || lw->NameList->Names == 0) return;
  937.  
  938.    if (name == NULL)
  939.       lw->Selected = -1;
  940.    else
  941.       for (i = 0; i < lw->TotalNames; i++)
  942.          if (strcmp(lw->NameList->NamePtrs[i], name) == NULL)
  943.          {
  944.             if (i > lw->VisibleNum)
  945.                lw->TopNum = i;
  946.             lw->Selected = i;
  947.             SetNameListPos(win, lw->TopNum);
  948.             break;
  949.          }
  950. }
  951.  
  952. void SortListWindowNames(win)
  953. struct Window *win;
  954. {
  955.    struct ListWindow *lw;
  956.  
  957.    lw = (struct ListWindow *)win->UserData;
  958.    if (!win || !lw) return;
  959.    if (!lw->NameList || lw->NameList->Names == 0) return;
  960.  
  961.    SortNameList(lw->NameList);
  962.    SetNameListPos(win, lw->TopNum);
  963. }
  964.