/** \file
 * \brief IupDialog class
 *
 * See Copyright Notice in "iup.h"
 */


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

#include "iup.h"
#include "iupcbs.h"
#include "iup_class.h"
#include "iup_object.h"
#include "iup_attrib.h"
#include "iup_drv.h"
#include "iup_str.h"
#define _IUPDLG_PRIVATE
#include "iup_dialog.h"
#include "iup_image.h"

#include "iupcocoa_drv.h"
#include "iupcocoa_keycodes.h"
#include "iupcocoa_dragdrop.h"


static const void* DOCKPROGRESS_ASSOCIATED_OBJ_KEY = @"DOCKPROGRESS_ASSOCIATED_OBJ_KEY";
static const char IUPCocoaZoomRestoreFrameKey = 0;

static void* IupCocoaAppearanceContext = &IupCocoaAppearanceContext;

static void cocoaDialogRefreshControlsOnThemeChange(Ihandle* child)
{
  Ihandle* c;
  for (c = child; c; c = c->brother)
  {
    if (c->handle && c->iclass && c->iclass->name)
    {
      if (iupStrEqual(c->iclass->name, "table") ||
          iupStrEqual(c->iclass->name, "list"))
      {
        NSTableView* table_view = (NSTableView*)iupAttribGet(c, "_IUPCOCOA_TABLEVIEW");
        if (table_view)
          [table_view reloadData];
      }
      else if (iupStrEqual(c->iclass->name, "tree"))
      {
        NSScrollView* scroll_view = (NSScrollView*)c->handle;
        if ([scroll_view isKindOfClass:[NSScrollView class]])
        {
          NSOutlineView* outline_view = (NSOutlineView*)[scroll_view documentView];
          if ([outline_view isKindOfClass:[NSOutlineView class]])
            [outline_view reloadData];
        }
      }
    }

    if (c->firstchild)
      cocoaDialogRefreshControlsOnThemeChange(c->firstchild);
  }
}

@interface IupCocoaWindowDelegate : NSObject <NSWindowDelegate>
@end

@interface IupCocoaWindow : NSWindow
@end

@implementation IupCocoaWindow

- (BOOL)performKeyEquivalent:(NSEvent *)event
{
  if ([event type] == NSEventTypeKeyDown)
  {
    Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY); /* this is the dialog handle */
    if (iupObjectCheck(ih))
    {
      NSResponder* first_responder = [self firstResponder];
      Ihandle* focused_ih = nil;

      if (first_responder && [first_responder isKindOfClass:[NSView class]])
      {
        focused_ih = (Ihandle*)objc_getAssociatedObject(first_responder, IHANDLE_ASSOCIATED_OBJ_KEY);
      }

      if (!iupObjectCheck(focused_ih))
      {
        focused_ih = ih;
      }

      int mac_key_code = [event keyCode];
      if (iupcocoaKeyEvent(focused_ih, event, mac_key_code, true))
      {
        return YES;
      }

      if (mac_key_code == kVK_Return)
      {
        if (focused_ih && IupClassMatch(focused_ih, "button"))
        {
          return [super performKeyEquivalent:event];
        }
        Ihandle* button_ih = IupGetAttributeHandle(ih, "DEFAULTENTER");
        if (iupObjectCheck(button_ih))
        {
          iupdrvActivate(button_ih);
          return YES;
        }
      }
      else if (mac_key_code == kVK_Escape)
      {
        Ihandle* button_ih = IupGetAttributeHandle(ih, "DEFAULTESC");
        if (iupObjectCheck(button_ih))
        {
          iupdrvActivate(button_ih);
          return YES;
        }
      }
    }
  }

  return [super performKeyEquivalent:event];
}

- (void)keyDown:(NSEvent *)event
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (ih)
  {
    int mac_key_code = [event keyCode];
    BOOL handled = iupcocoaKeyEvent(ih, event, mac_key_code, true);
    if (!handled)
    {
      [super keyDown:event];
    }
  }
  else
  {
    [super keyDown:event];
  }
}

- (void)keyUp:(NSEvent *)event
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (ih)
  {
    int mac_key_code = [event keyCode];
    if (!iupcocoaKeyEvent(ih, event, mac_key_code, false))
      [super keyUp:event];
  }
  else
    [super keyUp:event];
}

- (void)flagsChanged:(NSEvent *)event
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (ih)
  {
    int mac_key_code = [event keyCode];
    if (!iupcocoaModifierEvent(ih, event, mac_key_code))
      [super flagsChanged:event];
  }
  else
    [super flagsChanged:event];
}

- (void)mouseEntered:(NSEvent*)event
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (iupObjectCheck(ih))
  {
    IFn cb = (IFn)IupGetCallback(ih, "ENTERWINDOW_CB");
    if (cb && cb(ih) == IUP_CLOSE)
      IupExitLoop();
  }
  [super mouseEntered:event];
}

- (void)mouseExited:(NSEvent*)event
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (iupObjectCheck(ih))
  {
    IFn cb = (IFn)IupGetCallback(ih, "LEAVEWINDOW_CB");
    if (cb && cb(ih) == IUP_CLOSE)
      IupExitLoop();
  }
  [super mouseExited:event];
}

- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)the_sender
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih))
    return NSDragOperationNone;

  IupTargetDropAssociatedData* target_drop_data = cocoaTargetDropGetAssociatedData(ih);
  NSArray* supported_types = [target_drop_data dropRegisteredTypes];
  NSPasteboard* paste_board = [the_sender draggingPasteboard];

  if ([paste_board availableTypeFromArray:supported_types])
    return NSDragOperationCopy;

  return NSDragOperationNone;
}

- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)the_sender
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih))
    return NSDragOperationNone;

  return cocoaTargetDropBaseDraggingUpdated(ih, the_sender);
}

- (BOOL)performDragOperation:(id<NSDraggingInfo>)the_sender
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(self, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih))
    return NO;

  NSPasteboard* paste_board = [the_sender draggingPasteboard];
  NSView* content_view = [self contentView];
  NSPoint drop_point = [content_view convertPoint:[the_sender draggingLocation] fromView:nil];

  cocoaTargetDropBasePerformDropCallback(ih, the_sender, paste_board, drop_point);
  return YES;
}

@end

/****************************************************************
 ****************** Utilities & Helpers *************************
 ****************************************************************/

static NSWindowStyleMask cocoaDialogGetStyleMask(Ihandle* ih)
{
  NSWindowStyleMask style_mask;
  int has_titlebar = 0;

  if (iupAttribGet(ih, "TITLE"))
    has_titlebar = 1;

  if (iupAttribGetBoolean(ih, "MAXBOX") ||
      iupAttribGetBoolean(ih, "MINBOX") ||
      iupAttribGetBoolean(ih, "MENUBOX"))
    has_titlebar = 1;

  if (iupAttribGetBoolean(ih, "BORDER"))
    has_titlebar = 1;

  if (has_titlebar)
    style_mask = NSWindowStyleMaskTitled;
  else
    style_mask = NSWindowStyleMaskBorderless;

  if (iupAttribGetBoolean(ih, "RESIZE"))
    style_mask |= NSWindowStyleMaskResizable;

  if (iupAttribGetBoolean(ih, "MINBOX"))
    style_mask |= NSWindowStyleMaskMiniaturizable;

  if (iupAttribGetBoolean(ih, "MENUBOX"))
    style_mask |= NSWindowStyleMaskClosable;

  if (iupAttribGetBoolean(ih, "CUSTOMFRAME"))
    style_mask |= NSWindowStyleMaskFullSizeContentView;

  return style_mask;
}

static void cocoaDialogUpdateStyleMask(Ihandle* ih)
{
  NSWindow* window = iupcocoaDialogGetWindow(ih);
  if (window)
  {
    NSWindowStyleMask new_mask = cocoaDialogGetStyleMask(ih);
    [window setStyleMask:new_mask];
  }
}

IUP_DRV_API bool iupcocoaDialogExitModal(Ihandle* modal_ih)
{
  if(!iupObjectCheck(modal_ih))
  {
    return false;
  }

  Ihandle* parent_ih = IupGetAttributeHandle(modal_ih, "PARENTDIALOG");
  NSWindow* parent_window = nil;
  if(iupObjectCheck(parent_ih))
  {
    parent_window = iupcocoaDialogGetWindow(parent_ih);
  }

  if(!parent_window)
  {
    NSWindow* the_window = iupcocoaDialogGetWindow(modal_ih);
    if(the_window)
    {
      parent_window = [the_window parentWindow];
      if(parent_window)
      {
        parent_ih = (Ihandle*)objc_getAssociatedObject(parent_window, IHANDLE_ASSOCIATED_OBJ_KEY);
      }
    }
  }

  if (parent_window && iupObjectCheck(parent_ih))
  {
    [NSApp activateIgnoringOtherApps:YES];
    [parent_window makeKeyAndOrderFront:nil];
    iupcocoaFocusIn(parent_ih);
    return true;
  }

  return false;
}

static void cocoaDialogChildDestroyNotification(NSNotification* notification)
{
  NSWindow* child_window = [notification object];
  Ihandle* child_ih = (Ihandle*)objc_getAssociatedObject(child_window, IHANDLE_ASSOCIATED_OBJ_KEY);

  if (iupObjectCheck(child_ih))
  {
    NSWindow* parent_window = [child_window parentWindow];
    if (parent_window)
    {
      Ihandle* parent_ih = (Ihandle*)objc_getAssociatedObject(parent_window, IHANDLE_ASSOCIATED_OBJ_KEY);
      if (iupObjectCheck(parent_ih))
      {
        if (iupAttribGetBoolean(child_ih, "MODAL"))
        {
          iupcocoaDialogExitModal(child_ih);
        }
      }
    }
  }
}

/****************************************************************
 ********************** Delegates *******************************
 ****************************************************************/

@implementation IupCocoaWindowDelegate

- (BOOL) windowShouldClose:(id)the_sender
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_sender, IHANDLE_ASSOCIATED_OBJ_KEY);

  if (!iupObjectCheck(ih))
  {
    return YES;
  }

  Icallback callback_function = IupGetCallback(ih, "CLOSE_CB");
  if(callback_function)
  {
    int ret = callback_function(ih);
    if (ret == IUP_IGNORE)
    {
      return NO;
    }
  }

  IupHide(ih);

  return NO;
}

- (void) windowWillClose:(NSNotification*)the_notification
{
  NSWindow* the_window = [the_notification object];
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY);

  if (!iupObjectCheck(ih)) return;

  if(iupAttribGetBoolean(ih, "MODAL"))
  {
    iupcocoaDialogExitModal(ih);
  }
}

- (void) windowDidBecomeKey:(NSNotification*)notification
{
  NSWindow* the_window = [notification object];
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY);

  if (!iupObjectCheck(ih)) return;

  iupcocoaFocusIn(ih);

  if (ih->data->menu)
  {
    iupcocoaMenuSetApplicationMenu(ih->data->menu);
  }
  else
  {
    Ihandle* global_menu = (Ihandle*)IupGetGlobal("MENU");
    iupcocoaMenuSetApplicationMenu(global_menu);
  }
}

- (NSSize) windowWillResize:(NSWindow*)the_sender toSize:(NSSize)frame_size
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_sender, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return frame_size;

  NSSize content_size = [the_sender contentRectForFrameRect:NSMakeRect(0, 0, frame_size.width, frame_size.height)].size;

  IFnii cb = (IFnii)IupGetCallback(ih, "RESIZE_CB");
  if(!cb || cb(ih, content_size.width, content_size.height)!=IUP_IGNORE)
  {
    return frame_size;
  }
  else
  {
    return [the_sender frame].size;
  }
}

- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)newFrame
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(window, IHANDLE_ASSOCIATED_OBJ_KEY);

  if (ih && ih->data->ignore_resize)
    return [window frame];

  NSValue* previousFrameValue = objc_getAssociatedObject(window, &IUPCocoaZoomRestoreFrameKey);

  if (previousFrameValue)
  {
    NSRect restoreFrame = [previousFrameValue rectValue];
    objc_setAssociatedObject(window, &IUPCocoaZoomRestoreFrameKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    return restoreFrame;
  }
  else
  {
    NSRect currentFrame = [window frame];
    NSValue* frameValue = [NSValue valueWithRect:currentFrame];
    objc_setAssociatedObject(window, &IUPCocoaZoomRestoreFrameKey, frameValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    return newFrame;
  }
}

- (void) windowDidResize:(NSNotification*)the_notification
{
  NSWindow* the_window = [the_notification object];
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return;

  NSRect frame_rect = [the_window frame];
  NSRect content_rect = [[the_window contentView] bounds];

  int new_width = iupROUND(frame_rect.size.width);
  int new_height = iupROUND(frame_rect.size.height);

  if (ih->data->ignore_resize) return;

  if (ih->currentwidth == new_width && ih->currentheight == new_height)
    return;

  ih->currentwidth = new_width;
  ih->currentheight = new_height;

  int new_state = IUP_RESTORE;
  if ([the_window isZoomed])
    new_state = IUP_MAXIMIZE;

  if (ih->data->show_state != new_state)
  {
    IFni show_cb = (IFni)IupGetCallback(ih, "SHOW_CB");
    ih->data->show_state = new_state;
    if (show_cb && show_cb(ih, new_state) == IUP_CLOSE)
      IupExitLoop();
  }

  IFnii resize_cb = (IFnii)IupGetCallback(ih, "RESIZE_CB");
  if (!resize_cb || resize_cb(ih, (int)content_rect.size.width, (int)content_rect.size.height) != IUP_IGNORE)
  {
    ih->data->ignore_resize = 1;
    IupRefresh(ih);
    ih->data->ignore_resize = 0;
  }

  if (iupAttribGetBoolean(ih, "BACKIMAGEZOOM"))
  {
    char* background = iupAttribGet(ih, "BACKGROUND");
    if (background)
    {
      unsigned char r_tmp, g_tmp, b_tmp;
      if (!iupStrToRGB(background, &r_tmp, &g_tmp, &b_tmp))
        IupSetAttribute(ih, "BACKGROUND", background);
    }
  }
}

- (void) windowDidMove:(NSNotification*)the_notification
{
  NSWindow* the_window = [the_notification object];
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return;

  IFnii cb = (IFnii)IupGetCallback(ih, "MOVE_CB");
  if (cb)
  {
    int x, y;
    iupdrvDialogGetPosition(ih, NULL, &x, &y);
    cb(ih, x, y);
  }
}

- (void) windowDidMiniaturize:(NSNotification*)the_notification
{
  NSWindow* the_window = [the_notification object];
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return;

  if (ih->data->show_state != IUP_MINIMIZE)
  {
    IFni cb = (IFni)IupGetCallback(ih, "SHOW_CB");
    ih->data->show_state = IUP_MINIMIZE;
    if (cb && cb(ih, IUP_MINIMIZE) == IUP_CLOSE)
      IupExitLoop();
  }
}

- (void) windowDidDeminiaturize:(NSNotification*)the_notification
{
  NSWindow* the_window = [the_notification object];
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return;

  int new_state = [the_window isZoomed] ? IUP_MAXIMIZE : IUP_RESTORE;
  if (ih->data->show_state != new_state)
  {
    IFni cb = (IFni)IupGetCallback(ih, "SHOW_CB");
    ih->data->show_state = new_state;
    if (cb && cb(ih, new_state) == IUP_CLOSE)
      IupExitLoop();
  }
}

- (void) windowWillEnterFullScreen:(NSNotification*)the_notification
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject([the_notification object], IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return;

  NSWindow* window = [the_notification object];
  if (!objc_getAssociatedObject(window, &IUPCocoaZoomRestoreFrameKey))
  {
    NSRect currentFrame = [window frame];
    NSValue* frameValue = [NSValue valueWithRect:currentFrame];
    objc_setAssociatedObject(window, &IUPCocoaZoomRestoreFrameKey, frameValue, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  }

  iupAttribSet(ih, "_IUPCOCOA_FULLSCREEN", "YES");
}

- (void) windowDidEnterFullScreen:(NSNotification*)the_notification
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject([the_notification object], IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return;

  ih->data->ignore_resize = 1;
  IupRefresh(ih);
  ih->data->ignore_resize = 0;
}

- (void) windowDidExitFullScreen:(NSNotification*)the_notification
{
  Ihandle* ih = (Ihandle*)objc_getAssociatedObject([the_notification object], IHANDLE_ASSOCIATED_OBJ_KEY);
  if (!iupObjectCheck(ih)) return;

  iupAttribSet(ih, "_IUPCOCOA_FULLSCREEN", "NO");
  ih->data->ignore_resize = 1;
  IupRefresh(ih);
  ih->data->ignore_resize = 0;
}

- (void)cocoaDialogChildDestroyNotification:(NSNotification*)notification
{
  cocoaDialogChildDestroyNotification(notification);
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
  if (context == IupCocoaAppearanceContext)
  {
    NSWindow* the_window = (NSWindow*)object;
    Ihandle* ih = (Ihandle*)objc_getAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY);

    if (!iupObjectCheck(ih))
    return;

    iupcocoaSetGlobalColors();

    int dark_mode = iupcocoaIsSystemDarkMode();

    IFni cb = (IFni)IupGetCallback(ih, "THEMECHANGED_CB");
    if (cb)
    cb(ih, dark_mode);

    if (ih->firstchild)
      cocoaDialogRefreshControlsOnThemeChange(ih->firstchild);

    NSView* content_view = [the_window contentView];
    if (content_view)
    {
    NSMutableArray* view_stack = [NSMutableArray arrayWithObject:content_view];
    while ([view_stack count] > 0)
    {
      NSView* current_view = [view_stack lastObject];
      [view_stack removeLastObject];

      [current_view setNeedsDisplay:YES];

      [view_stack addObjectsFromArray:[current_view subviews]];
    }
    }

    ih->data->ignore_resize = 1;
    IupRefresh(ih);
    ih->data->ignore_resize = 0;
  }
  else
  {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
  }
}

@end

/****************************************************************
 ******************* Driver Functions ***************************
 ****************************************************************/

IUP_SDK_API int iupdrvDialogIsVisible(Ihandle* ih)
{
  return iupdrvIsVisible(ih);
}

IUP_SDK_API void iupdrvDialogGetSize(Ihandle* ih, InativeHandle* handle, int *w, int *h)
{
  NSWindow* the_window = handle ? (NSWindow*)handle : iupcocoaDialogGetWindow(ih);
  if (!the_window) return;

  NSRect frame_rect = [the_window frame];

  if (w) *w = iupROUND(frame_rect.size.width);
  if (h) *h = iupROUND(frame_rect.size.height);
}

IUP_SDK_API void iupdrvDialogSetVisible(Ihandle* ih, int visible)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window)
  {
    return;
  }

  if (visible)
  {
    if (ih->data->show_state == IUP_MINIMIZE)
      return;

    InativeHandle* parent = iupDialogGetNativeParent(ih);
    if (parent && [(id)parent isKindOfClass:[NSWindow class]])
    {
      NSWindow* parent_window = (NSWindow*)parent;
      if (![parent_window childWindows] || ![[parent_window childWindows] containsObject:the_window])
        [parent_window addChildWindow:the_window ordered:NSWindowAbove];
    }

    if (iupAttribGetBoolean(ih, "SHOWNOACTIVATE"))
    {
      [the_window orderFront:nil];
    }
    else
    {
      [the_window makeKeyAndOrderFront:nil];
    }

    /* no resize event fires on show, so run the settling relayout once here */
    if (!iupAttribGet(ih, "_IUPCOCOA_FIRSTLAYOUT"))
    {
      iupAttribSet(ih, "_IUPCOCOA_FIRSTLAYOUT", "1");
      ih->data->ignore_resize = 1;
      IupRefresh(ih);
      ih->data->ignore_resize = 0;
    }
  }
  else
  {
    Ihandle* parent_ih = IupGetAttributeHandle(ih, "PARENTDIALOG");
    NSWindow* parent_window = nil;

    if (iupObjectCheck(parent_ih))
    {
      parent_window = iupcocoaDialogGetWindow(parent_ih);
    }

    if (!parent_window)
    {
      parent_window = [the_window parentWindow];
      if (parent_window)
      {
        parent_ih = (Ihandle*)objc_getAssociatedObject(parent_window, IHANDLE_ASSOCIATED_OBJ_KEY);
      }
    }

    if (parent_window && iupObjectCheck(parent_ih))
    {
      [NSApp activateIgnoringOtherApps:YES];
      [parent_window makeKeyAndOrderFront:nil];
    }

    [the_window orderOut:nil];

    if (parent_window && iupObjectCheck(parent_ih))
    {
      IupSetFocus(parent_ih);
    }
  }
}

IUP_SDK_API void iupdrvDialogGetPosition(Ihandle *ih, InativeHandle* handle, int *x, int *y)
{
  NSWindow* the_window = handle ? (NSWindow*)handle : iupcocoaDialogGetWindow(ih);
  if (!the_window) return;

  NSRect the_rect = [the_window frame];

  if (x) *x = the_rect.origin.x;
  if (y) *y = iupcocoaComputeIupScreenHeightFromCartesian(the_rect.origin.y + the_rect.size.height);
}

IUP_SDK_API void iupdrvDialogSetPosition(Ihandle *ih, int x, int y)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return;

  int inverted_y = iupcocoaComputeCartesianScreenHeightFromIup(y);
  [the_window setFrameTopLeftPoint:NSMakePoint(x, inverted_y)];
}

IUP_SDK_API void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu)
{
  *menu = 0; /* In Cocoa, the menu bar is not part of the window's decoration height. */

  NSWindowStyleMask style_mask = 0;
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);

  if (the_window)
    style_mask = [the_window styleMask];
  else
    style_mask = cocoaDialogGetStyleMask(ih);

  if (iupAttribGetBoolean(ih, "CUSTOMFRAME") || iupAttribGetBoolean(ih, "CUSTOMFRAMESIMULATE"))
  {
    style_mask = NSWindowStyleMaskBorderless;
  }

  /* Using a sample content rectangle, we ask Cocoa for the corresponding frame rectangle. */
  /* The difference between them gives us the total size of the decorations. */
  NSRect sample_content_rect = NSMakeRect(0, 0, 100, 100);
  NSRect sample_frame_rect = [NSWindow frameRectForContentRect:sample_content_rect styleMask:style_mask];

  int total_decor_width = (int)round(sample_frame_rect.size.width - sample_content_rect.size.width);
  int total_decor_height = (int)round(sample_frame_rect.size.height - sample_content_rect.size.height);

  /* Translate these total decoration sizes into IUP's `border` and `caption` model. */
  /* The IUP layout engine formulas assume: */
  /* total_decor_width = 2 * border */
  /* total_decor_height = caption + 2 * border */
  /* We derive our values to satisfy these formulas. */

  *border = total_decor_width / 2;
  *caption = total_decor_height - (2 * (*border));
  if (*caption < 0)
  {
    *caption = 0;
  }

  if (iupAttribGetBoolean(ih, "HIDETITLEBAR"))
  {
    *caption = 0;
  }
}

IUP_SDK_API int iupdrvDialogSetPlacement(Ihandle* ih)
{
  id root_object = (id)ih->handle;
  if([root_object isKindOfClass:[NSStatusItem class]] || !root_object) return 0;

  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  char* placement;
  int old_state = ih->data->show_state;

  ih->data->show_state = IUP_SHOW;

  if (iupAttribGetBoolean(ih, "FULLSCREEN"))
  {
    if (!([the_window styleMask] & NSWindowStyleMaskFullScreen))
    {
      [the_window toggleFullScreen:nil];
    }
    return 1;
  }

  if ([the_window styleMask] & NSWindowStyleMaskFullScreen)
  {
    [the_window toggleFullScreen:nil];
  }

  placement = iupAttribGet(ih, "PLACEMENT");
  if (!placement)
  {
    if (old_state == IUP_MAXIMIZE || old_state == IUP_MINIMIZE)
      ih->data->show_state = IUP_RESTORE;

    if ([the_window isZoomed])
      [the_window zoom:nil];
    if ([the_window isMiniaturized])
      [the_window deminiaturize:nil];

    if ((iupAttribGetBoolean(ih, "CUSTOMFRAME") || iupAttribGetBoolean(ih, "CUSTOMFRAMESIMULATE")) && iupDialogCustomFrameRestore(ih))
    {
      ih->data->show_state = IUP_RESTORE;
      return 1;
    }

    return 0;
  }

  if ((iupAttribGetBoolean(ih, "CUSTOMFRAME") || iupAttribGetBoolean(ih, "CUSTOMFRAMESIMULATE")) && iupStrEqualNoCase(placement, "MAXIMIZED"))
  {
    iupDialogCustomFrameMaximize(ih);
    iupAttribSet(ih, "PLACEMENT", NULL);
    ih->data->show_state = IUP_MAXIMIZE;
    return 1;
  }

  if (iupStrEqualNoCase(placement, "MINIMIZED"))
  {
    ih->data->show_state = IUP_MINIMIZE;
    if (![the_window isMiniaturized])
      [the_window miniaturize:nil];
  }
  else if (iupStrEqualNoCase(placement, "MAXIMIZED"))
  {
    ih->data->show_state = IUP_MAXIMIZE;
    if (![the_window isZoomed])
      [the_window zoom:nil];
  }
  else if (iupStrEqualNoCase(placement, "FULL"))
  {
    NSRect screen_frame = [[NSScreen mainScreen] visibleFrame];
    [the_window setFrame:screen_frame display:YES];

    if ([the_window isMiniaturized])
      [the_window deminiaturize:nil];

    if (old_state == IUP_MAXIMIZE || old_state == IUP_MINIMIZE)
      ih->data->show_state = IUP_RESTORE;
  }

  iupAttribSet(ih, "PLACEMENT", NULL);
  return 1;
}

IUP_SDK_API void iupdrvDialogSetParent(Ihandle* ih, InativeHandle* parent)
{
  id root_object = (id)ih->handle;
  if([root_object isKindOfClass:[NSStatusItem class]]) return;

  NSWindow* parent_window = (NSWindow*)parent;
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (the_window && [parent_window isKindOfClass:[NSWindow class]])
  {
    [parent_window addChildWindow:the_window ordered:NSWindowAbove];
  }
}

/****************************************************************
 ********************** Attributes ******************************
 ****************************************************************/

static int cocoaDialogSetMenuAttrib(Ihandle* ih, const char* value)
{
  if (ih->handle && [(NSWindow*)ih->handle isKeyWindow])
  {
    Ihandle* menu_ih = IupGetHandle(value);
    iupcocoaMenuSetApplicationMenu(menu_ih);
  }

  return 1;
}

static void cocoaDialogSetMinMax(Ihandle* ih, int min_w, int min_h, int max_w, int max_h)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window)
    return;

  int decorwidth = 0, decorheight = 0;
  iupDialogGetDecorSize(ih, &decorwidth, &decorheight);

  NSSize minSize = NSMakeSize(1, 1);
  if (min_w > decorwidth)
    minSize.width = min_w - decorwidth;
  if (min_h > decorheight)
    minSize.height = min_h - decorheight;

  NSSize maxSize = NSMakeSize(65535, 65535);
  if (max_w > decorwidth && max_w > minSize.width)
    maxSize.width = max_w - decorwidth;
  if (max_h > decorheight && max_h > minSize.height)
    maxSize.height = max_h - decorheight;

  [the_window setContentMinSize:minSize];
  [the_window setContentMaxSize:maxSize];
}

static int cocoaDialogSetMinSizeAttrib(Ihandle* ih, const char* value)
{
  int min_w = 1, min_h = 1;
  int max_w = 65535, max_h = 65535;
  iupStrToIntInt(value, &min_w, &min_h, 'x');
  iupStrToIntInt(iupAttribGet(ih, "MAXSIZE"), &max_w, &max_h, 'x');

  cocoaDialogSetMinMax(ih, min_w, min_h, max_w, max_h);

  return iupBaseSetMinSizeAttrib(ih, value);
}

static int cocoaDialogSetMaxSizeAttrib(Ihandle* ih, const char* value)
{
  int min_w = 1, min_h = 1;
  int max_w = 65535, max_h = 65535;
  iupStrToIntInt(value, &max_w, &max_h, 'x');
  iupStrToIntInt(iupAttribGet(ih, "MINSIZE"), &min_w, &min_h, 'x');

  cocoaDialogSetMinMax(ih, min_w, min_h, max_w, max_h);

  return iupBaseSetMaxSizeAttrib(ih, value);
}

static char* cocoaDialogGetClientSizeAttrib(Ihandle *ih)
{
  if (ih->handle)
  {
    NSWindow* the_window = iupcocoaDialogGetWindow(ih);
    if (the_window)
    {
      NSRect content_rect = [[the_window contentView] bounds];
      int width = (int)content_rect.size.width;
      int height = (int)content_rect.size.height;

      if (iupAttribGetBoolean(ih, "CUSTOMFRAMEDRAW"))
      {
        int border, caption, menu;
        iupdrvDialogGetDecoration(ih, &border, &caption, &menu);
        width -= 2 * border;
        height -= caption + menu + 2 * border;
      }

      if (width < 0) width = 0;
      if (height < 0) height = 0;

      return iupStrReturnIntInt(width, height, 'x');
    }
  }

  return iupDialogGetClientSizeAttrib(ih);
}

static char* cocoaDialogGetClientOffsetAttrib(Ihandle *ih)
{
  if (iupAttribGetBoolean(ih, "CUSTOMFRAMEDRAW"))
  {
    int border, caption, menu;
    iupdrvDialogGetDecoration(ih, &border, &caption, &menu);

    int x = border;
    int y = border + caption + menu;

    return iupStrReturnIntInt(x, y, 'x');
  }

  return "0x0";
}

static char* cocoaDialogGetResizeAttrib(Ihandle* ih)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return iupAttribGet(ih, "RESIZE");

  NSWindowStyleMask style_mask = [the_window styleMask];
  return iupStrReturnBoolean(style_mask & NSWindowStyleMaskResizable);
}

static int cocoaDialogSetResizeAttrib(Ihandle* ih, const char* value)
{
  cocoaDialogUpdateStyleMask(ih);
  return 1;
}

static int cocoaDialogSetMinBoxAttrib(Ihandle* ih, const char* value)
{
  cocoaDialogUpdateStyleMask(ih);
  return 1;
}

static int cocoaDialogSetMaxBoxAttrib(Ihandle* ih, const char* value)
{
  cocoaDialogUpdateStyleMask(ih);
  return 1;
}

static int cocoaDialogSetMenuBoxAttrib(Ihandle* ih, const char* value)
{
  cocoaDialogUpdateStyleMask(ih);
  return 1;
}

static int cocoaDialogSetBorderAttrib(Ihandle* ih, const char* value)
{
  cocoaDialogUpdateStyleMask(ih);
  return 1;
}

static int cocoaDialogSetTitleAttrib(Ihandle* ih, const char* value)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (the_window)
  {
    NSString* ns_string = value ? [NSString stringWithUTF8String:value] : @"";
    [the_window setTitle:ns_string];
  }

  if (iupAttribGetBoolean(ih, "CUSTOMFRAME") || iupAttribGetBoolean(ih, "CUSTOMFRAMESIMULATE"))
    return 0;

  return 1;
}

static int cocoaDialogSetFullScreenAttrib(Ihandle* ih, const char* value)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return 0;

  if (iupStrBoolean(value))
  {
    if (!iupAttribGet(ih, "_IUPCOCOA_FS_STYLE"))
    {
      iupAttribSetStr(ih, "_IUPCOCOA_FS_MAXBOX", iupAttribGet(ih, "MAXBOX"));
      iupAttribSetStr(ih, "_IUPCOCOA_FS_MINBOX", iupAttribGet(ih, "MINBOX"));
      iupAttribSetStr(ih, "_IUPCOCOA_FS_MENUBOX", iupAttribGet(ih, "MENUBOX"));
      iupAttribSetStr(ih, "_IUPCOCOA_FS_RESIZE", iupAttribGet(ih, "RESIZE"));
      iupAttribSetStr(ih, "_IUPCOCOA_FS_BORDER", iupAttribGet(ih, "BORDER"));
      iupAttribSetStr(ih, "_IUPCOCOA_FS_TITLE", iupAttribGet(ih, "TITLE"));

      iupAttribSetStr(ih, "_IUPCOCOA_FS_X", IupGetAttribute(ih, "X"));
      iupAttribSetStr(ih, "_IUPCOCOA_FS_Y", IupGetAttribute(ih, "Y"));
      iupAttribSetStr(ih, "_IUPCOCOA_FS_SIZE", IupGetAttribute(ih, "RASTERSIZE"));

      iupAttribSet(ih, "MAXBOX", "NO");
      iupAttribSet(ih, "MINBOX", "NO");
      iupAttribSet(ih, "MENUBOX", "NO");
      IupSetAttribute(ih, "TITLE", NULL);
      iupAttribSet(ih, "RESIZE", "NO");
      iupAttribSet(ih, "BORDER", "NO");

      [the_window toggleFullScreen:nil];

      iupAttribSet(ih, "_IUPCOCOA_FS_STYLE", "YES");
    }
  }
  else
  {
    if (iupAttribGet(ih, "_IUPCOCOA_FS_STYLE"))
    {
      iupAttribSet(ih, "_IUPCOCOA_FS_STYLE", NULL);

      iupAttribSetStr(ih, "MAXBOX", iupAttribGet(ih, "_IUPCOCOA_FS_MAXBOX"));
      iupAttribSetStr(ih, "MINBOX", iupAttribGet(ih, "_IUPCOCOA_FS_MINBOX"));
      iupAttribSetStr(ih, "MENUBOX",iupAttribGet(ih, "_IUPCOCOA_FS_MENUBOX"));
      IupSetAttribute(ih, "TITLE", iupAttribGet(ih, "_IUPCOCOA_FS_TITLE"));
      iupAttribSetStr(ih, "RESIZE", iupAttribGet(ih, "_IUPCOCOA_FS_RESIZE"));
      iupAttribSetStr(ih, "BORDER", iupAttribGet(ih, "_IUPCOCOA_FS_BORDER"));

      [the_window toggleFullScreen:nil];

      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (!iupObjectCheck(ih))
          return;
        NSWindow* cur_window = iupcocoaDialogGetWindow(ih);
        if (!cur_window)
          return;
        int x = iupAttribGetInt(ih, "_IUPCOCOA_FS_X");
        int y = iupAttribGetInt(ih, "_IUPCOCOA_FS_Y");
        int w = IupGetInt(ih, "_IUPCOCOA_FS_SIZE");
        int h = IupGetInt2(ih, "_IUPCOCOA_FS_SIZE");

        if (w > 0 && h > 0)
        {
          iupdrvDialogSetPosition(ih, x, y);
          NSRect frame = [cur_window frame];
          frame.size.width = w;
          frame.size.height = h;
          [cur_window setFrame:frame display:YES];
        }
      });

      iupAttribSet(ih, "_IUPCOCOA_FS_MAXBOX", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_MINBOX", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_MENUBOX", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_TITLE", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_RESIZE", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_BORDER", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_X", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_Y", NULL);
      iupAttribSet(ih, "_IUPCOCOA_FS_SIZE", NULL);
    }
  }

  return 1;
}

static char* cocoaDialogGetFullScreenAttrib(Ihandle* ih)
{
  return iupAttribGet(ih, "_IUPCOCOA_FULLSCREEN");
}

static int cocoaDialogSetDialogHintAttrib(Ihandle* ih, const char* value)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return 0;

  if (iupStrBoolean(value))
    [the_window setLevel:NSFloatingWindowLevel];
  else
    [the_window setLevel:NSNormalWindowLevel];

  return 1;
}

static int cocoaDialogSetHideTitleBarAttrib(Ihandle *ih, const char *value)
{
  NSWindow* window = iupcocoaDialogGetWindow(ih);
  if (!window) return 0;

#ifndef GNUSTEP
  BOOL hide = (BOOL)iupStrBoolean(value);
  if (hide)
  {
    window.styleMask |= NSWindowStyleMaskFullSizeContentView;
    window.titlebarAppearsTransparent = YES;
    window.titleVisibility = NSWindowTitleHidden;
    [[window standardWindowButton:NSWindowCloseButton] setHidden:YES];
    [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
    [[window standardWindowButton:NSWindowZoomButton] setHidden:YES];
  }
  else
  {
    window.styleMask &= ~NSWindowStyleMaskFullSizeContentView;
    window.titlebarAppearsTransparent = NO;
    window.titleVisibility = NSWindowTitleVisible;
    [[window standardWindowButton:NSWindowCloseButton] setHidden:NO];
    [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:NO];
    [[window standardWindowButton:NSWindowZoomButton] setHidden:NO];
  }
#else
  (void)value;
#endif
  return 1;
}

static char* cocoaDialogGetActiveWindowAttrib(Ihandle* ih)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window)
    return NULL;

  return iupStrReturnBoolean([the_window isKeyWindow]);
}

static int cocoaDialogSetTopMostAttrib(Ihandle *ih, const char *value)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return 0;

  if (iupStrBoolean(value))
    [the_window setLevel:NSStatusWindowLevel];
  else
    [the_window setLevel:NSNormalWindowLevel];
  return 1;
}

static int cocoaDialogSetBringFrontAttrib(Ihandle *ih, const char *value)
{
  if (iupStrBoolean(value))
  {
    NSWindow* the_window = iupcocoaDialogGetWindow(ih);
    if (the_window)
    {
      [NSApp activateIgnoringOtherApps:YES];
      [the_window makeKeyAndOrderFront:nil];
    }
  }
  return 0;
}

static int cocoaDialogSetOpacityAttrib(Ihandle *ih, const char *value)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return 0;

  int opacity;
  if (iupStrToInt(value, &opacity))
  {
    if (opacity < 0) opacity = 0;
    if (opacity > 255) opacity = 255;
    [the_window setAlphaValue:(CGFloat)opacity / 255.0];
    return 1;
  }
  return 0;
}

static int cocoaDialogSetIconAttrib(Ihandle* ih, const char *value)
{
  NSImage* icon = iupImageGetIcon(value);
  [NSApp setApplicationIconImage:icon];
  return 1;
}

static int cocoaDialogSetBgColorAttrib(Ihandle* ih, const char* value)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return 0;

  unsigned char r, g, b;
  if (!iupStrToRGB(value, &r, &g, &b))
    return 0;

  if (iupStrEqual(value, IupGetGlobal("DLGBGCOLOR")))
    [the_window setBackgroundColor:[NSColor windowBackgroundColor]];
  else
  {
    NSColor* color = [NSColor colorWithSRGBRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0];
    [the_window setBackgroundColor:color];
  }
  return 1;
}

static int cocoaDialogSetBackgroundAttrib(Ihandle* ih, const char* value)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window) return 0;

  unsigned char r, g, b;
  if (iupStrToRGB(value, &r, &g, &b))
  {
    NSColor* color = [NSColor colorWithSRGBRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0];
    [the_window setBackgroundColor:color];
    return 1;
  }
  else
  {
    NSImage* image = iupImageGetImage(value, ih, 0, NULL);
    if (image)
    {
      if (iupAttribGetBoolean(ih, "BACKIMAGEZOOM"))
      {
        NSSize windowSize = [[the_window contentView] bounds].size;
        if (windowSize.width > 0 && windowSize.height > 0)
        {
          NSImage* scaledImage = [[NSImage alloc] initWithSize:windowSize];
          [scaledImage lockFocus];
          [image drawInRect:NSMakeRect(0, 0, windowSize.width, windowSize.height)
                   fromRect:NSZeroRect
                  operation:NSCompositingOperationCopy
                   fraction:1.0];
          [scaledImage unlockFocus];
          [the_window setBackgroundColor:[NSColor colorWithPatternImage:scaledImage]];
          [scaledImage release];
        }
      }
      else
        [the_window setBackgroundColor:[NSColor colorWithPatternImage:image]];
      return 1;
    }
  }
  return 0;
}

static int cocoaDialogSetShapeImageAttrib(Ihandle *ih, const char *value)
{
  NSWindow* window = iupcocoaDialogGetWindow(ih);
  if (!window) return 0;

  if (!value)
  {
    cocoaDialogUpdateStyleMask(ih);
    [window setOpaque:YES];
    [window setBackgroundColor:[NSColor windowBackgroundColor]];
    return 1;
  }

  NSImage* image = iupImageGetImage(value, ih, 0, NULL);
  if (!image)
    return 0;

  [window setStyleMask:NSWindowStyleMaskBorderless];
  [window setOpaque:NO];
  [window setBackgroundColor:[NSColor clearColor]];
  [window setHasShadow:YES];
  [window setMovableByWindowBackground:YES];

  NSImageView* imageView = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 0, image.size.width, image.size.height)];
  [imageView setImage:image];
  [imageView setImageFrameStyle:NSImageFrameNone];
  [imageView setImageScaling:NSImageScaleNone];

  [window setContentView:imageView];
  [window setContentSize:image.size];
  [imageView release];

  return 1;
}

static int cocoaDialogSetOpacityImageAttrib(Ihandle *ih, const char *value)
{
  return cocoaDialogSetShapeImageAttrib(ih, value);
}

static int cocoaDialogSetCustomFrameAttrib(Ihandle *ih, const char *value)
{
  NSWindow* window = iupcocoaDialogGetWindow(ih);
  if (!window) return 0;

#ifndef GNUSTEP
  if (iupStrBoolean(value))
  {
    iupDialogCustomFrameSimulateCheckCallbacks(ih);

    [window setStyleMask:[window styleMask] | NSWindowStyleMaskFullSizeContentView];
    window.titlebarAppearsTransparent = YES;
    window.titleVisibility = NSWindowTitleHidden;
    [[window standardWindowButton:NSWindowCloseButton] setHidden:YES];
    [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
    [[window standardWindowButton:NSWindowZoomButton] setHidden:YES];
    [window setHasShadow:YES];
  }
  else
  {
    [window setStyleMask:[window styleMask] & ~NSWindowStyleMaskFullSizeContentView];
    window.titlebarAppearsTransparent = NO;
    window.titleVisibility = NSWindowTitleVisible;
    [[window standardWindowButton:NSWindowCloseButton] setHidden:NO];
    [[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:NO];
    [[window standardWindowButton:NSWindowZoomButton] setHidden:NO];
  }
#else
  (void)value;
#endif
  return 1;
}

static char* cocoaDialogGetMaximizedAttrib(Ihandle *ih)
{
  if (iupAttribGetBoolean(ih, "CUSTOMFRAME") || iupAttribGetBoolean(ih, "CUSTOMFRAMESIMULATE"))
    return iupAttribGet(ih, "MAXIMIZED");

  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window)
    return NULL;

  return iupStrReturnBoolean([the_window isZoomed]);
}

static char* cocoaDialogGetMinimizedAttrib(Ihandle *ih)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window)
    return NULL;

  return iupStrReturnBoolean([the_window isMiniaturized]);
}

static char* cocoaDialogGetNSViewAttrib(Ihandle *ih)
{
  NSWindow* the_window = iupcocoaDialogGetWindow(ih);
  if (!the_window)
    return NULL;

  return (char*)[the_window contentView];
}

/****************************************************************
 ********************** Class Methods ***************************
 ****************************************************************/

static void cocoaDialogSetChildrenPositionMethod(Ihandle* ih, int x, int y)
{
  (void)x;
  (void)y;

  if (ih->firstchild)
  {
    char* offset = iupAttribGet(ih, "CHILDOFFSET");
    int offset_x = 0;
    int offset_y = 0;

    if (offset)
      iupStrToIntInt(offset, &offset_x, &offset_y, 'x');

    iupBaseSetPosition(ih->firstchild, ih->firstchild->x + offset_x, ih->firstchild->y + offset_y);
  }
}

static int cocoaDialogMapMethod(Ihandle* ih)
{
  InativeHandle* parent;
  NSWindowStyleMask style_mask = cocoaDialogGetStyleMask(ih);

  NSWindow* the_window = [[IupCocoaWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100)
                                                   styleMask:style_mask
                                                     backing:NSBackingStoreBuffered
                                                       defer:YES];

  [the_window setReleasedWhenClosed:NO];
  [the_window setAutorecalculatesKeyViewLoop:YES];

  [[the_window contentView] setAutoresizesSubviews:NO];

  ih->handle = (__bridge void*)the_window;
  iupcocoaSetAssociatedViews(ih, [the_window contentView], [the_window contentView]);

  IupCocoaWindowDelegate* window_delegate = [[IupCocoaWindowDelegate alloc] init];
  [the_window setDelegate:window_delegate];
  objc_setAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY, (id)ih, OBJC_ASSOCIATION_ASSIGN);

  parent = iupDialogGetNativeParent(ih);
  if (parent && [(id)parent isKindOfClass:[NSWindow class]])
  {
    [[NSNotificationCenter defaultCenter] addObserver:window_delegate
                                             selector:@selector(cocoaDialogChildDestroyNotification:)
                                                 name:NSWindowWillCloseNotification
                                               object:the_window];
  }

  NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
  [nc addObserver:window_delegate selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:the_window];
  [nc addObserver:window_delegate selector:@selector(windowDidMove:) name:NSWindowDidMoveNotification object:the_window];
  [nc addObserver:window_delegate selector:@selector(windowDidMiniaturize:) name:NSWindowDidMiniaturizeNotification object:the_window];
  [nc addObserver:window_delegate selector:@selector(windowDidDeminiaturize:) name:NSWindowDidDeminiaturizeNotification object:the_window];
  [nc addObserver:window_delegate selector:@selector(windowWillEnterFullScreen:) name:NSWindowWillEnterFullScreenNotification object:the_window];
  [nc addObserver:window_delegate selector:@selector(windowDidEnterFullScreen:) name:NSWindowDidEnterFullScreenNotification object:the_window];
  [nc addObserver:window_delegate selector:@selector(windowDidExitFullScreen:) name:NSWindowDidExitFullScreenNotification object:the_window];
  [nc addObserver:window_delegate selector:@selector(windowDidBecomeKey:) name:NSWindowDidBecomeKeyNotification object:the_window];

  [the_window addObserver:window_delegate
               forKeyPath:@"effectiveAppearance"
                  options:NSKeyValueObservingOptionNew
                  context:IupCocoaAppearanceContext];

#ifndef GNUSTEP
  if (iupAttribGetBoolean(ih, "CUSTOMFRAME"))
  {
    iupDialogCustomFrameSimulateCheckCallbacks(ih);

    the_window.titlebarAppearsTransparent = YES;
    the_window.titleVisibility = NSWindowTitleHidden;
    [[the_window standardWindowButton:NSWindowCloseButton] setHidden:YES];
    [[the_window standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
    [[the_window standardWindowButton:NSWindowZoomButton] setHidden:YES];
    [the_window setHasShadow:YES];
  }
#endif

  NSView* content_view = [the_window contentView];
  cocoaTargetDropCreateAssociatedData(ih, content_view, content_view);

  {
    NSTrackingArea* tracking_area = [[NSTrackingArea alloc] initWithRect:[content_view bounds]
                                                                 options:NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect
                                                                   owner:the_window
                                                                userInfo:nil];
    [content_view addTrackingArea:tracking_area];
    [tracking_area release];
  }

  if (IupGetCallback(ih, "DROPFILES_CB"))
    iupAttribSet(ih, "DROPFILESTARGET", "YES");

  iupAttribSet(ih, "VISIBLE", NULL);

  return IUP_NOERROR;
}

static void cocoaDialogUnMapMethod(Ihandle* ih)
{
  if (!ih->handle) return;

  if (ih->data->menu)
  {
    ih->data->menu->handle = NULL;
    IupDestroy(ih->data->menu);
    ih->data->menu = NULL;
  }

  NSWindow* the_window = (__bridge NSWindow*)ih->handle;

  NSWindow* parent_window = [the_window parentWindow];
  if (parent_window)
  {
    [[NSNotificationCenter defaultCenter] removeObserver:[the_window delegate]
                                                     name:NSWindowWillCloseNotification
                                                   object:the_window];
    [parent_window removeChildWindow:the_window];
  }


  @try
  {
    [the_window removeObserver:[the_window delegate]
                    forKeyPath:@"effectiveAppearance"
                       context:IupCocoaAppearanceContext];
  }
  @catch (NSException *exception)
  {
    /* Observer might not have been added, ignore */
  }

  [[NSNotificationCenter defaultCenter] removeObserver:[the_window delegate] name:nil object:the_window];

  objc_setAssociatedObject(the_window, IHANDLE_ASSOCIATED_OBJ_KEY, nil, OBJC_ASSOCIATION_ASSIGN);

  [the_window close];

  IupCocoaWindowDelegate* window_delegate = [the_window delegate];
  [the_window setDelegate:nil];
  [window_delegate release];

  cocoaTargetDropDestroyAssociatedData(ih);

  iupcocoaSetAssociatedViews(ih, nil, nil);
  [the_window release];
  ih->handle = NULL;
}

static void cocoaDialogLayoutUpdateMethod(Ihandle *ih)
{
  int width, height;

  id root_object = (id)ih->handle;
  if([root_object isKindOfClass:[NSStatusItem class]] || !root_object) return;

  if(ih->data->ignore_resize || iupAttribGet(ih, "_IUPCOCOA_FS_STYLE"))
    return;

  ih->data->ignore_resize = 1;

  NSWindow* the_window = iupcocoaDialogGetWindow(ih);

  if (!the_window)
  {
    ih->data->ignore_resize = 0;
    return;
  }

  if ([the_window isMiniaturized])
  {
    ih->data->ignore_resize = 0;
    return;
  }

  if ([the_window isZoomed])
  {
    NSRect zoomed_frame = [the_window frame];

    /* Compare the desired total size from IUP with the current zoomed frame size. */
    /* If they differ significantly, we should unzoom before applying the new size. */
    if (abs(ih->currentwidth - (int)zoomed_frame.size.width) > 10 ||
        abs(ih->currentheight - (int)zoomed_frame.size.height) > 10)
    {
      /* Unzoom before resizing */
      [the_window setStyleMask:[the_window styleMask] & ~NSWindowStyleMaskFullScreen];
      [the_window zoom:nil];
      /* Clear the zoom restore frame */
      objc_setAssociatedObject(the_window, &IUPCocoaZoomRestoreFrameKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
      /* Update show state */
      ih->data->show_state = IUP_RESTORE;
    }
    else
    {
      /* Size is similar to zoomed size, don't unzoom */
      ih->data->ignore_resize = 0;
      return;
    }
  }

  if (iupAttribGetBoolean(ih, "CUSTOMFRAME"))
  {
    /* With CUSTOMFRAME + FullSizeContentView, the content view fills the entire
       window frame. Set the frame directly so the window size matches exactly
       what IUP calculated (which has no decoration space). */
    [the_window setContentMinSize:NSMakeSize(1, 1)];
    [the_window setContentMaxSize:NSMakeSize(65535, 65535)];

    NSRect old_frame = [the_window frame];
    NSRect new_frame = NSMakeRect(old_frame.origin.x,
                                   old_frame.origin.y + old_frame.size.height - ih->currentheight,
                                   ih->currentwidth,
                                   ih->currentheight);
    [the_window setFrame:new_frame display:YES];
  }
  else
  {
    int decor_w = 0, decor_h = 0;
    iupDialogGetDecorSize(ih, &decor_w, &decor_h);

    width = ih->currentwidth - decor_w;
    height = ih->currentheight - decor_h;
    if(width <= 0) width = 1;
    if(height <= 0) height = 1;

    NSSize content_size = NSMakeSize(width, height);

    /* Clear any existing size constraints before resizing */
    [the_window setContentMinSize:NSMakeSize(1, 1)];
    [the_window setContentMaxSize:NSMakeSize(65535, 65535)];

    [the_window setContentSize:content_size];

    if (!iupAttribGetBoolean(ih, "RESIZE"))
    {
      [the_window setContentMinSize:content_size];
      [the_window setContentMaxSize:content_size];
    }
  }

  ih->data->ignore_resize = 0;
}

/****************************************************************
 ******************** Other Attributes **************************
 ****************************************************************/

/* Accent-colored bar across the bottom of the app icon; NSDockTile is per-app singleton. */

typedef enum { IUP_DOCK_NORMAL, IUP_DOCK_PAUSED, IUP_DOCK_ERROR, IUP_DOCK_INDETERMINATE } IupDockState;

@interface IupDockProgressView : NSView
{
  double _percent;            /* 0..1, ignored when INDETERMINATE */
  IupDockState _state;
  CGFloat _marqueeOffset;     /* 0..1, INDETERMINATE animation phase */
  NSTimer* _timer;
}
- (void)setPercent:(double)p;
- (void)setState:(IupDockState)s;
- (void)stopAnimation;
@end

@implementation IupDockProgressView

- (instancetype)init
{
  self = [super initWithFrame:NSMakeRect(0, 0, 128, 128)];
  if (self)
  {
    _percent = 0.0;
    _state = IUP_DOCK_NORMAL;
    _marqueeOffset = 0.0;
    _timer = nil;
  }
  return self;
}

- (void)dealloc
{
  [self stopAnimation];
  [super dealloc];
}

- (void)setPercent:(double)p
{
  if (p < 0.0) p = 0.0;
  if (p > 1.0) p = 1.0;
  _percent = p;
  [self setNeedsDisplay:YES];
  [[NSApp dockTile] display];
}

- (void)setState:(IupDockState)s
{
  _state = s;
  if (s == IUP_DOCK_INDETERMINATE)
  {
    if (!_timer)
    {
      _timer = [[NSTimer scheduledTimerWithTimeInterval:0.05 target:self
        selector:@selector(advanceMarquee:) userInfo:nil repeats:YES] retain];
    }
  }
  else
  {
    [self stopAnimation];
  }
  [self setNeedsDisplay:YES];
  [[NSApp dockTile] display];
}

- (void)stopAnimation
{
  if (_timer) { [_timer invalidate]; [_timer release]; _timer = nil; }
}

- (void)advanceMarquee:(NSTimer*)t
{
  (void)t;
  _marqueeOffset += 0.04;
  if (_marqueeOffset > 1.0) _marqueeOffset -= 1.0;
  [self setNeedsDisplay:YES];
  [[NSApp dockTile] display];
}

- (NSColor*)accentColor
{
  if ([NSColor respondsToSelector:@selector(controlAccentColor)])
    return [NSColor performSelector:@selector(controlAccentColor)];
  return [NSColor colorWithCalibratedRed:0.0 green:0.48 blue:1.0 alpha:1.0];
}

- (void)drawRect:(NSRect)dirty
{
  (void)dirty;
  NSRect bounds = self.bounds;

  NSImage* icon = [NSApp applicationIconImage];
  if (icon)
    [icon drawInRect:bounds fromRect:NSZeroRect operation:NSCompositingOperationCopy fraction:1.0];

  /* Geometry matches the Finder/App Store look: ~10% icon height, bottom-anchored, narrow margins. */
  CGFloat bar_h = bounds.size.height * 0.10;
  CGFloat margin_x = bounds.size.width * 0.10;
  CGFloat margin_y = bounds.size.height * 0.06;
  NSRect track = NSMakeRect(margin_x, margin_y, bounds.size.width - 2 * margin_x, bar_h);
  CGFloat radius = bar_h * 0.5;

  [[NSColor colorWithCalibratedWhite:0.0 alpha:0.45] set];
  [[NSBezierPath bezierPathWithRoundedRect:track xRadius:radius yRadius:radius] fill];

  NSColor* fill_color = nil;
  switch (_state)
  {
    case IUP_DOCK_PAUSED: fill_color = [[self accentColor] colorWithAlphaComponent:0.45]; break;
    case IUP_DOCK_ERROR:  fill_color = [NSColor systemRedColor]; break;
    default:              fill_color = [self accentColor]; break;
  }
  [fill_color set];

  NSRect fill = NSInsetRect(track, 1.0, 1.0);
  CGFloat fill_radius = radius - 1.0;

  if (_state == IUP_DOCK_INDETERMINATE)
  {
    CGFloat block_w = fill.size.width * 0.30;
    CGFloat travel = fill.size.width + block_w;
    CGFloat x = fill.origin.x - block_w + _marqueeOffset * travel;
    NSRect block = NSMakeRect(x, fill.origin.y, block_w, fill.size.height);
    NSRect clip = NSIntersectionRect(block, fill);
    if (!NSIsEmptyRect(clip))
      [[NSBezierPath bezierPathWithRoundedRect:clip xRadius:fill_radius yRadius:fill_radius] fill];
  }
  else
  {
    fill.size.width *= _percent;
    if (fill.size.width >= 1.0)
      [[NSBezierPath bezierPathWithRoundedRect:fill xRadius:fill_radius yRadius:fill_radius] fill];
  }
}

@end

static IupDockProgressView* cocoaDockProgressView(Ihandle *ih)
{
  return (IupDockProgressView*)objc_getAssociatedObject((id)ih->handle, DOCKPROGRESS_ASSOCIATED_OBJ_KEY);
}

static int cocoaDialogSetTaskBarProgressAttrib(Ihandle *ih, const char *value)
{
  if (iupStrBoolean(value))
  {
    IupDockProgressView* view = cocoaDockProgressView(ih);
    if (!view)
    {
      view = [[[IupDockProgressView alloc] init] autorelease];
      objc_setAssociatedObject((id)ih->handle, DOCKPROGRESS_ASSOCIATED_OBJ_KEY, view, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    [[NSApp dockTile] setContentView:view];
    [[NSApp dockTile] display];
  }
  else
  {
    IupDockProgressView* view = cocoaDockProgressView(ih);
    if (view) [view stopAnimation];
    [[NSApp dockTile] setContentView:nil];
    [[NSApp dockTile] display];
    objc_setAssociatedObject((id)ih->handle, DOCKPROGRESS_ASSOCIATED_OBJ_KEY, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  }
  return 1;
}

static int cocoaDialogSetTaskBarProgressStateAttrib(Ihandle *ih, const char *value)
{
  IupDockProgressView* view = cocoaDockProgressView(ih);
  if (!view) return 1;

  if (iupStrEqualNoCase(value, "NOPROGRESS"))
    cocoaDialogSetTaskBarProgressAttrib(ih, "NO");
  else if (iupStrEqualNoCase(value, "INDETERMINATE"))
    [view setState:IUP_DOCK_INDETERMINATE];
  else if (iupStrEqualNoCase(value, "PAUSED"))
    [view setState:IUP_DOCK_PAUSED];
  else if (iupStrEqualNoCase(value, "ERROR"))
    [view setState:IUP_DOCK_ERROR];
  else
    [view setState:IUP_DOCK_NORMAL];
  return 1;
}

static int cocoaDialogSetTaskBarProgressValueAttrib(Ihandle *ih, const char *value)
{
  IupDockProgressView* view = cocoaDockProgressView(ih);
  if (!view) return 1;

  int int_value;
  if (iupStrToInt(value, &int_value))
  {
    if (int_value < 0) int_value = 0;
    if (int_value > 100) int_value = 100;
    [view setPercent:(double)int_value / 100.0];
    if (int_value >= 100)
      cocoaDialogSetTaskBarProgressAttrib(ih, "NO");
  }
  return 1;
}


static int cocoaDialogSetBackImageZoomAttrib(Ihandle* ih, const char* value)
{
  (void)value;
  char* background = iupAttribGet(ih, "BACKGROUND");
  if (background)
    cocoaDialogSetBackgroundAttrib(ih, background);
  return 1;
}

/****************************************************************
 ******************** Class Registration ************************
 ****************************************************************/

IUP_SDK_API void iupdrvDialogInitClass(Iclass* ic)
{
  ic->Map = cocoaDialogMapMethod;
  ic->UnMap = cocoaDialogUnMapMethod;
  ic->LayoutUpdate = cocoaDialogLayoutUpdateMethod;
  ic->SetChildrenPosition = cocoaDialogSetChildrenPositionMethod;

  iupClassRegisterAttribute(ic, "CLIENTSIZE", cocoaDialogGetClientSizeAttrib, iupDialogSetClientSizeAttrib, NULL, NULL, IUPAF_NOT_MAPPED | IUPAF_NO_SAVE | IUPAF_NO_DEFAULTVALUE | IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "CLIENTOFFSET", cocoaDialogGetClientOffsetAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED | IUPAF_NO_DEFAULTVALUE | IUPAF_READONLY | IUPAF_NO_INHERIT);

  iupClassRegisterAttribute(ic, "MENU", NULL, cocoaDialogSetMenuAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "TITLE", NULL, cocoaDialogSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "RESIZE", cocoaDialogGetResizeAttrib, cocoaDialogSetResizeAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "BORDER", NULL, cocoaDialogSetBorderAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "MINBOX", NULL, cocoaDialogSetMinBoxAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "MAXBOX", NULL, cocoaDialogSetMaxBoxAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "MENUBOX", NULL, cocoaDialogSetMenuBoxAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "MINSIZE", NULL, cocoaDialogSetMinSizeAttrib, IUPAF_SAMEASSYSTEM, "1x1", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "MAXSIZE", NULL, cocoaDialogSetMaxSizeAttrib, IUPAF_SAMEASSYSTEM, "65535x65535", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "FULLSCREEN", cocoaDialogGetFullScreenAttrib, cocoaDialogSetFullScreenAttrib, NULL, NULL, IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "CUSTOMFRAME", NULL, cocoaDialogSetCustomFrameAttrib, NULL, "NO", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "SHOWNOACTIVATE", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "DIALOGHINT", NULL, cocoaDialogSetDialogHintAttrib, NULL, NULL, IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "HELPBUTTON", NULL, NULL, NULL, NULL, IUPAF_NOT_SUPPORTED|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "TOOLBOX", NULL, NULL, NULL, NULL, IUPAF_NOT_SUPPORTED|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "HIDETITLEBAR", NULL, cocoaDialogSetHideTitleBarAttrib, NULL, NULL, IUPAF_NO_INHERIT);

  iupClassRegisterAttribute(ic, "BGCOLOR", NULL, cocoaDialogSetBgColorAttrib, "DLGBGCOLOR", NULL, IUPAF_DEFAULT);
  iupClassRegisterAttribute(ic, "BACKGROUND", NULL, cocoaDialogSetBackgroundAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "BACKIMAGEZOOM", NULL, cocoaDialogSetBackImageZoomAttrib, NULL, NULL, IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "ICON", NULL, cocoaDialogSetIconAttrib, NULL, NULL, IUPAF_IHANDLENAME|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "OPACITY", NULL, cocoaDialogSetOpacityAttrib, NULL, NULL, IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "SHAPEIMAGE", NULL, cocoaDialogSetShapeImageAttrib, NULL, NULL, IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "OPACITYIMAGE", NULL, cocoaDialogSetOpacityImageAttrib, NULL, NULL, IUPAF_NO_INHERIT);

  iupClassRegisterAttribute(ic, "TOPMOST", NULL, cocoaDialogSetTopMostAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "ACTIVEWINDOW", cocoaDialogGetActiveWindowAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "NSVIEW", cocoaDialogGetNSViewAttrib, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT|IUPAF_READONLY);
  iupClassRegisterAttribute(ic, "MAXIMIZED", cocoaDialogGetMaximizedAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "MINIMIZED", cocoaDialogGetMinimizedAttrib, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "BRINGFRONT", NULL, cocoaDialogSetBringFrontAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);

  iupClassRegisterAttribute(ic, "TASKBARPROGRESS", NULL, cocoaDialogSetTaskBarProgressAttrib, NULL, NULL, IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "TASKBARPROGRESSSTATE", NULL, cocoaDialogSetTaskBarProgressStateAttrib, IUPAF_SAMEASSYSTEM, "NORMAL", IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "TASKBARPROGRESSVALUE", NULL, cocoaDialogSetTaskBarProgressValueAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);

  iupClassRegisterAttribute(ic, "COMPOSITED", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_READONLY|IUPAF_NO_INHERIT);

  iupClassRegisterAttribute(ic, "SAVEUNDER", NULL, NULL, IUPAF_SAMEASSYSTEM, NULL, IUPAF_NOT_SUPPORTED|IUPAF_NO_INHERIT);
  iupClassRegisterAttribute(ic, "CONTROL", NULL, NULL, IUPAF_SAMEASSYSTEM, NULL, IUPAF_NOT_SUPPORTED|IUPAF_NO_INHERIT);
}
