#include "xheaders.h"

#include XPopupMenu_i
#include XMenuBar_i
#include XMenuItem_i
#include XPoint_i
#include XResource_i
#include XResourceLibrary_i
#include XFrameWindow_i

#include <stdlib.h>
#include <string.h>


/**** XMenuItem ***/

char * XMenuItem :: GetText( void )
{  return t; }

void XMenuItem :: SetID( SHORT i)
{ item.id = i; }


XMenuItem :: XMenuItem()
{ memset(&item, 0, sizeof(item)); t = NULL; }

XMenuItem :: XMenuItem( char *text, SHORT id, LONG style, LONG position, BOOL isSeparator)
{
   memset( &item, 0, sizeof(item));
   if(isSeparator)
      {
         item.afStyle = MIS_SEPARATOR;
         item.iPosition = position;
         t = NULL;
      }
   else
      {
         t = (char*) malloc( strlen(text) + 1);
         strcpy( t, text);
         item.iPosition = position;
         item.afStyle = style;
         item.id = id;
      }
}


XMenuItem :: ~XMenuItem()
{
  if(t)
   free(t);
}


void XMenuItem :: SetText( char * p)
{
  t = (char*) realloc(t, strlen(p)+1);
  strcpy( t, p);
  winhandle=0;
}


/**** XMenu ****/

XMenu :: XMenu ( XMenu * m)
{
  if(m )
     winhandle = m->winhandle;
}


/*DOC
CLASS XMenu
FUNCTION CascadeItem
If you call CascadeItem() a menuitem with a submenu bcomes cascade, that means
a button is inserted which enables the submenu. If you have made a menuitm cascaded
you must select a default-item from the submenu of that menuitem by calling CheckItem().
Parameters: SHORT itemId                 the menuItem to become cascade
*/
void XMenu :: CascadeItem( SHORT itemID)
{
  MENUITEM menuitem;
  ULONG style;

  WinSendMsg(winhandle, MM_QUERYITEM,
             MPFROM2SHORT(itemID, TRUE),
             MPFROMP(&menuitem));

  style=WinQueryWindowULong(menuitem.hwndSubMenu, QWL_STYLE);
  WinSetWindowULong(menuitem.hwndSubMenu,
                    QWL_STYLE, style|MS_CONDITIONALCASCADE);
}


SHORT XMenu :: QueryItemCount( void )
{
   return (SHORT) WinSendMsg( winhandle, MM_QUERYITEMCOUNT, 0, 0);
}


SHORT XMenu :: QueryItemID( SHORT pos)
{
   return (SHORT) WinSendMsg( winhandle, MM_ITEMIDFROMPOSITION, MPFROMSHORT( pos ), 0);
}


void XMenu :: DeleteItem( SHORT id)
{
   WinSendMsg( winhandle, MM_DELETEITEM, MPFROM2SHORT( id, TRUE), 0);
}

#include "xmsgBox.h"
/*DOC
CLASS XMenu
FUNCTION QueryItem
REMARKS query an item of a XMenuBar or XPopupMenu
Parameters: XMenuItem * item             buffer to hold the information
            SHORT theID                  the ID of the requested menu-item
Returns:    BOOL  success
*/
BOOL XMenu :: QueryItem( XMenuItem * it, SHORT id)
{
   BOOL res = SHORT1FROMMR(WinSendMsg( winhandle, MM_QUERYITEM,
                      MPFROM2SHORT( id, TRUE),
                      MPFROMP( &it->item)));
   if( res)
      {
         SHORT l = SHORT1FROMMR( WinSendMsg( winhandle, MM_QUERYITEMTEXTLENGTH, MPFROM2SHORT( it->item.id, TRUE), 0));
         it->t = (char*) realloc( it->t, l + 1 );
         WinSendMsg( winhandle,  MM_QUERYITEMTEXT, MPFROM2SHORT( it->item.id, l+1), (MPARAM) it->t);
         it->winhandle = it->item.hwndSubMenu;
      }
   return res;
}



void XMenu :: InsertItem( XMenuItem * it, XMenuItem * subMenu)
{
   if( subMenu )
      {
         if( subMenu->item.hwndSubMenu == 0)
            {
               subMenu->winhandle = subMenu->item.hwndSubMenu = WinCreateWindow( HWND_OBJECT, WC_MENU, (PSZ) "", WS_VISIBLE, 0,0,0,0, HWND_OBJECT, HWND_TOP, 999, NULL, NULL);
               subMenu->item.afStyle|= MIS_SUBMENU;
               WinSendMsg( winhandle, MM_DELETEITEM, MPFROM2SHORT(subMenu->item.id, TRUE), 0);
//               WinSendMsg( winhandle, MM_SETITEM, MPFROMSHORT(subMenu->item.id), MPFROMP(&subMenu->item));
               WinSendMsg( subMenu->winhandle, MM_INSERTITEM, MPFROMP(&it->item), MPFROMP(it->t));
               WinSendMsg( winhandle, MM_INSERTITEM, MPFROMP(&subMenu->item), MPFROMP(subMenu->t));
               return;
           }
         WinSendMsg( subMenu->item.hwndSubMenu, MM_INSERTITEM, MPFROMP(&it->item), MPFROMP(it->t));
      }
   else
      WinSendMsg( winhandle, MM_INSERTITEM, MPFROMP(&it->item), MPFROMP(it->t));
}


void XMenu :: EnableItem( SHORT id, BOOL enable)
{
   SHORT r = 0;

   if( enable == FALSE)
      r = MIA_DISABLED;

   WinSendMsg( winhandle, MM_SETITEMATTR, MPFROM2SHORT( id, TRUE), MPFROM2SHORT(MIA_DISABLED, r));
}


void XMenu :: RemoveItem( SHORT itemId )
{
   WinSendMsg(winhandle, MM_REMOVEITEM, MPFROM2SHORT( itemId, TRUE), 0);
}


void XMenu :: SetItemText( SHORT itemId, char * text)
{
   WinSendMsg( winhandle, MM_SETITEMTEXT, MPFROM2SHORT(itemId, TRUE), (MPARAM) text);
}


void XMenu :: CheckItem( SHORT itemId, BOOL check)
{
   SHORT r = MIA_CHECKED;

   if( check == FALSE)
      r = 0;

   WinSendMsg( winhandle, MM_SETITEMATTR, MPFROM2SHORT( itemId, TRUE), MPFROM2SHORT(MIA_CHECKED, r));
}


/*****  XPopupMenu *****/
/*DOC
CLASS XPopupMenu
FUNCTION XPopupMenu
Creates a popup-menu, to show it call XPopupMenu::Display()
Parameters:  XResource * res      the resource which defines the menu
             XFrameWindow * win   the owner-window
*/
XPopupMenu :: XPopupMenu( XResource * res, XFrameWindow * ow): XMenu()
{
   owner = ow;
   winhandle = res->library->LoadMenu(ow, res->id);
   WinSetWindowPtr( winhandle, 0, this);
}


/*DOC
CLASS XPopupMenu
FUNCTION Display
shows a created popup-menu
Parameters:  XPoint * point   the point wher to show the menu
             USHORT default   the default-menuitem to display under the mouse
             ULONG style      style to display the menu
*/

void XPopupMenu :: Display( XPoint * p, USHORT def, ULONG style)
{
   WinPopupMenu( owner->winhandle, owner->winhandle, winhandle, p->GetX(), p->GetY(), def, style);
}


/**** XMenuBar ****/

XMenuBar :: XMenuBar( XFrameWindow * fr, XResource * res)
{
   winhandle = WinLoadMenu( fr->frame, (HMODULE) res->library->moduleHandle, res->id );
   WinSetWindowPtr( winhandle, 0, this);
   WinSetOwner( winhandle, fr->frame);
   WinSendMsg( fr->frame, WM_UPDATEFRAME, (MPARAM) FCF_MENU, (MPARAM) 0);
}


XMenuBar :: XMenuBar( LONG hwnd)
{
   winhandle = hwnd;
   WinSetWindowPtr( winhandle, 0, this);
}


XMenuBar :: ~XMenuBar()
{
}


void XMenuBar :: Show( void )
{
   WinSetParent( winhandle, WinQueryWindow( winhandle, QW_OWNER), TRUE);
   WinSendMsg( WinQueryWindow( winhandle, QW_OWNER), WM_UPDATEFRAME, (MPARAM) FCF_MENU, 0);
}


void XMenuBar :: Hide( void )
{
   WinSetParent( winhandle, HWND_OBJECT, FALSE );
   WinSendMsg( WinQueryWindow( winhandle, QW_OWNER), WM_UPDATEFRAME, (MPARAM) FCF_MENU, 0);
}
