/*
 * COPYRIGHT: 1992 David C. Navas                                       *
 *            License granted to SwRI to modify and use as per site     *
 *             license.  Further distribution license rights granted    *
 *             upon receipt of agreed upon compensation.                *
 *            All Other Rights Reserved by Author                       *
 */

#ifndef SHADOW_GUI_H
#define SHADOW_GUI_H

#include <exec/exec.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <shadow/watcher.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/gadtools_pragmas.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>

/*
 * ==========================================================================
 * =                                                                        =
 * =           Class definition for the GUI process.                        =
 * =                                                                        =
 * ==========================================================================
 */
#ifndef GUIPROCESS_CLASS
#define GUIPROCESS_CLASS "gui process class"
#endif

#ifndef ASLPROCESS_CLASS
#define ASLPROCESS_CLASS "asl process class"
#endif

#ifndef GUITASK
#define GUITASK "Gui Task\0"
#endif

#define ATTR_GUIPROCESS "shared window port\0"
struct GuiProcess {
   struct MsgPort *guip_port;
};

void HandleIntuiMessage(struct IntuiMessage *intui);
void GUIThreadStart(void);


/*
 * ==========================================================================
 * =                                                                        =
 * =           Class definition for GUI type of objects.                    =
 * =                                                                        =
 * ==========================================================================
 */
#ifndef GUI_CLASS
#define GUI_CLASS        "gui class"
#endif

#define ATTR_GUICHILDREN   "gui children\0"
#define ATTR_GUISTRUCT     "gui struct\0"
struct GUIStruct {
   OBJECT gui_parent;
   char   *gui_moniker;
};

#define ATTR_GUIOUTPUT     "gui output\0"
struct OutputStruct {
   OBJECT out_object;
   char   *out_method;
};

extern ARGUMENT_TAG REF_GuiInitMethod[];

void *GuiInitMethod(METHOD_ARGS, OBJECT parent,
                                 char   *name,
                                 OBJECT out_object,
                                 char   *out_method);
void GuiRemoveMethod(METHOD_ARGS);
void GuiDestroyMethod(METHOD_ARGS);

/*
 * The following are responsible for these:
 *    a) Setting the focus object.
 *    b) notification of state change.
 */

#define METH_GUI_RESIZE  "Resize Gui Element"
#define METH_GUI_FOCUS   "Grab Focus"
extern ARGUMENT_TAG REF_GuiGrabFocus[];
void GuiGrabFocus(METHOD_ARGS, long flag);

struct GuiIntuiHeader {
    /* the Class bits correspond directly with the IDCMP Flags, except for the
     * special bit LONELYMESSAGE (defined below)
     */
    ULONG gih_Class;

    /* the Code field is for special values like MENU number */
    USHORT gih_Code;

    /* the Qualifier field is a copy of the current InputEvent's Qualifier */
    USHORT gih_Qualifier;

};

struct GuiIntuiMouse {
    /* when getting mouse movement reports, any event you get will have the
     * the mouse coordinates in these variables.  the coordinates are relative
     * to the upper-left corner of your Window (GIMMEZEROZERO notwithstanding)
     */
    SHORT gim_MouseX,
          gim_MouseY;

};

struct GuiIntuiTime {
    /* the time values are copies of the current system clock time.  Micros
     * are in units of microseconds, Seconds in seconds.
     */
    ULONG gii_Seconds, gii_Micros;

};

struct GuiIntuiMsg {
   struct GuiIntuiHeader   gii_header;

#define gii_Class          gii_header.gih_Class
#define gii_Code           gii_header.gih_Code
#define gii_Qualifier      gii_header.gih_Qualifier

    /* IAddress contains particular addresses for Intuition functions, like
     * the pointer to the Gadget or the Screen
     * This is likely to be meaningless....  Particularly when sent
     *  Asynchronously.  subclassed methods should always be called!
     */
   APTR                    gii_IAddress;

   struct GuiIntuiMouse    gii_mouse;

#define gii_MouseX         gii_mouse.gim_MouseX
#define gii_MouseY         gii_mouse.gim_MouseY

   struct GuiIntuiTime     gii_time;

#define gii_Seconds        gii_time.git_Seconds
#define gii_Micros         gii_time.git_Micros
};

#define METH_GUI_STATE   "Intuition update"
extern ARGUMENT_TAG REF_GuiStateNotify[];
void GuiStateNotify(METHOD_ARGS, struct GuiIntuiMsg *info, OBJECT window);

/*
 * ==========================================================================
 * =                                                                        =
 * =           Class definition for window objects.                         =
 * =                                                                        =
 * ==========================================================================
 */

#ifndef WINDOW_CLASS
#define WINDOW_CLASS     "Window Class\0"
#endif

#define ATTR_WINDOW     "window attributes"
struct WindowObject {
   struct Window *wo_window;
   /*
    * Should really be a pointer to a screen Object, but....
    */
   struct VisualInfo *wo_vi;

   /*
    * Will eventually need menus here, too.
    */
   struct Gadget *wo_rootGadget, *wo_lastGadget;
   struct WindowLocation *wo_wl;
   OBJECT                wo_wlObject;
   char                  *wo_localWindowName;
};

struct WindowLocation {
   long  wl_left,
         wl_top,
         wl_width,
         wl_height,
         wl_xInc,
         wl_yInc,
         wl_flags;

/*
 * Internal use only all below.
 */

   short wl_localLeft,
         wl_localTop,
         wl_localWidth,
         wl_localHeight;
};

/*
 * Put in wl_* (not flags) for better control of window overlapping.
 *
 * PERCENT for top/left/width/height uses the low 16bits as a percentage
 *  value from screen location.
 * BORDER for width/height is used to skip an overlapping window's borders
 * UNDERMOUSE for left/top to Open window with left/top as MOUSE coords.
 */
#define WLO_Border      0x10000
#define WLO_Percent     0x20000
#define WLO_UnderMouse  0x40000

/*
 * wl_flags
 *
 * Don't check for window collisions -- used to reopen already opened and
 *  -repositioned- windows.
 *
 * Backstore saves the position of the window off -- will reset next window
 *  Open to Open to the same place.  Requires that passed WindowLocation
 *  structure stay around in the wlObject that is passed to the window INIT
 *  method.
 * Tile[Horiz|Vert] -- better name -- Shingle? Layer?
 * NoAuto -- DON'T do any auto-placement.
 */
#define WLO_Backstore   0x1
#define WLO_TileHoriz   0x2
#define WLO_TileVert    0x4
#define WLO_NoAuto      0x8

/*
 * Internal flags.
 */
#define WLO_ReTile     0x80000000
#define WLO_ResetVert   0x40000000
#define WLO_ResetHoriz  0x20000000

enum {WLO_Location = TAG_USER + 1};


#define METH_WINDOW_CLOSE      METH_REMOVE
#define METH_WINDOW_REFRESH    "Method window refresh"
#define METH_WINDOW_PRETITLE   "Prepend this string to window title"
#define METH_WINDOW_MOVE       "Move Window to position"
#define METH_WINDOW_UPDATE     "Update Window default location"
#define METH_GADGET_SELECT     "Method gadget select"

extern ARGUMENT_TAG REF_WinOpenMethod[];

void *WinOpenMethod(METHOD_ARGS, OBJECT parent,
                                 char *name,
                                 OBJECT out_object,
                                 char *out_method,
                                 struct TagItem *tags,
                                 OBJECT wlObject);
void WinCloseMethod(METHOD_ARGS);
void WinDestroyMethod(METHOD_ARGS);


/*
 * ==========================================================================
 * =                                                                        =
 * =           Class definition for GADTOOL gadget objects.                 =
 * =                                                                        =
 * ==========================================================================
 */

#ifndef GADGT_CLASS
#define GADGT_CLASS    "Gadget GadTool Class\0"
#endif

#define ATTR_GADGET   "gadget base offset\0"

struct GadgetObject {
   struct Gadget *go_gadget;
};

extern ARGUMENT_TAG REF_GadgTOpenMethod[], REF_GadgTChangeMethod[];

void *GadgTOpenMethod(METHOD_ARGS, OBJECT window,
                                   char *name,
                                   OBJECT out_object,
                                   char *out_method,
                                   struct NewGadget *ng,
                                   long gadType,
                                   struct TagItem *tags);


#define METH_GADGET_CHANGE "Method Change gadtool attrs"
void GadgTChangeMethod(METHOD_ARGS, struct TagItem *tags);

/*
 * ==========================================================================
 * =                                                                        =
 * =           Class definition for ASL objects.                            =
 * =                                                                        =
 * ==========================================================================
 */

#ifndef ASL_CLASS
#define ASL_CLASS    "ASL Requester Class"
#endif

#define ATTR_ASLREQUEST   "ASL Request ptr"

struct AslRequest {
   union {
      void  *uar_Requester;
      struct FileRequester *uar_FileRequester;
      struct FontRequester *uar_FontRequester;
   }       ar_union;
#define ar_Requester ar_union.uar_Requester
#define ar_FileRequester ar_union.uar_FileRequester
#define ar_FontRequester ar_union.uar_FontRequester
   USHORT  ar_OpenFlag;
   OBJECT  ar_ParentWindow;
   OBJECT  ar_LocalWindow;
   ULONG   ar_gadType;

   /*
    * for resource tracking.
    */
   char *ar_FontName;
   char *ar_File;
   char *ar_Dir;
   char *ar_OKText;
   char *ar_CancelText;
};

#define ASL_FLAG_BEGUN  1
#define ASL_FLAG_REMOVE 2

#define METH_ASL_LAUNCH "Method Launch asl requester"
#define METH_ASL_BEGIN  "Method Open Requester"
#define METH_ASL_DONE   "Method Requester Closed"

BOOL InitGUISystem(void);

#endif
