#define STRICT

// Includes standard Windows
#include <windows.h>
#include <windowsx.h>
#include <time.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <stdio.h>

// Includes D3D
#define  D3D_OVERLOADS
#include <ddraw.h>
#include <d3d.h>
#include <d3dx.h>

// Includes utilitaires D3D
#include "d3dmath.h"
#include "d3dutil.h"
#include "D3DEnum.h"

// Ids Resources
#include "resource.h"

// Constantes
#include "const.h"

// Types
#include "types.h"

// Variables globales projet
#include "vars.h"

// Prototypes fonctions autres modules
#include "proto.h"

// Macros
#include "macros.h"

// Spécifiques module
#include "libraries/gadtools.h"
#include "menusample.h"

#ifdef __PPC__
#include <powerpc/powerpc.h>
#include <clib/powerpc_protos.h>
#endif

#ifdef __PPC__
char sVersion[] = "$VER: sKulpt W3D alpha 7 24-Aug-2000 (W3D/PPC) - stephane.guillard@steria.fr";
#else
char sVersion[] = "$VER: sKulpt W3D alpha 7 24-Aug-2000 (W3D/060) - stephane.guillard@steria.fr";
#endif

NewWindow NWS2D =
{
	1, 1,
	30, 30,
	0, 1,
	IDCMP_NEWSIZE,  // Seul le newsize est activé à la création, mais ensuite l'IDCMP est modifié pour prise en compte de tous les autres messages
    WFLG_DEPTHGADGET | WFLG_SIZEBBOTTOM | WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_SIMPLE_REFRESH,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	20, 20,
	~0, ~0,
	CUSTOMSCREEN
};

NewWindow NWS3D =
{
	1, 1,
	30, 30,
	0, 1,
	IDCMP_VANILLAKEY | IDCMP_NEWSIZE | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK,
    WFLG_DEPTHGADGET | WFLG_SIZEBBOTTOM | WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_SIMPLE_REFRESH,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	20, 20,
	~0, ~0,
	CUSTOMSCREEN
};

NewWindow NWSMenu =
{
	1, 1,
	100, 20,
	0, 1,
	IDCMP_VANILLAKEY | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK,
	WFLG_ACTIVATE | WFLG_DEPTHGADGET | WFLG_SIZEBBOTTOM | WFLG_DRAGBAR | WFLG_SIZEGADGET | WFLG_CLOSEGADGET | WFLG_SIMPLE_REFRESH,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	20, 20,
	~0, ~0,
	CUSTOMSCREEN
};

struct Menu *hMenu = NULL;

void vWarpInfo(void)
{
	ULONG lRes;
    char cBuf[255];

	W3D_Driver **hDriver = W3D_GetDrivers();

	while (*hDriver)
    {
		sprintf(cBuf, "Driver [%s] : fmt 0x%lX ", hDriver[0] -> name, hDriver[0] -> formats);

		if (hDriver[0] -> swdriver) sprintf(cBuf + strlen(cBuf), "(HEL) ");
		else                        sprintf(cBuf + strlen(cBuf), "(HAL) ");

		sprintf(cBuf + strlen(cBuf), "- primitives : ");
		lRes = W3D_QueryDriver(hDriver[0], W3D_Q_DRAW_POINT, W3D_FMT_R5G5B5);
		if (lRes != W3D_NOT_SUPPORTED) sprintf(cBuf + strlen(cBuf), "point ");

		lRes = W3D_QueryDriver(hDriver[0], W3D_Q_DRAW_LINE, W3D_FMT_R5G5B5);
		if (lRes != W3D_NOT_SUPPORTED) sprintf(cBuf + strlen(cBuf), "line ");

		lRes = W3D_QueryDriver(hDriver[0], W3D_Q_DRAW_TRIANGLE, W3D_FMT_R5G5B5);
		if (lRes != W3D_NOT_SUPPORTED) sprintf(cBuf + strlen(cBuf), "triangle ");

		sprintf(cBuf + strlen(cBuf), "- filtres : ");
		lRes = W3D_QueryDriver(hDriver[0], W3D_Q_BILINEARFILTER, W3D_FMT_R5G5B5);
		if (lRes != W3D_NOT_SUPPORTED) sprintf(cBuf + strlen(cBuf), "bilinear ");

		lRes = W3D_QueryDriver(hDriver[0], W3D_Q_MMFILTER, W3D_FMT_R5G5B5);
		if (lRes != W3D_NOT_SUPPORTED) sprintf(cBuf + strlen(cBuf), "mipmap");

        vTrace(cBuf);
		hDriver++;
	}
}

inline int iDispatchIntuiMessage(HWND wGotMsg, IntuiMessage *iMsg)
{
    APTR iAddress   = iMsg -> IAddress;
    register int
        iClass      = iMsg -> Class,
        iCode       = iMsg -> Code;
    register WORD
        wQualifier  = iMsg -> Qualifier,
        wMouseX     = iMsg -> MouseX,
        wMouseY     = iMsg -> MouseY;

	ReplyMsg((struct Message *) iMsg);

    switch(iClass)
    {
        case IDCMP_VANILLAKEY :
			PostMessage(wGotMsg, WM_CHAR, iCode, 0);
            break;

        case IDCMP_NEWSIZE :
            PostMessage(wGotMsg, WM_SIZE, 0, (ULONG) wGotMsg -> Width | ((ULONG) wGotMsg -> Height) << 16);
            break;

        case IDCMP_MOUSEMOVE:
            if (!PeekSignal(l2DWinSigMask))
                PostMessage(wGotMsg, WM_MOUSEMOVE, wQualifier, (ULONG) wMouseX | ((ULONG) wMouseY) << 16);
            break;

        case IDCMP_MENUPICK :
            if (iCode != MENUNULL)
                PostMessage(wGotMsg, WM_COMMAND, (WPARAM) GTMENUITEM_USERDATA(ItemAddress(hMenu, iCode)), (LPARAM) 0);
            break;

        case IDCMP_REFRESHWINDOW :
            BeginRefresh(wGotMsg);
			PostMessage(wGotMsg, WM_PAINT, 0, 0);
            EndRefresh(wGotMsg, TRUE);
            break;

        case IDCMP_CLOSEWINDOW :
            PostMessage(wGotMsg, WM_CLOSE, 0, 0);
            break;

        case IDCMP_MOUSEBUTTONS:
            switch(iCode)
            {
                case SELECTDOWN:
                    PostMessage(wGotMsg, WM_LBUTTONDOWN, wQualifier, (ULONG) wMouseX | ((ULONG) wMouseY) << 16);
                    break;

                case SELECTUP:
                    PostMessage(wGotMsg, WM_LBUTTONUP, wQualifier, (ULONG) wMouseX | ((ULONG) wMouseY) << 16);
                    break;
            }
            break;

        default :
            vTrace("*** E0034 : Message Class %08lX Code %04X Qualif %04X reçu et non traité pour fenêtre %s", iClass, iCode, wQualifier, wGotMsg -> Title);
            break;
    }
    return iClass;
}

#define mCleanExit(s, l)    \
{                           \
    vTrace(s);              \
    goto l;                 \
}

ULONG lFlags, lModeID, lError;

int main(int argc, char **argv)
{
    IntuiMessage *iMsg;
    int iClass;
    void *hVi = NULL;
    ULONG lSigMask, lSigTop, lSigFace, lSigRight, lSig3D, lSigMenu;
    W3D_Double dZdepth = 0.8;

    // Mémoriser notre pointeur de tâche
    hApp = FindTask(NULL);

    // Ouvrir les librairies non ouvertes par défaut par les stubs Storm
    GadToolsBase   = OpenLibrary((UBYTE *) "gadtools.library",  39L);
    UtilityBase    = OpenLibrary((UBYTE *) "utility.library",   39L);
    AslBase        = OpenLibrary((UBYTE *) "asl.library",       39L);
    AmigaGuideBase = OpenLibrary((UBYTE *) "amigaguide.library",39L);
    DataTypesBase  = OpenLibrary((UBYTE *) "datatypes.library", 39L);
    IconBase       = OpenLibrary((UBYTE *) "icon.library",      39L);
    CyberGfxBase   = OpenLibrary((UBYTE *) "cybergraphics.library", 0L);
    if (!(GadToolsBase && UtilityBase && AslBase && AmigaGuideBase && DataTypesBase && IconBase && CyberGfxBase))
        mCleanExit("*** E0035 : librairie manquante, utilisez SnoopDos pour trouver laquelle", _mce_CloseLibs);

#ifndef __PPC__
	Warp3DBase     = OpenLibrary((UBYTE *) "Warp3D.library",    3L);
	if (!Warp3DBase)
#else
	Warp3DPPCBase  = OpenLibrary((UBYTE *) "Warp3DPPC.library", 3L);
	if (!Warp3DPPCBase)
#endif
        mCleanExit("*** E0036 : librairie Warp3D v3 manquante", _mce_CloseLibs);

	// Check for availability of drivers
	lFlags = W3D_CheckDriver();
	if (lFlags & W3D_DRIVER_UNAVAILABLE)
        mCleanExit("*** E0037 : pas de driver Warp3D", _mce_CloseLibs);

	// Choisir un mode d'écran compatible Warp3D
	lModeID = W3D_RequestModeTags(
		W3D_SMR_TYPE,       W3D_DRIVER_3DHW,
		W3D_SMR_DESTFMT,    ~W3D_FMT_CLUT,
	    TAG_DONE);

	if (lModeID == INVALID_ID)
        mCleanExit("*** E0038 : pas de mode d'écran valide", _mce_CloseLibs);

	// Ouvrir l'écran selon mode demandé
	if (!(hInst = OpenScreenTags(NULL,
  	                       		 SA_DisplayID,          lModeID,
                                 SA_SharePens,          TRUE,
                                 SA_Title,              (ULONG) sVersion + 6,
                         		 SA_Draggable,          FALSE,
                         	     TAG_DONE)))
        mCleanExit("*** E0039 : ouverture écran", _mce_CloseLibs);

    NWS2D.Screen = NWS3D.Screen = NWSMenu.Screen = hInst;

    // Créer la structure de menus GadToolz
    hVi     = GetVisualInfo(hInst, TAG_DONE);                                     
    hMenu   = CreateMenus(mNMenu, GTMN_FrontPen, 0, TAG_DONE);
    LayoutMenus(hMenu, hVi, TAG_DONE);
	
	// Allouer les structures du filerequester
    if (!FSInit())
        mCleanExit("*** E0040 : allocation filerequester", _mce_CloseLibsAndScreenAndVI);

	// Allouer les structures du gestionnaire de dialogs
    if (!DLGInit("sampler.res"))
        mCleanExit("*** E0048 : initialisation ressources", _mce_CloseLibsAndScreenAndVIAndFS);

    // Préparer les gadgets
    if (!bPrepareGadgets())
        mCleanExit("*** E0049 : initialisation gadgets", _mce_CloseLibsAndScreenAndVIAndFSAndDlg);

	// Initialiser les tableaux d'objets 3D
	vDeleteObjects();

    // Se présenter...
    vLogo();

    // Créer la fenêtre de menus, y attacher le menustrip et définr son titre
    PostMessage(hWndMenu = OpenWindow(&NWSMenu), WM_CREATE, 0, 0); SetMenuStrip(hWndMenu, hMenu); SetWindowTitles(hWndMenu, sVersion + 6, (UBYTE *) -1);

    // Attacher la console de trace à la fenêtre de menus
    if (!InitConsole(hWndMenu))
        mCleanExit("*** E0047 : initialisation console", _mce_CloseLibsAndScreenAndVIAndFSAndDlgAndGads);

	// Créer les fenêtres 2D, leur envoyer un WM_CREATE, leur attacher la menustrip de la fenêtre menu, leur coller un titre
	PostMessage(hWndTop = OpenWindow(&NWS2D), WM_CREATE, 0, 0); LendMenus(hWndTop, hWndMenu); SetWindowTitles(hWndTop, "Vue de dessus", (UBYTE *) -1); SetDrMd(GetDC(hWndTop), JAM1);
	PostMessage(hWndFace = OpenWindow(&NWS2D), WM_CREATE, 0, 0); LendMenus(hWndFace, hWndMenu); SetWindowTitles(hWndFace, "Vue de face", (UBYTE *) -1); SetDrMd(GetDC(hWndFace), JAM1);
	PostMessage(hWndRight = OpenWindow(&NWS2D), WM_CREATE, 0, 0); LendMenus(hWndRight, hWndMenu); SetWindowTitles(hWndRight, "Vue de droite", (UBYTE *) -1); SetDrMd(GetDC(hWndRight), JAM1);

    // Créer la fenêtre 3D etc....
	PostMessage(hWndPersp = OpenWindow(&NWS3D), WM_CREATE, 0, 0); LendMenus(hWndPersp, hWndMenu); SetWindowTitles(hWndPersp, "3D incomplète dans cette version", (UBYTE *) -1);

    // Laisser Intuition flusher son pipe
    Delay(10);

    // Redimensionner les fenêtres (ce qui vide la trace...)
    vRemakeTriview(0L);

	// Forcer le rafraichissement complet de la fenêtre 3D
	vForce3DRefresh(XDC_MODE_COMPLET);

	// Mettre à jour les checkmarks des menus
	vUpdateMenu();

	// Créer le contexte W3D commun aux 3 fenêtres 2D (sans zbuf)
    hW3DContext = W3D_CreateContextTags(&lError,
		W3D_CC_MODEID,      lModeID,
		W3D_CC_BITMAP,      (ULONG) (hInst -> RastPort.BitMap),
		W3D_CC_YOFFSET,     0,
		W3D_CC_DRIVERTYPE,  W3D_DRIVER_BEST,
        W3D_CC_DOUBLEHEIGHT, FALSE,
		W3D_CC_FAST,        TRUE,
	    TAG_DONE);

	if (!hW3DContext || lError != W3D_SUCCESS)
    {
		switch(lError)
        {
		case W3D_ILLEGALINPUT:
			vTrace("*** E0041 : paramètres CreateContext()");
			break;
		case W3D_NOMEMORY:
			vTrace("*** E0042 : mémoire insuffisante");
			break;
		case W3D_NODRIVER:
			vTrace("*** E0043 : driver invalide");
			break;
		case W3D_UNSUPPORTEDFMT:
			vTrace("*** E0044 : bitmap incompatible Warp3D");
			break;
		case W3D_ILLEGALBITMAP:
			vTrace("*** E0045 : bitmap mal initialisé");
			break;
		default:
			vTrace("*** E0046 : erreur interne");
		}
		goto _mce_CloseLibsAndScreenAndVIAndWindows;
	}

	// Set dithering. This will look considerably better on 15 bit displays.
	W3D_SetState(hW3DContext, W3D_DITHERING, W3D_DISABLE);

    // Set Gouraud shading state
    W3D_SetState(hW3DContext, W3D_GOURAUD, W3D_DISABLE);

    // Activer le clipping
    W3D_SetState(hW3DContext, W3D_SCISSOR, W3D_ENABLE);

    // Désactiver le zbuffer
    W3D_SetState(hW3DContext, W3D_ZBUFFERUPDATE, W3D_ENABLE);
    W3D_SetState(hW3DContext, W3D_ZBUFFER, W3D_DISABLE);

	// Afficher les propriétés des drivers Warp installés
    vWarpInfo();

    // Préparer les matrices world / view / proj
    hrInitWorld(NULL);

    // Finaliser la liste des messages broadcastés pour les fenêtres 2D
    ModifyIDCMP(hWndTop, IDCMP_VANILLAKEY | IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK);
    ModifyIDCMP(hWndFace, IDCMP_VANILLAKEY | IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK);
    ModifyIDCMP(hWndRight, IDCMP_VANILLAKEY | IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_REFRESHWINDOW | IDCMP_MENUPICK);

	// Préparer les masques de signaux pour la boucle de messages
    lSigMenu = 1L << hWndMenu -> UserPort -> mp_SigBit;
	lSigTop = 1L << hWndTop -> UserPort -> mp_SigBit;
	lSigFace = 1L << hWndFace -> UserPort -> mp_SigBit;
	lSigRight = 1L << hWndRight -> UserPort -> mp_SigBit;
	lSig3D = 1L << hWndPersp -> UserPort -> mp_SigBit;
    l2DWinSigMask = lSigTop | lSigFace | lSigRight;

    // Boucle principale de traitement des messages Intuition
    do
	{
		// Attendre un message sur toutes les fenêtres
#ifdef __PPC__
        lSigMask = WaitPPC(lSigMenu | l2DWinSigMask | lSig3D);
#else
        lSigMask = Wait(lSigMenu | l2DWinSigMask | lSig3D);
#endif
        // Traiter tous les messages dans la file de la fenêtre Menus
        if (lSigMask & lSigMenu)
            while (iMsg = (struct IntuiMessage *) GetMsg(hWndMenu -> UserPort))
                iClass = iDispatchIntuiMessage(hWndMenu, iMsg);
      
		// Traiter tous les messages dans la file de la fenêtre Vue de dessus
  		if (lSigMask & lSigTop)
            while (iMsg = (struct IntuiMessage *) GetMsg(hWndTop -> UserPort))
                iClass = iDispatchIntuiMessage(hWndTop, iMsg);

		// Traiter tous les messages dans la file de la fenêtre Vue de face
		if (lSigMask & lSigFace)
            while (iMsg = (struct IntuiMessage *) GetMsg(hWndFace -> UserPort))
                iClass = iDispatchIntuiMessage(hWndFace, iMsg);

		// Traiter tous les messages dans la file de la fenêtre Vue de droite
		if (lSigMask & lSigRight)
            while (iMsg = (struct IntuiMessage *) GetMsg(hWndRight -> UserPort))
                iClass = iDispatchIntuiMessage(hWndRight, iMsg);

		// Traiter tous les messages dans la file de la fenêtre Vue 3D
		if (lSigMask & lSig3D)
            while (iMsg = (struct IntuiMessage *) GetMsg(hWndPersp -> UserPort))
                iClass = iDispatchIntuiMessage(hWndPersp, iMsg);
	}
    // Jusqu'à IDCMP_CLOSEWINDOW (qui ne peut venir que de la fenêtre Menus)
	while (iClass != IDCMP_CLOSEWINDOW);

	if (hW3DContext) W3D_DestroyContext(hW3DContext);

_mce_CloseLibsAndScreenAndVIAndWindows:
    // Libérer les entités allouées par les fenêtres en leur envoyant un WM_DESTROY
    if (hWndTop)    PostMessage(hWndTop,    WM_DESTROY, 0, 0);
    if (hWndFace)   PostMessage(hWndFace,   WM_DESTROY, 0, 0);
    if (hWndRight)  PostMessage(hWndRight,  WM_DESTROY, 0, 0);
    if (hWndPersp)  PostMessage(hWndPersp,  WM_DESTROY, 0, 0);
    if (hWndMenu)   PostMessage(hWndMenu,   WM_DESTROY, 0, 0);

    // Détacher la menustrip
    if (hWndTop)    LendMenus(hWndTop, NULL);
    if (hWndFace)   LendMenus(hWndFace, NULL);
    if (hWndRight)  LendMenus(hWndRight, NULL);
    if (hWndPersp)  LendMenus(hWndPersp, NULL);
    if (hWndMenu)   ClearMenuStrip(hWndMenu);

	// Refermer la console de trace
    if (hWndMenu)   CloseConsole();
	
    // Fermer les fenêtres
    if (hWndTop)    CloseWindowSafely(hWndTop);
    if (hWndFace)   CloseWindowSafely(hWndFace);
    if (hWndRight)  CloseWindowSafely(hWndRight);
    if (hWndPersp)  CloseWindowSafely(hWndPersp);
    if (hWndMenu)   CloseWindowSafely(hWndMenu);

_mce_CloseLibsAndScreenAndVIAndFSAndDlgAndGads:
    // Libérer les gadgets
    vEraseGadgets();

_mce_CloseLibsAndScreenAndVIAndFSAndDlg:
    // Libérer les structures File Requester et screenmoderequester et du gestionnaire de console
    DLGClose();
_mce_CloseLibsAndScreenAndVIAndFS:
    FSClose();

_mce_CloseLibsAndScreenAndVI:
    // Détruire le menustrip
    FreeMenus(hMenu);

    // Libérer le Visual Info Gadtoolz
    FreeVisualInfo(hVi);

    // Fermer l'écran s'il s'agit d'un écran custom
    if (lModeID != INVALID_ID)
        CloseScreen(hInst);

_mce_CloseLibs:
    // Refermer les librairies
    if (GadToolsBase)   CloseLibrary(GadToolsBase);
    if (UtilityBase)    CloseLibrary(UtilityBase);
    if (AslBase)        CloseLibrary(AslBase);
    if (AmigaGuideBase) CloseLibrary(AmigaGuideBase);
    if (DataTypesBase)  CloseLibrary(DataTypesBase);
    if (IconBase)       CloseLibrary(IconBase);
    if (CyberGfxBase)   CloseLibrary(CyberGfxBase);
#ifndef __PPC__
	if (Warp3DBase)     CloseLibrary(Warp3DBase);
#else
	if (Warp3DPPCBase)  CloseLibrary(Warp3DPPCBase);
#endif

_mce_End:
}

// Simulation PostMessage Windows : dispatcher le message sur la WindowProc en fonction de hWnd
int PostMessage(HWND hWnd, int iMsg, WPARAM wParam, LPARAM lParam)
{
	if (hWnd ==  hWndTop || hWnd == hWndFace || hWnd == hWndRight)
	{
    	lrPlanarWndProc(hWnd, iMsg, wParam, lParam);
        return 0;
    }

	if (hWnd ==  hWndPersp)
	{
    	lrPerspWndProc(hWnd, iMsg, wParam, lParam);
        return 0;
    }

	if (hWnd ==  hWndMenu)
		lrMenuWndProc(hWnd, iMsg, wParam, lParam);

	return 0;
}

void DestroyWindow(HWND hWnd)
{
    PostMessage(hWnd, WM_DESTROY, 0, 0);
}

// Gestion du clipping fenêtres
struct Region *ClipWindow(HWND hWnd, LONG lMinX, LONG lMinY, LONG lMaxX, LONG lMaxY)
{
    struct Region *hRNew;
    struct Rectangle rRect;

    rRect.MinX = lMinX;
    rRect.MinY = lMinY;
    rRect.MaxX = lMaxX;
    rRect.MaxY = lMaxY;

    hRNew = NewRegion();
    OrRectRegion(hRNew, &rRect);

    return InstallClipRegion(hWnd -> WLayer, hRNew);
}

void UnclipWindow(HWND hWnd)
{
    register struct Region *hROld;

    if (hROld = InstallClipRegion(hWnd -> WLayer, NULL))
        DisposeRegion(hROld);
}

struct RastPort *GetDC(HWND hWnd)
{
    return hWnd -> RPort;
}

BOOL ExtTextOut(HDC hdc,int X,int Y, int fuOptions, RECT *lprc, char *lpString, int cbCount, int *lpDx)
{
    Move(hdc, X, Y + 24);
    Text(hdc, lpString, cbCount);
    return TRUE;
}

BOOL PtInRect(RECT *rRect, POINT pPoint)
{
    if (pPoint.x > rRect -> right)  return FALSE;
    if (pPoint.x < rRect -> left)   return FALSE;
    if (pPoint.y > rRect -> bottom) return FALSE;
    if (pPoint.y < rRect -> top)    return FALSE;
    return TRUE;
}

// Récupérer le rectangle complet de la zone client de la fenêtre
void GetClientRect(HWND hWnd, RECT *rRect)
{
    rRect -> left   = hWnd -> BorderLeft;
    rRect -> right  = hWnd -> Width - hWnd -> BorderRight - 1;
    rRect -> top    = hWnd -> BorderTop;
    rRect -> bottom = hWnd -> Height - hWnd -> BorderBottom - 1;
}

// Cloner un rectangle (r1 <- r2)
void CopyRect(RECT *rR1, RECT *rR2)
{
    *rR1 = *rR2;
}

// Enfler un rectangle
void InflateRect(RECT *rRect, int iX, int iY)
{
    rRect -> left   -= iX;
    rRect -> right  += iX;
    rRect -> top    -= iY;
    rRect -> bottom += iY;
}

// Définir un rectangle (x / y / lagreur / hauteur)
void SetRect(RECT *rRect, int x, int y, int w, int h)
{
    rRect -> left   = x;
    rRect -> right  = x + w;
    rRect -> top    = y;
    rRect -> bottom = y + h;
}

BOOL bPrepareGadgets(void)
{
    if (!(gAddPoint.hIcon   = GetDiskObjectNew("gfx/BTN_ADD_POINT")))       return FALSE;
	if (!(gCenter.hIcon	    = GetDiskObjectNew("gfx/BTN_CENTER")))          return FALSE;
	if (!(gGoDown.hIcon	    = GetDiskObjectNew("gfx/BTN_GO_DOWN")))         return FALSE;
	if (!(gGoLeft.hIcon	    = GetDiskObjectNew("gfx/BTN_GO_LEFT")))         return FALSE;
	if (!(gGoUp.hIcon	    = GetDiskObjectNew("gfx/BTN_GO_UP")))           return FALSE;
	if (!(gGoRight.hIcon    = GetDiskObjectNew("gfx/BTN_GO_RIGHT")))        return FALSE;
	if (!(gGrab.hIcon	    = GetDiskObjectNew("gfx/BTN_GRABBER")))         return FALSE;
	if (!(gMakeTri.hIcon    = GetDiskObjectNew("gfx/BTN_MAKE_TRIANGLE")))   return FALSE;
	if (!(gReverse.hIcon    = GetDiskObjectNew("gfx/BTN_REVERSE")))         return FALSE;
	if (!(gRotAnti.hIcon    = GetDiskObjectNew("gfx/BTN_ROTATE_TRIGO")))    return FALSE;
	if (!(gRotClock.hIcon   = GetDiskObjectNew("gfx/BTN_ROTATE_CLOCK")))    return FALSE;
	if (!(gZoomIn.hIcon	    = GetDiskObjectNew("gfx/BTN_ZOOM_IN")))         return FALSE;
	if (!(gZoomOut.hIcon    = GetDiskObjectNew("gfx/BTN_ZOOM_OUT")))        return FALSE;

    return TRUE;
}

void vEraseGadgets(void)
{
    if (gAddPoint.hIcon)FreeDiskObject(gAddPoint.hIcon);
    if (gCenter.hIcon)  FreeDiskObject(gCenter.hIcon);
    if (gGoDown.hIcon)  FreeDiskObject(gGoDown.hIcon);
    if (gGoLeft.hIcon)  FreeDiskObject(gGoLeft.hIcon);
    if (gGoUp.hIcon)    FreeDiskObject(gGoUp.hIcon);
    if (gGoRight.hIcon) FreeDiskObject(gGoRight.hIcon);
    if (gGrab.hIcon)    FreeDiskObject(gGrab.hIcon);
    if (gMakeTri.hIcon) FreeDiskObject(gMakeTri.hIcon);
    if (gReverse.hIcon) FreeDiskObject(gReverse.hIcon);
    if (gRotAnti.hIcon) FreeDiskObject(gRotAnti.hIcon);
    if (gRotClock.hIcon)FreeDiskObject(gRotClock.hIcon);
    if (gZoomIn.hIcon)  FreeDiskObject(gZoomIn.hIcon);
    if (gZoomOut.hIcon) FreeDiskObject(gZoomOut.hIcon);
}

HGDIOBJ hAddImage(HWND hWnd, char *sName, int iX, int iY, int iWidth, int iHeight)
{
    HGDIOBJ hObject = NewDTObject(sName,
		DTA_SourceType,		DTST_FILE,
        GA_RelVerify,		TRUE,
  	    GA_Immediate,       TRUE,
        GA_Left,		    iX,
  	    GA_Top,			    iY,
        GA_Width,           iWidth,
        GA_Height,          iHeight,
        ICA_TARGET,		    ICTARGET_IDCMP,
		TAG_DONE);

	if (!hObject)
        return NULL;

    AddDTObject(hWnd, NULL, hObject, -1);
    return hObject;
}

void vMoveImage(HWND hWnd, HGDIOBJ hObject, int iX, int iY)
{
    RemoveDTObject(hWnd, hObject);
    SetDTAttrs(hObject, hWnd, NULL,
        GA_Left,		    iX,
  	    GA_Top,			    iY,
        TAG_DONE);
    AddDTObject(hWnd, NULL, hObject, -1);
}

void vRefreshImage(HWND hWnd, HGDIOBJ hObject)
{
    RefreshDTObjectA(hObject, hWnd, NULL, NULL);
}

void vRemoveImage(HWND hWnd, HGDIOBJ hObject)
{
    RemoveDTObject(hWnd, hObject);
	DisposeDTObject(hObject);
}

//###############################################################################
// Protos non mappés
BOOL CALLBACK bGlobLightDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

BOOL CALLBACK bSphereDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

BOOL CALLBACK bFaceDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

BOOL CALLBACK bExpandDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

BOOL CALLBACK bHelixDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

BOOL CALLBACK bHoleDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

BOOL CALLBACK bStringDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return TRUE;
}

void vAddTextOutline(void)
{
}

DWORD GetTickCount(void)
{
    return (DWORD) 0;
}

void ShowWindow(HWND hWnd, int iI)
{
}     

void PostQuitMessage(int iI)
{
}


