// File: tomfunkhouser[P]gaps/pkgs/fglut/freeglut_menu.c
// Function: fghCheckMenuStatus
static GLboolean fghCheckMenuStatus( SFG_Menu* menu )
{
    SFG_MenuEntry* menuEntry;
    int x, y;

    /* First of all check any of the active sub menus... */
    for( menuEntry = (SFG_MenuEntry *)menu->Entries.First;
         menuEntry;
         menuEntry = (SFG_MenuEntry *)menuEntry->Node.Next )
    {
        if( menuEntry->SubMenu && menuEntry->IsActive )
        {
            /*
             * OK, have the sub-menu checked, too. If it returns GL_TRUE, it
             * will mean that it caught the mouse cursor and we do not need
             * to regenerate the activity list, and so our parents do...
             */
            GLboolean return_status;

            menuEntry->SubMenu->Window->State.MouseX =
                menu->Window->State.MouseX + menu->X - menuEntry->SubMenu->X;
            menuEntry->SubMenu->Window->State.MouseY =
                menu->Window->State.MouseY + menu->Y - menuEntry->SubMenu->Y;
            return_status = fghCheckMenuStatus( menuEntry->SubMenu );

            if ( return_status )
                return GL_TRUE;
        }
    }

    /* That much about our sub menus, let's get to checking the current menu: */
    x = menu->Window->State.MouseX;
    y = menu->Window->State.MouseY;

    /* Check if the mouse cursor is contained within the current menu box */
    if( ( x >= FREEGLUT_MENU_BORDER ) &&
        ( x < menu->Width  - FREEGLUT_MENU_BORDER ) &&
        ( y >= FREEGLUT_MENU_BORDER ) &&
        ( y < menu->Height - FREEGLUT_MENU_BORDER )  )
    {
        int menuID = ( y - FREEGLUT_MENU_BORDER ) / FREEGLUT_MENU_HEIGHT;

        /* The mouse cursor is somewhere over our box, check it out. */
        menuEntry = fghFindMenuEntry( menu, menuID + 1 );
        FREEGLUT_INTERNAL_ERROR_EXIT( menuEntry, "Cannot find menu entry",
                                      "fghCheckMenuStatus" );

        menuEntry->IsActive = GL_TRUE;
        menuEntry->Ordinal = menuID;

        /*
         * If this is not the same as the last active menu entry, deactivate
         * the previous entry.  Specifically, if the previous active entry
         * was a submenu then deactivate it.
         */
        if( menu->ActiveEntry && ( menuEntry != menu->ActiveEntry ) )
            if( menu->ActiveEntry->SubMenu )
                fghDeactivateSubMenu( menu->ActiveEntry );

        if( menuEntry != menu->ActiveEntry )
        {
            menu->Window->State.Redisplay = GL_TRUE;
            if( menu->ActiveEntry )
                menu->ActiveEntry->IsActive = GL_FALSE;
        }

        menu->ActiveEntry = menuEntry;
        menu->IsActive = GL_TRUE;  /* XXX Do we need this? */

        /*
         * OKi, we have marked that entry as active, but it would be also
         * nice to have its contents updated, in case it's a sub menu.
         * Also, ignore the return value of the check function:
         */
        if( menuEntry->SubMenu )
        {
            if ( ! menuEntry->SubMenu->IsActive )
            {
                int max_x, max_y;
                SFG_Window *current_window = fgStructure.CurrentWindow;

                /* Set up the initial menu position now... */
                menuEntry->SubMenu->IsActive = GL_TRUE;

                /* Set up the initial submenu position now: */
                fghGetVMaxExtent(menu->ParentWindow, &max_x, &max_y);
                menuEntry->SubMenu->X = menu->X + menu->Width;
                menuEntry->SubMenu->Y = menu->Y +
                    menuEntry->Ordinal * FREEGLUT_MENU_HEIGHT;

                if( menuEntry->SubMenu->X + menuEntry->SubMenu->Width > max_x )
                    menuEntry->SubMenu->X = menu->X - menuEntry->SubMenu->Width;

                if( menuEntry->SubMenu->Y + menuEntry->SubMenu->Height > max_y )
                {
                    menuEntry->SubMenu->Y -= ( menuEntry->SubMenu->Height -
                                               FREEGLUT_MENU_HEIGHT -
                                               2 * FREEGLUT_MENU_BORDER );
                    if( menuEntry->SubMenu->Y < 0 )
                        menuEntry->SubMenu->Y = 0;
                }

                fgSetWindow( menuEntry->SubMenu->Window );
                glutPositionWindow( menuEntry->SubMenu->X,
                                    menuEntry->SubMenu->Y );
                glutReshapeWindow( menuEntry->SubMenu->Width,
                                   menuEntry->SubMenu->Height );
                glutPopWindow( );
                glutShowWindow( );
                menuEntry->SubMenu->Window->ActiveMenu = menuEntry->SubMenu;
                fgSetWindow( current_window );
                menuEntry->SubMenu->Window->State.MouseX =
                    x + menu->X - menuEntry->SubMenu->X;
                menuEntry->SubMenu->Window->State.MouseY =
                    y + menu->Y - menuEntry->SubMenu->Y;
                fghCheckMenuStatus( menuEntry->SubMenu );
            }

            /* Activate it because its parent entry is active */
            menuEntry->SubMenu->IsActive = GL_TRUE;  /* XXX Do we need this? */
        }

        /* Report back that we have caught the menu cursor */
        return GL_TRUE;
    }

    /* Looks like the menu cursor is somewhere else... */
    if( menu->ActiveEntry && menu->ActiveEntry->IsActive &&
        ( !menu->ActiveEntry->SubMenu ||
          !menu->ActiveEntry->SubMenu->IsActive ) )
    {
        menu->Window->State.Redisplay = GL_TRUE;
        menu->ActiveEntry->IsActive = GL_FALSE;
        menu->ActiveEntry = NULL;
    }

    return GL_FALSE;
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x38(%rsp)
movq 0x38(%rsp), %rax
movq 0x20(%rax), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, 0x30(%rsp)
je 0x17fdfe
movq 0x30(%rsp), %rax
cmpq $0x0, 0x20(%rax)
je 0x17fdea
movq 0x30(%rsp), %rax
movzbl 0x28(%rax), %eax
cmpl $0x0, %eax
je 0x17fdea
movq 0x38(%rsp), %rax
movq 0x60(%rax), %rax
movl 0x60(%rax), %ecx
movq 0x38(%rsp), %rax
addl 0x4c(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
subl 0x4c(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x60(%rax), %rax
movl %ecx, 0x60(%rax)
movq 0x38(%rsp), %rax
movq 0x60(%rax), %rax
movl 0x64(%rax), %ecx
movq 0x38(%rsp), %rax
addl 0x50(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
subl 0x50(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x60(%rax), %rax
movl %ecx, 0x64(%rax)
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rdi
callq 0x17fd20
movb %al, 0x27(%rsp)
cmpb $0x0, 0x27(%rsp)
je 0x17fde8
movb $0x1, 0x47(%rsp)
jmp 0x180229
jmp 0x17fdea
jmp 0x17fdec
movq 0x30(%rsp), %rax
movq (%rax), %rax
movq %rax, 0x30(%rsp)
jmp 0x17fd37
movq 0x38(%rsp), %rax
movq 0x60(%rax), %rax
movl 0x60(%rax), %eax
movl %eax, 0x2c(%rsp)
movq 0x38(%rsp), %rax
movq 0x60(%rax), %rax
movl 0x64(%rax), %eax
movl %eax, 0x28(%rsp)
cmpl $0x2, 0x2c(%rsp)
jl 0x1801bc
movl 0x2c(%rsp), %eax
movq 0x38(%rsp), %rcx
movl 0x44(%rcx), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
jge 0x1801bc
cmpl $0x2, 0x28(%rsp)
jl 0x1801bc
movl 0x28(%rsp), %eax
movq 0x38(%rsp), %rcx
movl 0x48(%rcx), %ecx
subl $0x2, %ecx
cmpl %ecx, %eax
jge 0x1801bc
movl 0x28(%rsp), %eax
subl $0x2, %eax
movl %eax, 0xc(%rsp)
leaq 0x7ffa4(%rip), %rdi     # 0x1ffe18
callq 0x17a700
movl %eax, %ecx
movl 0xc(%rsp), %eax
addl $0x2, %ecx
cltd
idivl %ecx
movl %eax, 0x20(%rsp)
movq 0x38(%rsp), %rdi
movl 0x20(%rsp), %esi
addl $0x1, %esi
callq 0x180df0
movq %rax, 0x30(%rsp)
cmpq $0x0, 0x30(%rsp)
jne 0x17fec3
leaq 0x2e39c(%rip), %rdi     # 0x1ae24a
leaq 0x2ec22(%rip), %rsi     # 0x1aead7
leaq 0x2ec32(%rip), %rdx     # 0x1aeaee
movb $0x0, %al
callq 0x17de70
movq 0x30(%rsp), %rax
movb $0x1, 0x28(%rax)
movl 0x20(%rsp), %ecx
movq 0x30(%rsp), %rax
movl %ecx, 0x14(%rax)
movq 0x38(%rsp), %rax
cmpq $0x0, 0x58(%rax)
je 0x17ff14
movq 0x30(%rsp), %rax
movq 0x38(%rsp), %rcx
cmpq 0x58(%rcx), %rax
je 0x17ff14
movq 0x38(%rsp), %rax
movq 0x58(%rax), %rax
cmpq $0x0, 0x20(%rax)
je 0x17ff12
movq 0x38(%rsp), %rax
movq 0x58(%rax), %rdi
callq 0x180890
jmp 0x17ff14
movq 0x30(%rsp), %rax
movq 0x38(%rsp), %rcx
cmpq 0x58(%rcx), %rax
je 0x17ff4c
movq 0x38(%rsp), %rax
movq 0x60(%rax), %rax
movb $0x1, 0x48(%rax)
movq 0x38(%rsp), %rax
cmpq $0x0, 0x58(%rax)
je 0x17ff4a
movq 0x38(%rsp), %rax
movq 0x58(%rax), %rax
movb $0x0, 0x28(%rax)
jmp 0x17ff4c
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %rax
movq %rcx, 0x58(%rax)
movq 0x38(%rsp), %rax
movb $0x1, 0x40(%rax)
movq 0x30(%rsp), %rax
cmpq $0x0, 0x20(%rax)
je 0x1801b5
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
cmpb $0x0, 0x40(%rax)
jne 0x1801a8
leaq 0x7ff53(%rip), %rax     # 0x1ffee0
movq 0x30(%rax), %rax
movq %rax, 0x10(%rsp)
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movb $0x1, 0x40(%rax)
movq 0x38(%rsp), %rax
movq 0x68(%rax), %rdi
leaq 0x1c(%rsp), %rsi
leaq 0x18(%rsp), %rdx
callq 0x181160
movq 0x38(%rsp), %rax
movl 0x4c(%rax), %ecx
movq 0x38(%rsp), %rax
addl 0x44(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl %ecx, 0x4c(%rax)
movq 0x38(%rsp), %rax
movl 0x50(%rax), %eax
movl %eax, 0x4(%rsp)
movq 0x30(%rsp), %rax
movl 0x14(%rax), %eax
movl %eax, 0x8(%rsp)
leaq 0x7fe22(%rip), %rdi     # 0x1ffe18
callq 0x17a700
movl 0x4(%rsp), %ecx
movl %eax, %edx
movl 0x8(%rsp), %eax
addl $0x2, %edx
imull %edx, %eax
addl %eax, %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl %ecx, 0x50(%rax)
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x4c(%rax), %eax
movq 0x30(%rsp), %rcx
movq 0x20(%rcx), %rcx
addl 0x44(%rcx), %eax
cmpl 0x1c(%rsp), %eax
jle 0x180057
movq 0x38(%rsp), %rax
movl 0x4c(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
subl 0x44(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl %ecx, 0x4c(%rax)
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x50(%rax), %eax
movq 0x30(%rsp), %rcx
movq 0x20(%rcx), %rcx
addl 0x48(%rcx), %eax
cmpl 0x18(%rsp), %eax
jle 0x1800cd
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x48(%rax), %eax
movl %eax, (%rsp)
leaq 0x7fd8d(%rip), %rdi     # 0x1ffe18
callq 0x17a700
movl (%rsp), %edx
addl $0x2, %eax
subl %eax, %edx
subl $0x4, %edx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x50(%rax), %ecx
subl %edx, %ecx
movl %ecx, 0x50(%rax)
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
cmpl $0x0, 0x50(%rax)
jge 0x1800cb
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl $0x0, 0x50(%rax)
jmp 0x1800cd
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x60(%rax), %rdi
callq 0x1838e0
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x4c(%rax), %edi
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x50(%rax), %esi
callq 0x184ae0
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x44(%rax), %edi
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movl 0x48(%rax), %esi
callq 0x1849c0
callq 0x184bf0
callq 0x184620
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rcx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x60(%rax), %rax
movq %rcx, 0x150(%rax)
movq 0x10(%rsp), %rdi
callq 0x1838e0
movl 0x2c(%rsp), %ecx
movq 0x38(%rsp), %rax
addl 0x4c(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
subl 0x4c(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x60(%rax), %rax
movl %ecx, 0x60(%rax)
movl 0x28(%rsp), %ecx
movq 0x38(%rsp), %rax
addl 0x50(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
subl 0x50(%rax), %ecx
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movq 0x60(%rax), %rax
movl %ecx, 0x64(%rax)
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rdi
callq 0x17fd20
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rax
movb $0x1, 0x40(%rax)
movb $0x1, 0x47(%rsp)
jmp 0x180229
movq 0x38(%rsp), %rax
cmpq $0x0, 0x58(%rax)
je 0x180224
movq 0x38(%rsp), %rax
movq 0x58(%rax), %rax
movzbl 0x28(%rax), %eax
cmpl $0x0, %eax
je 0x180224
movq 0x38(%rsp), %rax
movq 0x58(%rax), %rax
cmpq $0x0, 0x20(%rax)
je 0x1801fd
movq 0x38(%rsp), %rax
movq 0x58(%rax), %rax
movq 0x20(%rax), %rax
cmpb $0x0, 0x40(%rax)
jne 0x180224
movq 0x38(%rsp), %rax
movq 0x60(%rax), %rax
movb $0x1, 0x48(%rax)
movq 0x38(%rsp), %rax
movq 0x58(%rax), %rax
movb $0x0, 0x28(%rax)
movq 0x38(%rsp), %rax
movq $0x0, 0x58(%rax)
movb $0x0, 0x47(%rsp)
movb 0x47(%rsp), %al
addq $0x48, %rsp
retq
nopw %cs:(%rax,%rax)