/*      GONE WITH THE WINDOWS

        by Melissa Jordan Grey and Todor Fay

        (c) 1989 Blue Ribbon Bakery

    Compile with Lattice or Aztec...
    Lattice: link with _main.o to avoid the extra console window
    Aztec: cc +L gone.c
           ln +C gone.o -lc32
           also make IntuitionBase global not extern! (see note below)
*/
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfxmacros.h>
#include <devices/input.h>
#include <devices/inputevent.h>

/* Power Windows generated definition of main window. */
static USHORT wImageData1[] = {
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x003E,0x0010,0x80CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x103E,0x0410,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8844,0x003E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x00BE,0x7F90,0x08CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8084,0x003E,0x1FD0,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x103E,0x07D7,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x003E,0x03D7,0xC0CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xFFFF,0xFFFF,0xFFCC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8024,0x00BE,0x0057,0xF8CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x203E,0x0057,0xFCCF,0xFFFF,0xFF80,
        0xC000,0x0019,0x9004,0x003E,0x1057,0xFCCC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x0057,0xFCCF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8104,0x403E,0x0257,0xFCCC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x0057,0xF8CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x013E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x003E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8085,0x003E,0x03D7,0xC0CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x013E,0x07D7,0x08CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8404,0x003E,0x1FD0,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x003E,0x7F90,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8404,0x043E,0x0011,0x08CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8024,0x403E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x2010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xFFFF,0xFFFF,0xFFCC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xFFEF,0x7F00,0x0000,0x0000,
        0x0000,0x0006,0x7FFB,0xEFC1,0xFBEF,0xFF30,0x0000,0x0000,
        0x0000,0x0006,0x77BB,0xFFC1,0xFFEF,0xFF30,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFF41,0x806F,0xF700,0x0000,0x0000,
        0x0000,0x0000,0x7F7B,0xFFC1,0xE02F,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xEFC1,0xF828,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xFC28,0x3F00,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xFFEF,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xFFEF,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x7FDB,0xFF41,0xFFA8,0x0700,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xDFC1,0xFFA8,0x0300,0x0000,0x0000,
        0x0000,0x0000,0x6FFB,0xFFC1,0xEFA8,0x0300,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xFFA8,0x0300,0x0000,0x0000,
        0x0000,0x0000,0x7EFB,0xBFC1,0xFDA8,0x0300,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xFFA8,0x0700,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFEC1,0xFFEF,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xFFEF,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x7F7A,0xFFC1,0xFC28,0x3F00,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFEC1,0xF828,0xF700,0x0000,0x0000,
        0x0000,0x0000,0x7BFB,0xFFC1,0xE02F,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0x806F,0xFF00,0x0000,0x0000,
        0x0000,0x0006,0x7BFB,0xFBC1,0xFFEE,0xF730,0x0000,0x0000,
        0x0000,0x0006,0x7FDB,0xBFC1,0xFFEF,0xFF30,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFFC1,0xDFEF,0xFF00,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};

static struct Image wImage1 = {
        0,0,
        121,31,
        2,
        wImageData1,
        0x0003,0x0000,
        NULL
};

static struct Gadget wGadget2 = {
        NULL,
        148,15,
        121,31,
        GADGHBOX+GADGHIMAGE+GADGIMAGE,
        RELVERIFY+GADGIMMEDIATE,
        BOOLGADGET,
        (APTR)&wImage1,
        NULL,
        NULL,
        NULL,
        NULL,
        2,
        NULL
};

static USHORT wImageData2[] = {
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xFE3E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xFE3F,0xFFFE,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xFE3E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xFE3E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xFC3F,0xFF90,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xFC3E,0x007E,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xF83E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xE03F,0xF010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xFFFF,0xFFFF,0xFFCC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFC,0x003E,0x0070,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFC4,0x003F,0xC010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x0C3E,0x3810,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8005,0x833E,0x0610,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x9864,0xC0FE,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x9864,0x603E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x9834,0x303E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x9834,0x183E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xC000,0x0019,0x981C,0x063E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x980C,0x003E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x9804,0x003E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x003E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0x8004,0x003E,0x0010,0x00CC,0x0000,0x0180,
        0xFFFF,0xFFF9,0x8004,0x003E,0x0010,0x00CF,0xFFFF,0xFF80,
        0xC000,0x0019,0xFFFF,0xFFFF,0xFFFF,0xFFCC,0x0000,0x0180,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0xFFFF,0xFFF9,0xFFFF,0xFFFF,0xFFFF,0xFFCF,0xFFFF,0xFF80,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFE00,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0006,0x7FFB,0xFE01,0xFFEE,0x0030,0x0000,0x0000,
        0x0000,0x0006,0x7FFB,0xFE00,0x0000,0x0030,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFE00,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFC01,0xFF80,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xFC00,0x006E,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xF800,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FFB,0xE001,0xF000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FF8,0x0000,0x0060,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x7FC0,0x0001,0xC000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0C00,0x3800,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0001,0x8300,0x0600,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x1860,0xC0C0,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x1860,0x6000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x1830,0x3000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x1830,0x1800,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x1818,0x0600,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x1808,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0006,0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,
        0x0000,0x0006,0x0000,0x0000,0x0000,0x0030,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
        0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000
};

static struct Image wImage2 = {
        0,0,
        121,31,
        2,
        wImageData2,
        0x0003,0x0000,
        NULL
};

static struct Gadget wGadget1 = {
        &wGadget2,
        16,15,
        121,31,
        GADGHBOX+GADGHIMAGE+GADGIMAGE,
        RELVERIFY+GADGIMMEDIATE,
        BOOLGADGET,
        (APTR)&wImage2,
        NULL,
        NULL,
        NULL,
        NULL,
        1,
        NULL
};

#define wGadgetList1 wGadget1

static struct NewWindow wNewWindowStructure1 = {
        118,24,
        284,52,
        0,1,
        GADGETDOWN+CLOSEWINDOW,
        WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH,
        &wGadget1,
        NULL,
        "Gone With The Windows",
        NULL,
        NULL,
        5,5,
        -1,-1,
        WBENCHSCREEN
};


/*      The Scrolling Pop Up Menu code starts here.  Feel free
        to cut it out and install it in your own application.
        Include the following copyright notice in your source code:

        ScrollingPopUpMenu (c) 1989 Blue Ribbon Bakery
*/

/*      For the Scrolling Pop Up Menu, we need a simple definition
        of a generic linked list node.
*/

struct ListNode {
    struct ListNode *next;
};

static void draw_arrows(rastport,width,height)

/*      This routine prints the two arrows that appear at the
        top and bottom of the menu.
*/

struct RastPort *rastport;
short width, height;

{
    static UWORD arrowdown[] =
        { 0x1c00,0x1c00,0xdd80,0x7f00,0x3e00,0x1c00,0x800 };
    static struct Image arrowdownimage = {0,0,9,7,1,&arrowdown[0],1,0x00,NULL,};
    static UWORD arrowup[] =
        { 0x800,0x1c00,0x3e00,0x7f00,0xdd80,0x1c00,0x1c00 };
    static struct Image arrowupimage = {0,0,9,7,1,&arrowup[0],1,0x00,NULL,};
    short center = width >> 1;
    DrawImage(rastport,&arrowupimage,center - 5,3);
    DrawImage(rastport,&arrowdownimage,center - 5,height - 10);
}

static draw_list(rastport,list,displayroutine,itemheight,itemwidth,count)

/*      This draws the visible section of the list.  Since this
        can not know what the elements of the list look like (this is
        a generic list handler,) a routine is supplied by the calling
        program that knows how to draw a given list item.  This
        routine is passed in the variable displayroutine.
*/

struct RastPort *rastport;
struct ListNode *list;
void (*displayroutine)();
short itemheight,itemwidth,count;

{
    short y;
    unsigned short index;
    y = 10;
    for (index = 0;index < count; index++) {
        SetAPen(rastport,1);
        SetBPen(rastport,1);
        SetOPen(rastport,1);
        SetDrMd(rastport,JAM2);
        RectFill(rastport,2,y,itemwidth-3,y+itemheight-1);
        if (list) {
            (*displayroutine)(rastport,list,y);
            list = list->next;
        }
        y += itemheight;
    }
}

static void complement_item(rastport,position,itemheight,itemwidth)

/*      This highlights a displayed list item by complementing all
        of the bits in the rectangle that the item is displayed in.
        To deselect, or remove the highlight, this routine is
        called a second time, and the complement operation returns
        the bits to normal.
*/

struct RastPort *rastport;
short position, itemheight, itemwidth;

{
    if (position < 0) return;
    position = (position * itemheight) + 10;
    BNDRYOFF(rastport);
    SetDrMd(rastport,COMPLEMENT);
    SetAPen(rastport,1);
    RectFill(rastport,2,position,itemwidth-3,position+itemheight-1);
}

list_len(top)

/*      Generic list handling rougine to return the length of a list.
*/

struct ListNode *top;

{
    unsigned long i;
    for(i=0;top;top = top->next) i++;
    return((long)i);
}

struct ListNode *item_in_list(top,index)

/*      Generic list handling rougine to return the item at index.
*/

struct ListNode *top;
long index;

{
    for (; index && top; index--) {
        top = top->next;
    }
    return(top);
}

static void send_false_button_up()

/*      This fools the input device into thinking a mouse button
        up event has happened.  It does this by sending a mouse
        up event into the input stream.
*/

{
    struct IOStdReq *ioreq;
    struct InputEvent event;
    struct MsgPort *ioport;
    ioport = (struct MsgPort *) CreatePort ("let's fool intuition",0);
    if (ioport) {
        ioreq = (struct IOStdReq *) CreateStdIO(ioport);
        if (ioreq) {
            if (!OpenDevice("input.device",0,ioreq,0)) {
                ioreq->io_Command = IND_WRITEEVENT;
                ioreq->io_Flags = 0;
                ioreq->io_Length = sizeof (struct InputEvent);
                ioreq->io_Data = (APTR) &event;
                event.ie_NextEvent = 0;
                event.ie_Class = IECLASS_RAWMOUSE;
                event.ie_X = 0;
                event.ie_Y = 0;
                event.ie_Code = IECODE_LBUTTON|IECODE_UP_PREFIX;
                DoIO(ioreq);
                CloseDevice(ioreq);
            }
            DeleteStdIO(ioreq);
        }
        DeletePort (ioport);
    }
}

struct ListNode *ScrollingPopUpMenu(screen,list,displayroutine,
    itemheight,itemwidth,count)

/*      This is the biggy.  Open a window and draw the menu in it.
        Wait for MOUSEMOVE, MOUSEBUTTONS and INTUITICKS events:

MOUSEMOVE. Read the position of the mouse and determine one of four scenarios:

        The mouse is outside the window.  Close the window down and leave,
        returning a NULL, or 0, pointer.

        The mouse is over one of the arrows.  If it just moved there from
        a highlighted item, deselect that item with the routine
        complement_item().

        The mouse is over the same item it was over last time.  Do nothing.

        The mouse has moved over a new item.  Select that item with
        the routine complement_item(). If it just moved there from
        a highlighted item, deselect that item with the routine
        complement_item().

MOUSEBUTTONS. The user has clicked on a mouse button.  Close the window and
        return the currently selected item, if such exists, or NULL for
        none selected (the mouse must be over an arrow.)

INTUITICKS. This message is only of importance if the mouse is over one
        of the arrows.  There is a variable, topdisplay, that points to
        the first item in the list that is displayed in the menu.  If
        the mouse is over the up arrow, topdisplay is changed to point
        to the item that precedes it in the list and the list is redrawn,
        scrolling it down one with a new item at the top.  If the mouse
        is over the down arrow, topdisplay is changed to point to the
        next item after it in the list and the list is redrawn, scrolling
        it up one with a new item at the bottom.
*/

struct Screen *screen;
struct ListNode *list;
void (*displayroutine)();
short itemheight,itemwidth,count;

{
    static struct NewWindow scrollNewWindowStructure = {
        0,0,10,10,0,1,
        MOUSEBUTTONS+MOUSEMOVE+INTUITICKS,
        ACTIVATE+NOCAREREFRESH+REPORTMOUSE,
        0,0,0,0,0,5,5,-1,-1,CUSTOMSCREEN
    };
    struct IntuiMessage *message;
    struct Window *window;
    struct ListNode *topdisplay = list;
    struct ListNode *activeitem;
/*    struct ListNode *item;*/
    short height;
    long class, code;
    short position, newposition;
    short mousex, mousey;
    short indent = 0;
    short scrolling = 0;
    short left, top;
    if (!list) return(0);
    if (!list->next) return(list);
    if (list_len(list) < count) count = list_len(list);
    height = (itemheight * count) + 20;
    top = screen->MouseY - (height >> 1);
    if (top < 0) top = 0;
    else if ((top + height) > screen->Height)
        top = screen->Height - height;
    left = screen->MouseX - (itemwidth >> 1);
    if (left < 0) left = 0;
    else if ((left + itemwidth) > screen->Width)
        left = screen->Width - itemwidth;
    scrollNewWindowStructure.Width = itemwidth;
    scrollNewWindowStructure.Height = height;
    scrollNewWindowStructure.TopEdge = top;
    scrollNewWindowStructure.LeftEdge = left;
    scrollNewWindowStructure.Screen = screen;
    send_false_button_up();
    window =(struct Window *) OpenWindow(&scrollNewWindowStructure);
    if (window) {
        position = window->MouseY - 10;
        position = position / itemheight;
        activeitem = (struct ListNode *) item_in_list(topdisplay,position);
        draw_list(window->RPort,list,displayroutine,itemheight,itemwidth,count);
        complement_item(window->RPort,position,itemheight,itemwidth);
        draw_arrows(window->RPort,itemwidth,height);
        for (;;) {
            message = 0;
            while (!message) {
                WaitPort(window->UserPort);
                message = (struct IntuiMessage *) GetMsg(window->UserPort);
            }
            class = message->Class;
            code = message->Code;
            mousex = message->MouseX;
            mousey = message->MouseY;
            ReplyMsg(message);
            if (class == MOUSEMOVE) {
                if ((mousex < 0) || (mousex > itemwidth) ||
                  (mousey < 0) || (mousey > height)) {
                    activeitem = 0;
                    break;
                }
                if (mousey < 10) {
                    if (activeitem) {
                        complement_item(window->RPort,position,itemheight,itemwidth);
                        activeitem = 0;
                        position = -1;
                    }
                    scrolling = 1;
                }
                else if (mousey > (height - 10)) {
                    if (activeitem) {
                        complement_item(window->RPort,position,itemheight,itemwidth);
                        activeitem = 0;
                        position = -1;
                    }
                    scrolling = 2;
                }
                else {
                    scrolling = 0;
                    newposition = (mousey - 10) / itemheight;
                    if ((newposition != position) && (newposition < count)
                        && (newposition >= 0)) {
                        if (position >= 0)
                            complement_item(window->RPort,position,
                                itemheight,itemwidth);
                        activeitem = (struct ListNode *)
                            item_in_list(topdisplay,newposition);
                        position = newposition;
                        complement_item(window->RPort,position,
                            itemheight,itemwidth);
                    }
                }
            }
            else if (class == MOUSEBUTTONS) {
                break;
            }
            else if (class == INTUITICKS) {
                if (scrolling == 1) {
                    if (indent) {
                        indent--;
                        topdisplay = item_in_list(list,indent);
                        draw_list(window->RPort,topdisplay,displayroutine,
                            itemheight,itemwidth,count);
                    }
                }
                else if (scrolling == 2) {
                    if (list_len(topdisplay) > count) {
                        indent++;
                        topdisplay = topdisplay->next;
                        draw_list(window->RPort,topdisplay,displayroutine,
                            itemheight,itemwidth,count);
                    }
                }
            }
        }
        CloseWindow(window);
    }
    return(activeitem);
}

/*      End of ScrollingPopUpMenu code.
*/

void draw_window_title(rastport,window,y)

/*      This is the routine supplied by Gone With The Windows
        that draws one window's title into the menu.  This routine
        is passed to ScrollingPopUpMenu() and used to draw the
        menu items.
*/

struct RastPort *rastport;
struct Window *window;
short y;

{
    if (window->Title) {
        SetAPen(rastport,2);
        Move(rastport,2,y+6);
        Text(rastport,window->Title,strlen(window->Title));
    }
}
/* Aztec users uncomment the following line, and comment the one after. */
/* struct IntuitionBase *IntuitionBase; */
extern struct IntuitionBase *IntuitionBase;
long GfxBase;

main()

/*      The main program.  Open an Intuition window in Workbench
        with two gadgets, one to send a window to the front, the
        second to send it to the back.

        When a gadget is clicked on, call ScrollingPopUpMenu() and
        pass it the list of Workbench windows.  If the user selects
        one of the windows, either call WindowToFront(window) or
        WindowToBack(window), depending on which gadget was clicked.
*/

{
    struct IntuiMessage *message;
    struct Window *window;
    struct Window *selectwindow;
    long class;  /* code*/
    struct Gadget *gadget;
    IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",0);
    GfxBase = OpenLibrary("graphics.library",0);
    window =(struct Window *) OpenWindow(&wNewWindowStructure1);
    if (window) {
        for (;;) {
            message = 0;
            while (!message) {
                WaitPort(window->UserPort);
                message = (struct IntuiMessage *) GetMsg(window->UserPort);
            }
            class = message->Class;
            gadget = (struct Gadget *) message->IAddress;
            ReplyMsg(message);
            if (class == CLOSEWINDOW) break;
            else if (class == GADGETDOWN) {
                selectwindow = (struct Window *)
                    ScrollingPopUpMenu(window->WScreen,
                        window->WScreen->FirstWindow,
                        draw_window_title,8,100,4);
                if (gadget->GadgetID == 1) {
                    if (selectwindow) WindowToFront(selectwindow);
                }
                else if (gadget->GadgetID == 2) {
                    if (selectwindow) WindowToBack(selectwindow);
                }
            }
        }
        CloseWindow(window);
    }
}
