/*----------------------------------------------------------------------*
    MenuFunc.c version 3.0 - © Copyright 1991 Jaba Development

    Author : Jan van den Baard
    Purpose: Menu editing subroutines.
 *----------------------------------------------------------------------*/
extern struct Window        *MainWindow;
extern struct Screen        *MainScreen;
extern struct RastPort      *MainRP;
extern struct MyMenu        *MenuStrip;
extern struct ListItem      *MenusList;
extern struct ListItem      *ItemsList;
extern struct ListItem      *SubsList;
extern struct Screen        *MainScreen;
extern struct RastPort      *MainRP;
extern struct MyMenu        *MenuStrip;
extern struct Gadget        *Gadget;
extern struct MemoryChain    Memory;
extern struct Menu           MainMenuStrip[];
extern struct Menu           ItemMenuStrip[];
extern struct Menu           SubMenuStrip[];
extern struct MenuItem       MainItem[];
extern struct MenuItem       TheItem[];
extern struct MenuItem       SubItem[];
extern struct MenuItem       dummy;
extern struct MyMenu        *ParentMenu;
extern struct MyMenuItem    *ParentItem;

extern ULONG                 Class;
extern UWORD                 Code, Qualifier, FrontPen, BackPen;
extern UWORD                 ItemCount, SubCount, MenuCount;
extern UWORD                 ItemTotal, SubTotal, MenuTotal;

struct IntuiText *MakeIText( UBYTE *text, ULONG DrMd , ULONG tsize)
{
    struct IntuiText    *IText;

    if(NOT(IText = AllocItem(&Memory,(ULONG)sizeof(struct IntuiText),MEMF_PUBLIC)))
        goto NoIMem;
    if(NOT(IText->IText = (UBYTE *)AllocItem(&Memory,tsize,MEMF_PUBLIC)))
        goto NoIMem;

    IText->LeftEdge = 1;
    IText->TopEdge  = 1;
    IText->DrawMode = DrMd;
    IText->FrontPen = FrontPen;
    IText->BackPen  = BackPen;

    strncpy((char *)IText->IText,(char *)text,tsize);

    return(IText);

NoIMem:
    if(IText)   FreeItem(&Memory,IText,(ULONG)sizeof(struct IntuiText));
    return(NULL);
}

ULONG WidestItem( register struct MyMenuItem *tmp, ULONG MinWidth)
{
    register struct IntuiText   *itext;
    register ULONG               width = MinWidth, w2 = 0L, flg;

    for( ; tmp; tmp = tmp->NextItem) {
        itext = (struct IntuiText *)tmp->ItemFill;
        flg   = (ULONG)tmp->Flags;
        w2 = TEXT_WIDTH(MainRP,itext->IText) + TEXTSPACING;
        if(TestBits(flg,CHECKIT))   w2 += 20;
        if(TestBits(flg,COMMSEQ))   w2 += 40;
        if(w2 > width) width = w2;
    }
    return(width);
}

struct MyMenu *LastMenu( void )
{
    register struct MyMenu *tmp;

    for(tmp = MenuStrip; tmp->NextMenu; tmp = tmp->NextMenu);

    return(tmp);
}

struct MyMenuItem *LastItem( struct MyMenuItem *first )
{
    for( ; first->NextItem; first = first->NextItem);

    return(first);
}

ULONG StripWidth( void )
{
    register struct MyMenu *tmp;

    if(NOT MenuStrip)   return(NULL);

    tmp = LastMenu();

    return(tmp->LeftEdge+tmp->Width);
}

ULONG ItemHeight( struct MyMenuItem *tmp )
{
    register ULONG height;

    tmp = LastItem(tmp);

    return(tmp->TopEdge+tmp->Height);
}

struct MyMenuItem *FindPredItem( struct MyMenuItem *first, struct MyMenuItem *search )
{
    for( ; first->NextItem != search; first = first->NextItem);

    return(first);
}

struct MyMenu *FindPredMenu( struct MyMenu *search )
{
    register struct MyMenu *tmp;

    for(tmp = MenuStrip; tmp->NextMenu != search; tmp = tmp->NextMenu);

    return(tmp);
}

void ReformatList( ULONG Type )
{
    register struct ListItem *tmp;
    register WORD             top = 0, i = 0, left = 120;

    if(Type == MENUED)
        tmp = MenusList;
    else if(Type == ITEMED)
        tmp = ItemsList;
    else
        tmp = SubsList;

    for(i = 0; tmp; tmp = (struct ListItem *)tmp->AItem.NextItem,i++) {
        if(i == 16) { left = 192; top = 0; }
        tmp->AItem.LeftEdge = left;
        tmp->AItem.TopEdge = top;
        top               += 9;
    }
}

struct ListItem *CreateListItem( APTR Object, ULONG Type, ULONG Insert, struct ListItem *pred , ULONG remset)
{
    struct MyMenu       *menu;
    struct MyMenuItem   *item;
    struct ListItem     *list, *ll;
    UWORD                count, num = 0;

    menu = (struct MyMenu *)Object;
    item = (struct MyMenuItem *)Object;

    if((list = (struct ListItem *)AllocItem(&Memory,(ULONG)sizeof(struct ListItem),MEMF_PUBLIC))) {
        if(Type == ITEMED)
            num = ItemCount;
        else if(Type == SUBED)
            num = SubCount;
        else
            num = MenuCount;

        if(num > 16)
            list->AItem.LeftEdge = 192;
        else
            list->AItem.LeftEdge = 120;

        list->AItem.Width    = 72;
        list->AItem.Height   = 9;
        list->AItem.Flags    = ITEMTEXT+ITEMENABLED+HIGHCOMP;
        list->AItem.ItemFill = (APTR)&list->Text;

        list->Text.FrontPen  = 0;
        list->Text.BackPen   = 1;
        list->Text.DrawMode  = JAM2;
        list->Text.LeftEdge  = 1;
        list->Text.TopEdge   = 1;
        list->Text.IText     = &list->Letters[0];

        if(Type == MENUED) {
            list->Menu       = menu;
            strncpy((char *)&list->Letters[0],(char *)&menu->TheMenuName[0],9);
            if(NOT Insert) {
                if(MenusList) {
                    ll = (struct ListItem *)LastItem((struct MyMenuItem *)MenusList);
                    if(num != 17)
                        list->AItem.TopEdge = ll->AItem.TopEdge+ll->AItem.Height;
                    else
                        list->AItem.TopEdge = 0;
                    ll->AItem.NextItem  = &list->AItem;
                } else {
                    list->AItem.TopEdge = 0;
                    MenusList           = list;
                }
            } else {
                if(pred == MenusList) {
                    list->AItem.NextItem = (struct MenuItem *)MenusList;
                    MenusList = list;
                } else {
                    ll = (struct ListItem *)FindPredItem((struct MyMenuItem *)MenusList,(struct MyMenuItem *)pred);
                    ll->AItem.NextItem = (struct MenuItem *)list;
                    list->AItem.NextItem = (struct MenuItem *)pred;
                }
                ReformatList(MENUED);
            }
            if(remset) ClearMenuStrip(MainWindow);
            for(count = 1; count < 5; count++)
                MainItem[count].SubItem = (struct MenuItem *)MenusList;
            if(remset) {
                SetMenuStrip(MainWindow,&MainMenuStrip[0]);
                SetMainMenus();
            }
            return(list);
        } else if(Type == ITEMED) {
            list->Menu       = ParentMenu;
            list->Item       = item;
            strncpy((char *)&list->Letters[0],(char *)((struct IntuiText *)item->ItemFill)->IText,9);
            if(NOT Insert) {
                if(ItemsList) {
                    ll = (struct ListItem *)LastItem((struct MyMenuItem *)ItemsList);
                    if(num != 17)
                        list->AItem.TopEdge = ll->AItem.TopEdge+ll->AItem.Height;
                    else
                        list->AItem.TopEdge = 0;
                    ll->AItem.NextItem  = &list->AItem;
                } else {
                    list->AItem.TopEdge = 0;
                    ItemsList           = list;
                }
            } else {
                if(pred == ItemsList) {
                    list->AItem.NextItem = (struct MenuItem *)ItemsList;
                    ItemsList = list;
                } else {
                    ll = (struct ListItem *)FindPredItem((struct MyMenuItem *)ItemsList,(struct MyMenuItem *)pred);
                    ll->AItem.NextItem = (struct MenuItem *)list;
                    list->AItem.NextItem = (struct MenuItem *)pred;
                }
            }
            if(remset) ClearMenuStrip(MainWindow);
            for(count = 1; count < 5; count++)
                TheItem[count].SubItem = (struct MenuItem *)ItemsList;
            if(remset) {
                SetMenuStrip(MainWindow,&ItemMenuStrip[0]);
                SetMainMenus();
            }
            return(list);
        } else {
            list->Menu       = ParentMenu;
            list->Item       = ParentItem;
            list->SubItem    = item;
            strncpy((char *)&list->Letters[0],(char *)((struct IntuiText *)item->ItemFill)->IText,9);
            if(NOT Insert) {
                if(SubsList) {
                    ll = (struct ListItem *)LastItem((struct MyMenuItem *)SubsList);
                    if(num != 17)
                        list->AItem.TopEdge = ll->AItem.TopEdge+ll->AItem.Height;
                    else
                        list->AItem.TopEdge = 0;
                    ll->AItem.NextItem  = &list->AItem;
                } else {
                    list->AItem.TopEdge = 0;
                    SubsList           = list;
                }
            } else {
                if(pred == SubsList) {
                    list->AItem.NextItem = (struct MenuItem *)SubsList;
                    SubsList = list;
                } else {
                    ll = (struct ListItem *)FindPredItem((struct MyMenuItem *)SubsList,(struct MyMenuItem *)pred);
                    ll->AItem.NextItem = (struct MenuItem *)list;
                    list->AItem.NextItem = (struct MenuItem *)pred;
                }
            }
            if(remset) ClearMenuStrip(MainWindow);
            for(count = 1; count < 4; count++)
                SubItem[count].SubItem = (struct MenuItem *)SubsList;
            if(remset) {
                SetMenuStrip(MainWindow,&SubMenuStrip[0]);
                SetMainMenus();
            }
            return(list);
        }
    }
    return(NULL);
}

void FreeMenuItem( struct MyMenuItem *item )
{
    struct IntuiText    *itext;

    if((TestBits((ULONG)item->Flags,ITEMTEXT)) && (item->ItemFill)) {
        itext = (struct IntuiText *)item->ItemFill;
        if(itext->IText) FreeItem(&Memory,itext->IText,80L);
        FreeItem(&Memory,itext,(ULONG)sizeof(struct IntuiText));
    }
    if((TestBits((ULONG)item->Flags,HIGHIMAGE+ITEMTEXT)) && (item->SelectFill)) {
        itext = (struct IntuiText *)item->SelectFill;
        if(itext->IText) FreeItem(&Memory,itext->IText,80L);
        FreeItem(&Memory,itext,(ULONG)sizeof(struct IntuiText));
    }
    FreeItem(&Memory,item->ItsListItem,(ULONG)sizeof(struct ListItem));
    FreeItem(&Memory,item,(ULONG)sizeof(struct MyMenuItem));

}

void FreeMenu( struct MyMenu *menu )
{
    register struct MyMenuItem *i, *i1, *s, *s1;

    if(menu->FirstItem != (struct MyMenuItem *)&dummy) {
        if((i = menu->FirstItem)) {
            while(1) {
                i1 = i->NextItem;
                if((s = i->SubItem)) {
                    while(1) {
                        s1 = s->NextItem;
                        FreeMenuItem(s);
                        if(NOT(s = s1)) break;
                    }
                }
                FreeMenuItem(i);
                if(NOT(i = i1)) break;
            }
        }
    }
    FreeItem(&Memory,menu->ItsListItem,(ULONG)sizeof(struct ListItem));
    FreeItem(&Memory,menu,(ULONG)sizeof(struct MyMenu));
}

void FreeMenuStrip()
{
    register struct MyMenu *m, *m1;

    if(NOT(m = MenuStrip)) return;

    while(1) {
        m1 = m->NextMenu;
        FreeMenu(m);
        if(NOT(m = m1)) break;
    }
    MenuStrip = NULL;
    MenuCount = MenuTotal = NULL;
    ItemCount = ItemTotal = NULL;
    SubCount  = SubTotal  = NULL;
    MenusList = ItemsList = SubsList = NULL;
}

void ReformatS( register struct MyMenuItem *first, WORD left, WORD top, WORD iw)
{
    register WORD tp = 0, le, width;

    width = WidestItem( first, 10 );

    if((left + width + 10) > MainScreen->Width)
        le = -(width);
    else
        le = iw;

    for( ; first; first = first->NextItem ) {
        if(NOT TestBits((ULONG)first->SpecialFlags,USERFORMAT)) {
            first->TopEdge  = tp;
            first->Width    = width;
            first->LeftEdge = le;
            tp += first->Height;
        } else
            tp = first->TopEdge + first->Height;
    }
}

void ReformatI( register struct MyMenuItem *first, WORD left , WORD width)
{
    register WORD top = 0, le;

    width = WidestItem( first, width );

    if((left + width + 10) > MainScreen->Width)
        le = MainScreen->Width - ( left + width + 10 );
    else
        le = 0;

    for( ; first; first = first->NextItem ) {
        if(first->SubItem)
            ReformatS( first->SubItem, left + le + width, first->TopEdge, width);
        if(NOT TestBits((ULONG)first->SpecialFlags,USERFORMAT)) {
            first->TopEdge  = top;
            first->Width    = width;
            first->LeftEdge = le;
            top += first->Height;
        } else
            top = first->TopEdge + first->Height;
    }
}

void ReformatM( void )
{
    register struct MyMenu  *menu;
    register WORD            left = 0;

    for(menu = MenuStrip; menu; menu = menu->NextMenu) {
        if(NOT TestBits((ULONG)menu->SpecialFlags,USERFORMAT)) {
            menu->LeftEdge = left;
            if(menu->FirstItem != (struct MyMenuItem *)&dummy)
                ReformatI( menu->FirstItem , left , menu->Width);
            left += menu->Width;
        } else {
            left = menu->LeftEdge;
            if(menu->FirstItem != (struct MyMenuItem *)&dummy)
                ReformatI( menu->FirstItem , left , menu->Width);
            left = menu->Width;
        }
    }
}
