#include "sysheaders.h"
#include "cdpanel.h"
#include "CompactPlayer.h"

/********************************************************
 * Main GUI
 */

#define CDPanelObject   NewObject( CDPanelClass, NULL /* ) open parentheses annoy */

struct Gadget *GList[GG_MAX];

struct Screen *Scr;
struct DrawInfo *Dri;
struct Window *Win;
struct Menu *MyMenuStrip;
APTR VisInfo;
Object *WinObj;
struct Gadget *MainLayout;
STRPTR Screen;

static UWORD chip forwardData[26] =
{
    /* Plane 0 */
    0x0000,0x0000,0x0000,0x0000,0x0410,0x0000,0x0618,0x0000,
    0x071C,0x0000,0x079E,0x0000,0x07DF,0x0000,0x079E,0x0000,
    0x071C,0x0000,0x0618,0x0000,0x0410,0x0000,0x0000,0x0000,
    0x0000,0x0000
};

static struct Image ForwardButton =
{
    0, 0,      /* LeftEdge, TopEdge */
    20, 13, 1,  /* Width, Height, Depth */
    forwardData,    /* ImageData */
    0x0001, 0x0000, /* PlanePick, PlaneOnOff */
    NULL        /* NextImage */
};

static UWORD chip playData[26] =
{
    /* Plane 0 */
    0x0000,0x0000,0x0000,0x0000,0x1003,0xDE00,0x1C03,0xDE00,
    0x1F03,0xDE00,0x1FC3,0xDE00,0x1FF3,0xDE00,0x1FC3,0xDE00,
    0x1F03,0xDE00,0x1C03,0xDE00,0x1003,0xDE00,0x0000,0x0000,
    0x0000,0x0000
};

static struct Image PlayButton =
{
    0, 0,      /* LeftEdge, TopEdge */
    26, 13, 1,  /* Width, Height, Depth */
    playData,   /* ImageData */
    0x0001, 0x0000, /* PlanePick, PlaneOnOff */
    NULL        /* NextImage */
};

static UWORD chip rewindData[26] =
{
    /* Plane 0 */
    0x0000,0x0000,0x0000,0x0000,0x0082,0x0000,0x0186,0x0000,
    0x038E,0x0000,0x079E,0x0000,0x0FBE,0x0000,0x079E,0x0000,
    0x038E,0x0000,0x0186,0x0000,0x0082,0x0000,0x0000,0x0000,
    0x0000,0x0000
};

static struct Image RewindButton =
{
    0, 0,      /* LeftEdge, TopEdge */
    20, 13, 1,  /* Width, Height, Depth */
    rewindData, /* ImageData */
    0x0001, 0x0000, /* PlanePick, PlaneOnOff */
    NULL        /* NextImage */
};

static UWORD chip stopData[26] =
{
    /* Plane 0 */
    0x0000,0x0000,0x0000,0x0000,0x1FF0,0x2000,0x1FF0,0x7000,
    0x1FF0,0xF800,0x1FF1,0xFC00,0x1FF3,0xFE00,0x1FF0,0x0000,
    0x1FF3,0xFE00,0x1FF3,0xFE00,0x1FF3,0xFE00,0x0000,0x0000,
    0x0000,0x0000
};

static struct Image StopButton =
{
    0, 0,      /* LeftEdge, TopEdge */
    26, 13, 1,  /* Width, Height, Depth */
    stopData,   /* ImageData */
    0x0001, 0x0000, /* PlanePick, PlaneOnOff */
    NULL        /* NextImage */
};

typedef enum { M_SelDev = 1, M_EditTitles, M_Iconify, M_Quit } MenuIDs;

struct NewMenu CompactMenu[] =
{
    NM_TITLE,   MENU_PROJECT,	NULL, 0, 0, NULL,
    NM_ITEM,    MENU_DEVICE,    NULL,  0, 0, (APTR)M_SelDev,
    NM_ITEM,    MENU_TITLES,    NULL,  0, 0, (APTR)M_EditTitles,
    NM_ITEM,    NM_BARLABEL,	NULL, 0, 0, NULL,
    NM_ITEM,    MENU_ICONIFY,	NULL,  0, 0, (APTR)M_Iconify,
    NM_ITEM,    MENU_QUIT,		NULL,  0, 0, (APTR)M_Quit,
    NM_END,     NULL,           NULL, 0, 0, NULL
};

struct TextAttr CompactAttr = { NULL, 0, FS_NORMAL, FPF_PROPORTIONAL };
struct TextAttr PanelAttr = { NULL, 0, FS_NORMAL, 0L };
struct TextFont *CompactFont;
struct TextFont *PanelFont;
struct TextFont *ScreenFont;

struct List dummyList;

/* handler functions for the buttons, since I want to act on them from
 * rawkey messages too. Gadgets don't support rawkey command keys (as of yet
 * anyway) because it is generally a bad practise to bind a rawkey to a gadget. */
static void
SeekCD(ULONG id)
{
  /* notifications from the rewind/fast forward buttons */
    ULONG status;
    static struct timeval tv1, tv2, tv3;

    GetSysTime(&tv1);
    tv3 = tv1;
    SubTime(&tv3, &tv2);

    GetAttr(CDPANEL_Status, GList[G_Panel], &status);

    if ((status == CDP_PLAYING || status == CDP_SEEKING)
        && (tv3.tv_secs || tv3.tv_micro >= 190000))
    {
        tv2 = tv1;                     /* only seek four times per second */
        switch (id)
         {
         case G_Backward:
             CD_Seek(-2);
             break;

         case G_Forward:
             CD_Seek(2);
             break;
         }
        if (status == CDP_PLAYING)
            SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_SEEKING, TAG_END);
    }
}

static void
PlayCD(void)
{
    ULONG status;

    GetAttr(CDPANEL_Status, GList[G_Panel], &status);

    if (status == CDP_PLAYING || status == CDP_SEEKING)
    {
        SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_PAUSED, TAG_END);
        CD_PauseResume(0x00);
    }
    else if (status == CDP_PAUSED)
    {
        SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_PLAYING, TAG_END);
        CD_PauseResume(0x01);
    }
    else if (status == CDP_STOPPED)
    {
        ULONG track;

        SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_PLAYING, TAG_END);
        GetAttr(LISTBROWSER_Selected, GList[G_List], &track);
        if (track++ > 100)
            track = 1;
        CD_Play(track);
        AbortIO(TimerIO);
    }
    else if (status == CDP_EJECTED || status == CDP_EMPTY)
    {
        CD_Eject(0x00);
        Delay(20);                     /* give it a chance to settle. I really hate these kind of things */
        if (Tracks = CD_ReadTOC())
            CD_Play(1);
    }
}

static void
StopCD(void)
{
    ULONG status;

    GetAttr(CDPANEL_Status, GList[G_Panel], &status);

    JustStarted = FALSE;

    if (status == CDP_STOPPED || status == CDP_EMPTY || status == CDP_EJECTED)
    {
        SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_EJECTED, TAG_END);
        CD_Eject(0x01);
    }
    else
    {
        SetGadgetAttrs(GList[G_List], Win, NULL, LISTBROWSER_Selected, ~0, TAG_END);
        SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_STOPPED, TAG_END);
        CD_Stop();
        AbortIO(TimerIO);
    }
}

static void
SelectCD(LONG dir)
{
    LONG track;
    ULONG status;

    GetAttr(CDPANEL_Track,  GList[G_Panel], (ULONG *) & track);
    GetAttr(CDPANEL_Status, GList[G_Panel], &status);

    if (dir > 0)
    {
         if (track < 100)
         {
             track++;
             if (track > Tracks)
                 track = Tracks - 1;
         }
         else
             track = 1;
    }
    else
    {
        if (track > 100)
            track = Tracks;
        track--;
        if (track < 1)
            track = 1;
    }
    SetGadgetAttrs(GList[G_List], Win, NULL, LISTBROWSER_Selected, track-1, LISTBROWSER_MakeVisible, track-1, TAG_END);
    SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Track, track, TAG_END);

    if (status == CDP_PLAYING || status == CDP_SEEKING)
    {
         CD_Play(track);
         AbortIO(TimerIO);
    }
}

static struct Hook IDCMPHook;

static ULONG __asm __saveds
IDCMPHookFunc(register __a0 struct Hook * hook, register __a2 Object * WinObj, register __a1 struct IntuiMessage *msg)
{
    /* this function is hooked from windowclass to grab some IDCMP messages */

    switch (msg->Class)
    {
    case IDCMP_IDCMPUPDATE:
    {
        ULONG id = GetTagData(GA_ID, 0, msg->IAddress);

        if (FindTagItem(GA_Selected, msg->IAddress) && (id == G_Backward || id == G_Forward))
        {
            SeekCD(id);
        }
        break;
    }

    case IDCMP_RAWKEY:
        switch (msg->Code)
        {
        case 0x43:  /* enter */
        case 0x44:  /* return */
            if (!(msg->Qualifier & IEQUALIFIER_REPEAT))
            {
                DoGadgetMethod(GList[G_Stop], Win, NULL, GM_KEYACTIVE, NULL, msg, (ULONG)'\n' );
                StopCD();
            }
            break;
        case 0xc3:
        case 0xc4:
            DoGadgetMethod(GList[G_Stop], Win, NULL, GM_KEYINACTIVE, NULL, msg, (ULONG)'\n', 0 );
            break;

        case 0x40:  /* space */
            if (!(msg->Qualifier & IEQUALIFIER_REPEAT))
            {
                DoGadgetMethod(GList[G_Play], Win, NULL, GM_KEYACTIVE, NULL, msg, (ULONG)' ' );
                PlayCD();
            }
            break;
        case 0xc0:
            DoGadgetMethod(GList[G_Play], Win, NULL, GM_KEYINACTIVE, NULL, msg, (ULONG)' ', 0 );
            break;

        case 0x4f:  /* cursor left */
            DoGadgetMethod(GList[G_Backward], Win, NULL, GM_KEYACTIVE, NULL, msg, (ULONG)'<' );
            SeekCD(G_Backward);
            break;

        case 0xcf:  /* cursor left (keyup)*/
            SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_PLAYING, TAG_END);
            DoGadgetMethod(GList[G_Backward], Win, NULL, GM_KEYINACTIVE, NULL, msg, (ULONG)'>', 0 );
            break;

        case 0x4e:  /* cursor right */
            DoGadgetMethod(GList[G_Forward], Win, NULL, GM_KEYACTIVE, NULL, msg, (ULONG)'>' );
            SeekCD(G_Forward);
            break;

        case 0xce:  /* cursor right (keyup) */
            SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_PLAYING, TAG_END);
            DoGadgetMethod(GList[G_Forward], Win, NULL, GM_KEYINACTIVE, NULL, msg, (ULONG)'>', 0 );
            break;

        case 0x4c:  /* cursor up */
            SelectCD(-1);
            break;

        case 0x4d:  /* cursor down */
            SelectCD(+1);
            break;

        case 0x45|0x80: /* escape up */
            done = TRUE;
            break;
        }
        break;
    }
    return 0;
}

struct Gadget *
CreateMainLayout( void )
{
    struct Image *i;

    return HGroupObject, Offset(1,1,1,1), Spacing(1),
        GA_TextAttr, & CompactAttr,
        GA_DrawInfo, Dri,
        LAYOUT_DeferLayout, TRUE,
        LAYOUT_AddChild, VGroupObject, Spacing(1),

            /* Layout hierarchies are so hard to explain.. we have the
             * window split to the status panel side and the listview side,
             * with four buttons below the status panel. */

            StartMember, GList[G_Panel] = CDPanelObject,
                CDPANEL_Status, CDP_EMPTY,
                GA_TextAttr, & PanelAttr,
                End,

            StartHGroup,
                LAYOUT_SpaceInner, FALSE,

                StartMember, GList[G_Backward] = ButtonObject,
                    GA_Image, i = & RewindButton,
                    GA_RelVerify, TRUE,
                    GA_ID, G_Backward,
                    ICA_TARGET, ICTARGET_IDCMP,
                    BUTTON_FillPen, Dri->dri_Pens[BACKGROUNDPEN],
                    CLASSACT_CommKey, "<",
                    End,
                    CHILD_MinWidth, i->Width,
                    CHILD_WeightMinimum, TRUE,

                StartMember, GList[G_Play] = ButtonObject,
                    GA_Image, i = & PlayButton,
                    GA_RelVerify, TRUE,
                    GA_ID, G_Play,
                    BUTTON_FillPen, Dri->dri_Pens[BACKGROUNDPEN],
                    End,
                    CHILD_MinWidth, i->Width,
                    CHILD_WeightMinimum, TRUE,

                StartMember, GList[G_Forward] = ButtonObject,
                    GA_Image, i = & ForwardButton,
                    GA_RelVerify, TRUE,
                    GA_ID, G_Forward,
                    ICA_TARGET, ICTARGET_IDCMP,
                    BUTTON_FillPen, Dri->dri_Pens[BACKGROUNDPEN],
                    CLASSACT_CommKey, ">",
                    End,
                    CHILD_MinWidth, i->Width,
                    CHILD_WeightMinimum, TRUE,

                StartMember, GList[G_Stop] = ButtonObject,
                    GA_Image, i = & StopButton,
                    GA_RelVerify, TRUE,
                    GA_ID, G_Stop,
                    BUTTON_FillPen, Dri->dri_Pens[BACKGROUNDPEN],
                    End,
                    CHILD_MinWidth, i->Width,
                    CHILD_WeightMinimum, TRUE,
                End,
                CHILD_WeightedHeight, 0,
            End,
            CHILD_WeightedWidth, 0,

        StartVGroup, Spacing(1),

            /* This is the listview group, with two buttons above it */

            StartHGroup, Spacing(1),
                LAYOUT_EvenSize, TRUE,

                StartMember, GList[G_Titles] = ButtonObject,
                    GA_Text, GS(B_TITLES),
                    GA_TextAttr, & CompactAttr,
                    GA_RelVerify, TRUE,
                    GA_ID, G_Titles,
                    End,

                StartMember, GList[G_Program] = ButtonObject,
                    GA_Text, GS(B_PROGR),
                    GA_TextAttr, & CompactAttr,
                    GA_RelVerify, TRUE,
                    GA_ID, G_Program,
                    End,
                End,
                /* force the button smaller than it tells is the minimum size.
                 * This gets rid of a few pixels that aren't needed, to really
                 * minimize the layout.. It's called _Compact_Player, after all.
                 */
                CHILD_WeightedHeight, 0,

            StartMember, GList[G_List] = ListBrowserObject,
                LISTBROWSER_Labels, &dummyList,
                LISTBROWSER_VerticalProp, FALSE,
                LISTBROWSER_ShowSelected, TRUE,
                GA_ReadOnly, TRUE,
                GA_TextAttr, & CompactAttr,
                GA_RelVerify, TRUE,
                GA_ID, G_List,
                End,
            End,
        End;
}

struct Gadget *
CreateZippedLayout( void )
{
    memset(&GList[G_Panel], 0, (ULONG)&GList[GG_MAX1]-(ULONG)&GList[G_Panel]);

    return HGroupObject,
        GA_DrawInfo, Dri,
        LAYOUT_DeferLayout, TRUE,
        LAYOUT_FixedHoriz, FALSE,
        LAYOUT_FixedVert, FALSE,

        StartMember, GList[G_Panel] = CDPanelObject,
            CDPANEL_NoBorder, TRUE,
            CDPANEL_Status, CDP_EMPTY,
            GA_TextAttr, & PanelAttr,
            End,

        End;
}

struct Window *
OpenMainWindow(ULONG X, ULONG Y)
{
    if (!ButtonBase) /* force it open */
        return NULL;

    if (Win)
        return Win;

    NewList( &dummyList );

    if (!(Scr = LockPubScreen(Screen)))
        Scr = LockPubScreen(NULL);

    if (Scr)
    {
        ScreenFont = OpenFont(Scr->Font);

        if (!CompactAttr.ta_Name)
        {
            CompactAttr = *Scr->Font;
        }
        if (!PanelAttr.ta_Name)
        {
            PanelAttr.ta_Name = GfxBase->DefaultFont->tf_Message.mn_Node.ln_Name;
            PanelAttr.ta_YSize = GfxBase->DefaultFont->tf_YSize;
        }

        if ((CompactFont = OpenDiskFont( &CompactAttr )) && (PanelFont = OpenDiskFont( &PanelAttr )))
        {
            if ((Dri = GetScreenDrawInfo(Scr)) && (VisInfo = GetVisualInfo(Scr, TAG_END)))
            {
                if ((MyMenuStrip = CreateMenus( CompactMenu, TAG_END )) &&
                    LayoutMenus( MyMenuStrip, VisInfo, GTMN_NewLookMenus, TRUE, TAG_END))
                {
                    struct IBox ZoomSize;

                    MainLayout = CreateZippedLayout();

                    LayoutLimits( MainLayout, (struct LayoutLimits *)&ZoomSize, NULL, Scr );
                    ZoomSize.Top     = -1;
                    ZoomSize.Left    = -1;
                    ZoomSize.Width  += Scr->WBorLeft + Scr->WBorRight + 2;
                    ZoomSize.Height += Scr->WBorTop + ScreenFont->tf_YSize + 1 + Scr->WBorBottom + 2;

                    DisposeObject( MainLayout );

                    MainLayout = CreateMainLayout();

                    if (MainLayout)
                    {
                        struct DiskObject *icon = NULL;

                        IDCMPHook.h_Entry = (HOOKFUNC)IDCMPHookFunc;
                        IDCMPHook.h_SubEntry = NULL;
                        IDCMPHook.h_Data = NULL;

                        if (_WBenchMsg)
                            icon = GetDiskObject( _WBenchMsg->sm_ArgList->wa_Name );
                        if (!icon)
                            icon = GetDiskObject( "PROGDIR:CompactPlayer" );

                        if (icon)
                        {
                            icon->do_CurrentY = icon->do_CurrentX = NO_ICON_POSITION;
                        }

                        if (WinObj = WindowObject,
                                WA_DepthGadget,     TRUE,
                                WA_DragBar,         TRUE,
                                WA_CloseGadget,     TRUE,
                                WA_Activate,        TRUE,
                                WA_Zoom,            &ZoomSize,
                                WA_Top,             Y,
                                WA_Left,            X,
                                WA_PubScreen,       Scr,
                                WA_Title,           GS(COMPACTPLAYER),
                                WA_ScreenTitle,     GS(TITLE_COPYRIGHT),
                                WA_AutoAdjust,      TRUE,
                                WINDOW_Layout,      MainLayout,
                                WINDOW_IDCMPHook,   &IDCMPHook,
                                WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_RAWKEY,
                                WA_IDCMP,           IDCMP_IDCMPUPDATE | IDCMP_RAWKEY,
                                WINDOW_MenuStrip,   MyMenuStrip,
                                WINDOW_AppPort,     AppPort,
                                WINDOW_SharedPort,  WinPort,
                                /* windowclass will free this */
                                WINDOW_Icon,        icon,
                                WINDOW_IconifyGadget, TRUE,
                                TAG_END))
                        {
                            Win = CA_OpenWindow(WinObj);

                            return Win;
                        }
                        DisposeObject(MainLayout);
                        MainLayout = NULL;
                    }
                    ErrorMsg(GS(GUI_FAIL));
                }
            }
        }
        else
            ErrorMsg(GS(FONTS_FAIL));
    }
    return NULL;
}

void
CloseMainWindow(void)
{
    if (TrackList)
    {
        SetGadgetAttrs(GList[G_List], Win, NULL, LISTBROWSER_Labels, ~0, TAG_END);
        FreeBrowserNodes(TrackList);
        TrackList = NULL;
    }
    if (WinObj)
    {
        DisposeObject(WinObj);
        MainLayout = NULL;
        WinObj = NULL;
        Win = NULL;
        memset(&GList[G_Panel], 0, (ULONG)&GList[GG_MAX1]-(ULONG)&GList[G_Panel]);
    }
    if (MyMenuStrip)
    {
        FreeMenus(MyMenuStrip);
        MyMenuStrip = NULL;
    }
    if (VisInfo)
    {
        FreeVisualInfo(VisInfo);
        VisInfo = NULL;
    }
    if (Dri)
    {
        FreeScreenDrawInfo(Scr, Dri);
        Dri = NULL;
    }
    if (Scr)
    {
        UnlockPubScreen(0, Scr);
        Scr = NULL;
    }
    if (CompactFont)
    {
        CloseFont(CompactFont);
        CompactFont = NULL;
    }
    if (PanelFont)
    {
        CloseFont(PanelFont);
        PanelFont = NULL;
    }
    if (ScreenFont)
    {
        CloseFont(ScreenFont);
        ScreenFont = NULL;
    }
}

void
Iconify(void)
{
    CA_Iconify( WinObj );
    CA_CloseWindow( ListWinObj );
    CA_CloseWindow( ConfWinObj );
    Win = ListWin = ConfWin = NULL;

    SetAttrs(WinObj, WA_PubScreen, NULL, TAG_END);
    SetAttrs(ListWinObj, WA_PubScreen, NULL, TAG_END);
    SetAttrs(ConfWinObj, WA_PubScreen, NULL, TAG_END);

    UnlockPubScreen( NULL, Scr );
}

void
UnIconify(void)
{
    if (!(Scr = LockPubScreen(Screen)))
        Scr = LockPubScreen(NULL);

    SetAttrs(WinObj, WA_PubScreen, Scr, TAG_END);
    SetAttrs(ListWinObj, WA_PubScreen, Scr, TAG_END);
    SetAttrs(ConfWinObj, WA_PubScreen, Scr, TAG_END);

    Win     = CA_OpenWindow( WinObj );
    ListWin = CA_OpenWindow( ListWinObj );
    ConfWin = CA_OpenWindow( ConfWinObj );
}

void
MainWindowIDCMP()
{
    ULONG result;
    UWORD code;
    BOOL iconify = FALSE;

    while ((result = CA_HandleInput(WinObj, &code)) != WMHI_LASTMSG)
    {
        /* Windowclass translates key events to GADGETUPs on its own */

        switch (result & WMHI_CLASSMASK)
        {
         case WMHI_CLOSEWINDOW:
             done = TRUE;
             break;

         case WMHI_GADGETUP:
            switch (result & WMHI_GADGETMASK)
             {
             case G_Backward:
                 {
                     ULONG status;

                     /* only do this if not playing. During playing do a continous
                      * seek by listening to the IDCMP messages */

                     GetAttr(CDPANEL_Status, GList[G_Panel], &status);

                     if (status == CDP_STOPPED)
                     {
                        SelectCD(-1);
                     }
                     else if (status == CDP_SEEKING)
                        SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_PLAYING, TAG_END);
                 }
                 break;

             case G_Play:
                 PlayCD(); /* see earlier in this file */
                 break;

             case G_Forward:
                 {
                     ULONG status;

                     /* As with G_Backward */

                     GetAttr(CDPANEL_Status, GList[G_Panel], &status);

                     if (status == CDP_STOPPED)
                     {
                        SelectCD(+1);
                     }
                     else if (status == CDP_SEEKING)
                         SetGadgetAttrs(GList[G_Panel], Win, NULL, CDPANEL_Status, CDP_PLAYING, TAG_END);
                 }
                 break;

             case G_Stop:
                 StopCD(); /* see earlier */
                 break;

             case G_Titles:
                 {
                     ULONG status;

                     /* open up the list list editor */

                     OpenListWindow(Win->LeftEdge + Win->Width, Win->TopEdge);

                     GetAttr(CDPANEL_Status, GList[G_Panel], &status);

                     if (status != CDP_EJECTED && status != CDP_EMPTY)
                     {
                         UpdateTitleEditor();
                     }
                 }
                 break;

             case G_Program:
                /* program editor unimplemented */
                 break;

             case G_List:
                /* user selected a track in the listview, jump to it and play */
                 CD_Play(code + 1);
                 AbortIO(TimerIO);
                 break;
             }
            break;

        case WMHI_MENUPICK:
            code = result & WMHI_MENUMASK;
            while (code != MENUNULL)
            {
                struct MenuItem *mi = ItemAddress( MyMenuStrip, code );
                switch ((ULONG)GTMENUITEM_USERDATA( mi ))
                {
                case M_SelDev:
                    OpenConfWindow(Win->LeftEdge, Win->TopEdge);
                    break;

                case M_EditTitles:
                    {
                        ULONG status;

                        OpenListWindow(Win->LeftEdge + Win->Width, Win->TopEdge);

                        GetAttr(CDPANEL_Status, GList[G_Panel], &status);

                        if (status != CDP_EJECTED && status != CDP_EMPTY)
                        {
                            UpdateTitleEditor();
                        }
                    }
                    break;

                case M_Iconify:
                    iconify = TRUE;
                    break;

                case M_Quit:
                    done = TRUE;
                    break;
                }
                code = mi->NextSelect;
            }
            break;

        case WMHI_NEWSIZE:
            if (result & WMF_ZIPWINDOW)
            {
                struct Gadget *l;
                if (result & WMF_ZOOMED)
                    l = CreateZippedLayout();
                else
                    l = CreateMainLayout();
                if (l)
                {
                    SetAttrs( WinObj, WINDOW_Layout, MainLayout = l, TAG_END );
                }
            }
            break;

        case WMHI_UNICONIFY:
            UnIconify();
            break;

        case WMHI_ICONIFY:
            iconify = TRUE;
            break;
        }
    }
    if (iconify)
    {
        Iconify();
    }
}
