/*
** MUI Helper
** Copyright (C) 2000 Gurer Ozen <madcat@linuxfan.com>
**
** This code is free software; you can redistribute it and/or
** modify it under the terms of GNU General Public License.
*/

#include "compiler.h"

#include <sys/types.h>

#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/intuition.h>
#include <libraries/mui.h>
#include <proto/muimaster.h>
#include <clib/alib_protos.h>

#include <mui/textinput_mcc.h>

#ifndef MADCAT_MUI_H
#define MADCAT_MUI_H

#ifdef __GNUC__
#undef MUI_NewObject
/* #undef MUI_MakeObject */
#endif

#ifdef __MORPHOS__
#define DoMethod(MyObject, tags...) \
	({ULONG _tags[] = { tags }; DoMethodA((MyObject), (APTR)_tags);})
#define DoSuperMethod(MyClass, MyObject, tags...) \
	({ULONG _tags[] = { tags }; DoSuperMethodA((MyClass), (MyObject), (APTR)_tags);})
#define CoerceMethod(MyClass, MyObject, tags...) \
	({ULONG _tags[] = { tags }; CoerceMethodA((MyClass), (MyObject), (APTR)_tags);})
ULONG DoSuperNew(struct IClass *cl, Object *obj, ...);
#else
ULONG __stdargs DoSuperNew(struct IClass *cl, Object *obj, ULONG tag1, ...);
#endif

#define MAKE_ID(a,b,c,d) ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

#define MUIA_Dtpic_Name 0x80423d72

typedef struct {
	ULONG MethodID;
	LONG a1, a2, a3, a4, a5, a6, a7;
} *muimsg;

#define MARG1 (((muimsg)msg)->a1)
#define MARG2 (((muimsg)msg)->a2)
#define MARG3 (((muimsg)msg)->a3)
#define MARG4 (((muimsg)msg)->a4)
#define MARG5 (((muimsg)msg)->a5)
#define MARG6 (((muimsg)msg)->a6)
#define MARG7 (((muimsg)msg)->a7)


typedef struct
{
	const UBYTE *body;
	const ULONG *colors;
	long w, h, d, comp, mask;
} muidefpix;

Object *mui_pix(char *fname, muidefpix *dp, ULONG tag1, ...);


typedef struct
{
	char *supername;
	int datasize;
	APTR dispatcher;
	struct MUI_CustomClass **ptr;
} muiclass;

int mui_classes_setup(muiclass mcl[]);
void mui_classes_cleanup(muiclass mcl[]);


char *mui_sget(Object *sobj);
u_long mui_id(Object *app, u_char *pre);

Object *mui_button(const UBYTE *label);
Object *mui_tmenu(const UBYTE *msg);
Object *mui_menu(const UBYTE *msg);
Object *mui_toggle(const UBYTE *msg, Object **tog);


#ifdef __MORPHOS__
#define MUI_HOOK_DECL(x,y,z) struct EmulLibEntry x
#define MUI_HOOK(x,y,z) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(struct Hook *hook, y , z ); \
	struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A0, (void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(struct Hook *hook, y , z )
#define MUI_HOOK_STATIC(x,y,z) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(struct Hook *hook, y , z ); \
	static struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A0, (void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(struct Hook *hook, y , z )

#define MUI_DISPATCH_DECL(x) struct EmulLibEntry x
#define MUI_DISPATCH(x) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(struct IClass *cl, Object *obj, Msg msg); \
	struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A0, (void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(struct IClass *cl, Object *obj, Msg msg)
#define MUI_DISPATCH_STATIC(x) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(struct IClass *cl, Object *obj, Msg msg); \
	static struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A0, (void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(struct IClass *cl, Object *obj, Msg msg)

#define MUI_LIST_DISP_DECL(x,y) struct EmulLibEntry x
#define MUI_LIST_DISP(x,y) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(char **array, y ); \
	struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(char **array, y )
#define MUI_LIST_DISP_STATIC(x,y) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(char **array, y ); \
	static struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(char **array, y )

#define MUI_LIST_DISP2_DECL(x) struct EmulLibEntry x
#define MUI_LIST_DISP2(x) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(Object *obj, struct NList_DisplayMessage *msg); \
	struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(Object *obj, struct NList_DisplayMessage *msg)
#define MUI_LIST_DISP2_STATIC(x) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(Object *obj, struct NList_DisplayMessage *msg); \
	static struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(Object *obj, struct NList_DisplayMessage *msg)

#define MUI_LIST_CONS_DECL(x,y) struct EmulLibEntry x
#define MUI_LIST_CONS(x,y) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(APTR pool, y ); \
	struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(APTR pool, y )
#define MUI_LIST_CONS_STATIC(x,y) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(APTR pool, y ); \
	static struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(APTR pool, y )

#define MUI_LIST_DEST_DECL(x,y) struct EmulLibEntry x
#define MUI_LIST_DEST(x,y) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(APTR pool, y ); \
	struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(APTR pool, y )
#define MUI_LIST_DEST_STATIC(x,y) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2(APTR pool, y ); \
	static struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A2, (void *)REG_A1)); } \
	static ULONG x ## _gate2(APTR pool, y )

#define MUI_LIST_COMP_DECL(x,y,z) struct EmulLibEntry x
#define MUI_LIST_COMP(x,y,z) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2( y , z ); \
	struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A1, (void *)REG_A2)); } \
	static ULONG x ## _gate2( y , z )
#define MUI_LIST_COMP_STATIC(x,y,z) \
	static ULONG SAVEDS x ## _gate(void); \
	static ULONG x ## _gate2( y , z ); \
	static struct EmulLibEntry x = { \
	TRAP_LIB, 0, (void (*)(void)) x ## _gate }; \
	static ULONG SAVEDS x ## _gate(void) { \
	return ( x ## _gate2((void *)REG_A1, (void *)REG_A2)); } \
	static ULONG x ## _gate2( y , z )

#else
#define MUI_HOOK_DECL(x,y,z) ULONG SAVEDS ASM x (REG(a0,struct Hook *hook), REG(a2, y ), REG(a1, z ))
#define MUI_HOOK(x,y,z) ULONG SAVEDS ASM x (REG(a0,struct Hook *hook), REG(a2, y ), REG(a1, z ))
#define MUI_HOOK_STATIC(x,y,z) static ULONG SAVEDS ASM x (REG(a0,struct Hook *hook), REG(a2, y ), REG(a1, z ))

#define MUI_DISPATCH_DECL(x) ULONG SAVEDS ASM x (REG(a0,struct IClass *cl), REG(a2,Object *obj), REG(a1,Msg msg))
#define MUI_DISPATCH(x) ULONG SAVEDS ASM x (REG(a0,struct IClass *cl), REG(a2,Object *obj), REG(a1,Msg msg))

#define MUI_LIST_DISP_DECL(x,y) ULONG SAVEDS ASM x (REG(a2,char **array), REG(a1, y ))
#define MUI_LIST_DISP(x,y) ULONG SAVEDS ASM x (REG(a2,char **array), REG(a1, y ))
#define MUI_LIST_DISP_STATIC(x,y) static ULONG SAVEDS ASM x (REG(a2,char **array), REG(a1, y ))

#define MUI_LIST_DISP2_DECL(x) ULONG SAVEDS ASM x (REG(a2,Object *obj), REG(a1,struct NList_DisplayMessage *msg))
#define MUI_LIST_DISP2(x) ULONG SAVEDS ASM x (REG(a2,Object *obj), REG(a1,struct NList_DisplayMessage *msg))
#define MUI_LIST_DISP2_STATIC(x) static ULONG SAVEDS ASM x (REG(a2,Object *obj), REG(a1,struct NList_DisplayMessage *msg))

#define MUI_LIST_CONS_DECL(x,y) ULONG SAVEDS ASM x (REG(a2,APTR pool), REG(a1, y ))
#define MUI_LIST_CONS(x,y) ULONG SAVEDS ASM x (REG(a2,APTR pool), REG(a1, y ))
#define MUI_LIST_CONS_STATIC(x,y) static ULONG SAVEDS ASM x (REG(a2,APTR pool), REG(a1, y ))

#define MUI_LIST_DEST_DECL(x,y) ULONG SAVEDS ASM x (REG(a2,APTR pool), REG(a1, y ))
#define MUI_LIST_DEST(x,y) ULONG SAVEDS ASM x (REG(a2,APTR pool), REG(a1, y ))
#define MUI_LIST_DEST_STATIC(x,y) static ULONG SAVEDS ASM x (REG(a2,APTR pool), REG(a1, y ))

#define MUI_LIST_COMP_DECL(x,y,z) LONG SAVEDS ASM x (REG(a1, y ), REG(a2, z ))
#define MUI_LIST_COMP(x,y,z) LONG SAVEDS ASM x (REG(a1, y ), REG(a2, z ))
#define MUI_LIST_COMP_STATIC(x,y,z) static LONG SAVEDS ASM x (REG(a1, y ), REG(a2, z ))
#endif



#endif	/* MADCAT_MUI_H */
