#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"

// Macros locales
static const int XDC_IS_ORDINAL = 0;
static const int XDC_IS_NAME    = 1;
#define XDC_C_FACTOR 17/10

// Types locaux
typedef union 
{
	UWORD	wOrd;
	char	szName[80];
} OrdinalOrName;

typedef struct
{
	DWORD dwDataSize;
	DWORD dwHeaderSize;
	DWORD dwDataVersion;
    UWORD wMemoryFlags;
    UWORD wLanguageId;
    DWORD dwVersion;  
	DWORD dwCharacteristics; 
	LPCTSTR lpType;
	LPCTSTR lpName;
	UINT  uResTypeTag;
	OrdinalOrName ResType;
	UINT  uResNameTag;
	OrdinalOrName ResName;
	void	*Data;
}  ResEntry;

#define XDC_MAXGADSTR   64
#define XDC_MAXWINSTR   128

// Globales (ce module est un peu sac à globales, pour arriver à partager le Wait() avec les autres fenêtres tout en
// conservant une compatibilité 100% API Windows)
static unsigned char *amsResBasePtr;        // Base des ressources
static unsigned long amsResSize;	        // Tailles des ressources
static int iDlgResult;                      // Valeur retournée par le dialogproc dans EndDialog(...)
static DLGPROC bDlgFunc;                    // DlgProc
static char cTitre[XDC_MAXWINSTR];          // Titre dialog
static Gadget *hGadgetList = NULL;
static char cGadStr[256][XDC_MAXGADSTR];
static unsigned char iLabel;

static HWND CreateWindow(ULONG x, ULONG y, ULONG largeur, ULONG hauteur, char *titre)
{
    Gadget *gad = CreateContext(&hGadgetList);

    strncpy(cTitre, titre, sizeof(cTitre) -1);

    HWND hDlg = OpenWindowTags(NULL,
                WA_Left,        x,
                WA_Top,         y,
                WA_Width,       largeur * XDC_C_FACTOR + hInst -> WBorLeft + hInst -> WBorRight,
                WA_Height,      hauteur * XDC_C_FACTOR + hInst -> WBorTop + hInst -> BarHeight + hInst -> WBorBottom,
                WA_Title,       cTitre,
                WA_Gadgets,     gad,
                WA_CustomScreen,(ULONG) hInst,
                WA_DepthGadget, TRUE,
                WA_DragBar,     TRUE,
                WA_Activate,    TRUE,
                WA_IDCMP,       IDCMP_VANILLAKEY | IDCMP_GADGETUP | IDCMP_GADGETDOWN | IDCMP_MOUSEMOVE);

     iLabel = 0;

     return hDlg;
}

static void AddGad(HWND hWnd, ULONG lType, ULONG lLeft, ULONG lTop, ULONG lWidth, ULONG lHeight, char *sGadgetText, UWORD wId, DWORD dwStyle)
{
    Gadget *hPrevGad = hWnd -> FirstGadget, *hGad;
    static NewGadget newGad;
    char *sText = &(cGadStr[iLabel][0]);

    // Si on a un label, le recopier dans une zone allouée pour le gadget
    strcpy(sText, sGadgetText);

    // Créer le newgadget
    newGad.ng_LeftEdge     = lLeft * XDC_C_FACTOR + hWnd -> BorderLeft;
    newGad.ng_TopEdge      = lTop  * XDC_C_FACTOR + hWnd -> BorderTop; //WScreen -> BarHeight;
    newGad.ng_Height       = (lType == TEXT_KIND) ? 16 : lHeight * XDC_C_FACTOR;
    newGad.ng_Width        = (lType == CHECKBOX_KIND) ? newGad.ng_Height : lWidth * XDC_C_FACTOR;
    newGad.ng_GadgetText   = sText;
    newGad.ng_UserData     = (APTR) lType;
    newGad.ng_TextAttr     = NULL;
    newGad.ng_GadgetID     = wId;
    newGad.ng_Flags        = (lType == CHECKBOX_KIND) ? PLACETEXT_RIGHT : PLACETEXT_IN;
    newGad.ng_VisualInfo   = hVi;

    // L'insérer en dernier dans la fenêtre
    while (hPrevGad -> NextGadget) hPrevGad = hPrevGad -> NextGadget;
    if (lType == SLIDER_KIND && (dwStyle & 1)) // Si on a un slider vertical
        hGad = CreateGadget(lType, hPrevGad, &newGad, PGA_FREEDOM, LORIENT_VERT, TAG_DONE);
    else
        hGad = CreateGadget(lType, hPrevGad, &newGad, TAG_DONE);

    if (hGad) iLabel++;
}

BOOL DLGInit(char *sResFileName)
{
	BPTR hFileLock = Lock(sResFileName, SHARED_LOCK);

	if (!hFileLock) return FALSE;

	FileInfoBlock sFib;
	BOOL bOk = FALSE;

	if (Examine(hFileLock,&sFib) && sFib.fib_DirEntryType < 0 && sFib.fib_Size > 0)
	{
		amsResSize = sFib.fib_Size;
		amsResBasePtr = (unsigned char *) AllocVec(amsResSize,MEMF_ANY|MEMF_PUBLIC);
		if (amsResBasePtr != NULL)
		{
			BPTR hFileHandle = Open(sResFileName,MODE_OLDFILE);

			if (hFileHandle)
			{
				if (Read(hFileHandle,amsResBasePtr, amsResSize) == amsResSize)
					bOk = TRUE;

				Close(hFileHandle);
			}
		}
	}
	UnLock(hFileLock);

	if (!bOk)
	{
		FreeVec(amsResBasePtr);
		amsResBasePtr = NULL;
		amsResSize = 0;
        return FALSE;
    }
    return TRUE;
}

void DLGClose(void)
{
    if (amsResBasePtr)
    {
        FreeVec(amsResBasePtr);
        amsResBasePtr = NULL;
    }
}

static UWORD IntelWord(UWORD *addr)
{
	unsigned char B1, B2;

	B1 = *((unsigned char *) addr);
	B2 = *(((unsigned char *) addr) + 1);
	return (UWORD) B1 | ((UWORD) B2 << 8);
}

static DWORD IntelLong(DWORD *addr)
{
	UWORD W1, W2;

	W1 = IntelWord((UWORD*) addr);
	W2 = IntelWord(((UWORD*) addr) + 1);
	return (ULONG) W1 | ((ULONG) W2 << 16);
}

// Lit un objet encodé sous la forme name ou ordinal
static int ReadNameOrOrdinal(unsigned char **pos, UWORD *wOrdinal, char *Name)
{
	unsigned char *carPtr;

	carPtr = *pos;

	if ((carPtr[0] == 0xFF) && (carPtr[1] == 0xFF))
	{
		// C'est un ordinal (UWORD suivant 0xFFFF)
		*wOrdinal = IntelWord((UWORD*)&carPtr[2]);
		*pos = *pos + 4;
		return XDC_IS_ORDINAL;
	}
	else
	{
		while(*Name++ = *carPtr) carPtr += 2;
		
		*pos = carPtr + 2;
		return XDC_IS_NAME;
	}
}

static unsigned char *ReadResEntry(unsigned char *pos, ResEntry *res)
{
	DWORD dwTaille;

	dwTaille = res -> dwDataSize = IntelLong(((DWORD*) pos)++ );
	res -> dwHeaderSize = IntelLong(((DWORD*) pos)++ );
	res -> uResTypeTag = ReadNameOrOrdinal(&pos, &(res -> ResType.wOrd), res -> ResType.szName);
	res -> uResNameTag = ReadNameOrOrdinal(&pos, &(res -> ResName.wOrd), res -> ResName.szName);

	if (res -> uResTypeTag == 0)
		res -> lpType = MAKEINTRESOURCE(res -> ResType.wOrd);
	else
		res -> lpType = (LPCTSTR)res -> ResType.szName;

	if (res -> uResNameTag == 0)
		res -> lpName = MAKEINTRESOURCE(res -> ResName.wOrd);
	else
		res -> lpName  = (LPCTSTR)res -> ResName.szName;

	res -> dwDataVersion     = IntelLong(((DWORD*) pos)++);
	res -> wMemoryFlags      = IntelWord(((UWORD*) pos)++);
	res -> wLanguageId       = IntelWord(((UWORD*) pos)++);
	res -> dwVersion         = IntelLong(((DWORD*) pos)++);
	res -> dwCharacteristics = IntelLong(((DWORD*) pos)++);
	res -> Data = pos;

	// Skip DataSize multiple de 4
	if ((dwTaille & 0x3) != 0) dwTaille = (dwTaille & 0xFFFFFFFC) + 4;
	return pos + dwTaille;
}

// Compare deux LPCTSTR
static int CheckLPCT(LPCTSTR lp1, LPCTSTR lp2)
{
	// On ne peut comparer que des types compatibles
	if ((((long)lp1 & 0xFFFF0000) == 0) && (((long)lp2 & 0xFFFF0000) == 0))
	{
		// Ordinal
		if ((long)lp1 == (long)lp2) return -1;
		return 0;
	}

	if ((((long)lp1 & 0xFFFF0000) != 0) && (((long)lp2 & 0xFFFF0000) != 0))
	{
		if (strcmp((char*)lp1, (char*)lp2) == 0) return -1;
		return 0;
	}

	return 0;
}

// Récupère une WSTRING dans la ressource et en fait une string non unicode
static unsigned char *myGetString(unsigned char *ucChar, char *szString)
{
	while(*szString++ = *ucChar ) ucChar += 2;

	ucChar += 2;

	return ucChar;
}

// Appelé en boucle pour chaque item de la structure de la dialog pour ajouter
// l'item à la fenêtre
static unsigned char *myLoadDialogItem(HWND hWnd, unsigned char *ucData)
{
	DWORD	dwHelpID;
	DWORD	dwStyle;
	DWORD	dwExtendedStyle; 
	UWORD	 wID;
	short	x, y, cx, cy; 
	UWORD	 wExtraBytes;
	UWORD	 wTagNom, wTagClasse;
	OrdinalOrName leNom;
	OrdinalOrName laClasse;

	// DialogItem est alignée sur un DWORD
	if ((long)ucData & 3)
		ucData = (unsigned char*) (((long)ucData & 0xFFFFFFFC) + 4);

	// Lecture des champs
	dwHelpID		= IntelLong(((DWORD*) ucData)++);
	dwExtendedStyle = IntelLong(((DWORD*) ucData)++);
	dwStyle			= IntelLong(((DWORD*) ucData)++);
	x				= IntelWord(((UWORD*)  ucData)++);
	y				= IntelWord(((UWORD*)  ucData)++);
	cx				= IntelWord(((UWORD*)  ucData)++);
	cy				= IntelWord(((UWORD*)  ucData)++);
	wID 	        = IntelWord(((UWORD*)  ucData)++);
    ucData+=2;

	wTagClasse = ReadNameOrOrdinal(&ucData, &(laClasse.wOrd), laClasse.szName );
	wTagNom = ReadNameOrOrdinal(&ucData, &(leNom.wOrd), leNom.szName );
	wExtraBytes = IntelWord(((UWORD*)ucData)++);

	ULONG aType = (ULONG) ~0;
    switch(laClasse.wOrd)
	{
		case 0x0080:
            switch(dwStyle & 0xF)
            {
                case BS_RADIOBUTTON:
                case BS_AUTORADIOBUTTON:
                case BS_CHECKBOX:
                case BS_AUTOCHECKBOX:
                     aType = CHECKBOX_KIND;  break;
                case BS_GROUPBOX:
                     aType = TEXT_KIND;      break;
                default:
                     aType = BUTTON_KIND;    break;
            }
            break;
		case 0x0081: aType = STRING_KIND;   break;
		case 0x0082: aType = TEXT_KIND;     break;
		case 0x0083: aType = LISTVIEW_KIND; break;
		case 0x0084: aType = SLIDER_KIND;   break;
		case 0x0085: aType = CYCLE_KIND;    break;
	}
    if (aType != ~0)
        AddGad(hWnd, aType, x, y, cx, cy, leNom.szName, wID, dwStyle);

	return ucData + wExtraBytes;
}

// Charge le dialogbox à partir du pointeur sur les données de la dialog dans les ressources
// (qui a été renseigné par myFindRessource())
static void myLoadDialog(unsigned char *ucData, DLGPROC bFunc, LPARAM lParam)
{
	DWORD	dwStyle;
	DWORD	dwExtendedStyle; 
	UWORD	wNbItem;
	short	x, y, cx, cy; 
	BOOL	bExtended;
	char	szTitle[128], szFont[80];
	UWORD	wTagMenu, wTagClasse;
	OrdinalOrName leMenu;
	OrdinalOrName laClasse;

	// Lire la signature
    bExtended = (IntelWord(((UWORD*)  ucData) + 1) == 0xFFFF);

	if (bExtended)
	{
		ucData += 8;
		dwExtendedStyle = IntelLong(((DWORD*) ucData)++);
		dwStyle			= IntelLong(((DWORD*) ucData)++);
	}
	else
	{
		dwStyle			= IntelLong(((DWORD*) ucData)++);
		dwExtendedStyle = IntelLong(((DWORD*) ucData)++);
	}

	wNbItem			= IntelWord(((UWORD*)  ucData)++);
	x				= IntelWord(((UWORD*)  ucData)++);
	y				= IntelWord(((UWORD*)  ucData)++);
	cx				= IntelWord(((UWORD*)  ucData)++);
	cy				= IntelWord(((UWORD*)  ucData)++);

	// Le menu & la Classe
	if ((wTagMenu = IntelWord(((UWORD*)ucData)++)) != 0x0000)	 // Il y a un menu
	{
		if (wTagMenu == 0xFFFF) leMenu.wOrd = IntelWord(((UWORD*)ucData)++);
		else ucData = myGetString(ucData, leMenu.szName);
	}

	if ((wTagClasse = IntelWord(((UWORD*)ucData)++)) != 0x0000)	 // Il y a une classe
	{
		if (wTagClasse == 0xFFFF) leMenu.wOrd = IntelWord(((UWORD*)ucData)++);
		else ucData = myGetString(ucData, laClasse.szName);
	}

	// Le nom
	ucData = myGetString(ucData, szTitle);

	if ((dwStyle & DS_SETFONT) == DS_SETFONT)
	{
		ucData += 6;
		ucData = myGetString(ucData, szFont);
	}

	vTrace(GetCatalogStr(hCat, MSG_0614, "DialogBox '%s' @(%d,%d), taille (%d,%d), %d contrôles"),szTitle, x, y,cx,cy, wNbItem);

    // Créer la fenêtre
    if (!(hWndDlg = CreateWindow(x, y, cx, cy, szTitle)))
    {
        vTrace(GetCatalogStr(hCat, MSG_0615, "*** E0077 : ouverture dialog [%s] (%d, %d, %d, %d)"), szTitle, x, y, cx, cy);
        return;
    }

	// Lecture des Items
	while(wNbItem--)
		ucData = myLoadDialogItem(hWndDlg, ucData);

    // Rafraîchir les gadgets
    RefreshGadgets(hWndDlg -> FirstGadget, hWndDlg, NULL);

    // Appel de la DlgProc pour INITDIALOG, en lui passant lParam (comme ça ça marche pour DlgBox() et DlgBoxParam())
    bDlgFunc = bFunc;
    bDlgFunc(hWndDlg, WM_INITDIALOG, 0, lParam);

    // Ajout du sigbit de la dialog dans le masque global
    lSigMask |= (1L << hWndDlg -> UserPort -> mp_SigBit);
}

void vProcessDlgMessage(void)
{
    if (!hWndDlg) return;

    IntuiMessage *hMsg;

 	// Traiter tous les messages dans la file de la fenêtre
    while (hWndDlg && (hMsg = GT_GetIMsg(hWndDlg -> UserPort)))
    {
        APTR iAddress   = hMsg -> IAddress;
        int  iClass      = hMsg -> Class,
             iCode       = hMsg -> Code,
             iGadId;

        GT_ReplyIMsg(hMsg);

        switch(iClass)
        {
            case IDCMP_GADGETUP:        // Click sur gadget dialog
                // Récupérer le pointeur sur le gadget
                iGadId = ((Gadget *) iAddress) -> GadgetID;

                // Appeller la DlgProc en lui passant le code et le lParam
                bDlgFunc(hWndDlg, WM_COMMAND, (iCode << 16) | iGadId, (LPARAM) iAddress);
                break;

            case IDCMP_VANILLAKEY:
                switch(iCode)
                {
                    case 27:        // Si Eskette, fin Dlg
                        EndDialog(hWndDlg, -1);
                        break;

                    default :
                        vTrace(GetCatalogStr(hCat, MSG_0616, "*** E0101 : code touche '%c' (%d) ignoré"), iCode, iCode);
                        break;
                }
                break;

            case IDCMP_MOUSEMOVE:
                bDlgFunc(hWndDlg, WM_HSCROLL, iCode, ((Gadget *) iAddress) -> GadgetID);
                break;

            default :
                vTrace(GetCatalogStr(hCat, MSG_0617, "*** E0102 : IntuiMessage classe %d code %d ignoré"), iClass, iCode);
                break;
        }
    }
}

// Trouve une ressource dans le fichier de ressource en fonction de son nom et de son type
static BOOL myFindResource(LPCTSTR lpTemplate, LPCTSTR lpType, ResEntry *res)
{
	unsigned char *ucBasePtr, *ucFin;
	
	ucBasePtr = amsResBasePtr;
	ucFin = ucBasePtr + amsResSize;

	while(ucBasePtr < ucFin)
	{
		ucBasePtr = ReadResEntry(ucBasePtr, res);

		// Est-ce le bon type de ressource et la bonne ressource
		if (CheckLPCT(lpType, res -> lpType) &&
				CheckLPCT(lpTemplate, res -> lpName))
					return TRUE;
    }

	return FALSE;
}

// Stubz des fonctions Windows pour les Dialog Boxes
int DialogBox(HINSTANCE hInst, LPCTSTR sRes, HWND hWnd, DLGPROC bFunc)
{
    if (hWndDlg)
    {
        vTrace(GetCatalogStr(hCat, MSG_0618, "*** E0078 : dialogue déjà ouvert"));
        return -1;
    }

	ResEntry res;
    vTrace(GetCatalogStr(hCat, MSG_0619, "Chargement dialog %d"), sRes);
	if (myFindResource(sRes , (LPCTSTR) RT_DIALOG, &res))
		myLoadDialog((unsigned char *) res.Data, bFunc, NULL); // Pas de lParam
    else
    {
        vTrace(GetCatalogStr(hCat, MSG_0620, "*** E0079 : dialog absent des ressources"));
        iDlgResult = -1;
    }

	return iDlgResult;
}

int DialogBoxParam(HINSTANCE hInst, LPCTSTR sRes, HWND hWnd, DLGPROC bFunc, LPARAM lParam)
{
    if (hWndDlg)
    {
        vTrace(GetCatalogStr(hCat, MSG_0621, "*** E0080 : dialogue déjà ouvert"));
        return -1;
    }

	ResEntry res;
    vTrace(GetCatalogStr(hCat, MSG_0622, "Chargement dialog %d (param. %ld)"), sRes, lParam);
	if (myFindResource(sRes , (LPCTSTR) RT_DIALOG, &res))
		myLoadDialog((unsigned char *) res.Data, bFunc, lParam);
    else
    {
        vTrace(GetCatalogStr(hCat, MSG_0623, "*** E0081 : dialog absent des ressources"));
        iDlgResult = -1;
    }

	return iDlgResult;
}

BOOL EndDialog(HWND hWnd, int nResult)
{
    // Si la dialog n'est pas ouverte, ne rien faire
    if (!hWnd) return FALSE;

    vTrace(GetCatalogStr(hCat, MSG_0624, "Fin dialogue %s, code %d"), hWnd -> Title, nResult);

    Forbid();
        ModifyIDCMP(hWndDlg, 0L);
        lSigMask &= ~(1L << hWndDlg -> UserPort -> mp_SigBit);  // Enlever le sigbit du mask du Wait()
//        Gadget *hGads = hWnd -> FirstGadget;                    // Récupérer un pointeur sur la gadlist de la dialog
        hWnd -> FirstGadget = NULL;                             // Débrancher la gadlist de la dialog
        CloseWindow(hWndDlg);                                   // Fermer la fenêtre
        FreeGadgets(hGadgetList);                                     // Libérer les gadgets
    Permit();

    hWndDlg = NULL;

    iDlgResult = nResult;

    return TRUE;
}

int SendDlgItemMessage(HWND hWnd, int iGad, int iMsg, WPARAM wParam, LPARAM lParam)
{
    ULONG lTag = 0;
    char *hStr;

    if (!hWnd)
    {
        vTrace(GetCatalogStr(hCat, MSG_0625, "*** E0103 : hWnd nul"));
        return FALSE;
    }

    Gadget *hGadget = hWnd -> FirstGadget;

    while (hGadget && hGadget -> GadgetID != iGad) hGadget = hGadget -> NextGadget;

    if (!hGadget)
    {
        vTrace(GetCatalogStr(hCat, MSG_0626, "*** E0104 : gadget %d fenêtre %s non trouvé"), iGad, hWnd -> Title);
        return FALSE;
    }
 
    switch(iMsg)
    {
        case WM_SETTEXT:
            switch((int) (hGadget -> UserData))
            {
                case TEXT_KIND:
                    GT_SetGadgetAttrs(hGadget, hWnd, NULL, GTTX_Text, (ULONG) lParam, GTTX_CopyText, TRUE, TAG_DONE);
                    break;
                default :
                    GT_SetGadgetAttrs(hGadget, hWnd, NULL, GTST_String, (ULONG) lParam, TAG_DONE);
                    break;
            }
            break;

        case WM_GETTEXT:
            switch((int) (hGadget -> UserData))
            {
                case TEXT_KIND:
                    GT_GetGadgetAttrs(hGadget, hWnd, NULL, GTTX_Text, (ULONG) &hStr, TAG_DONE);
                    break;
                default :
                    GT_GetGadgetAttrs(hGadget, hWnd, NULL, GTST_String, (ULONG) &hStr, TAG_DONE);
                    break;
            }
            strncpy((char *) lParam, hStr, wParam);
            break;

        case BM_SETCHECK:
            GT_SetGadgetAttrs(hGadget, hWnd, NULL, GTCB_Checked, (ULONG) wParam, TAG_DONE);
            break;

        case BM_GETCHECK:
            GT_GetGadgetAttrs(hGadget, hWnd, NULL, GTCB_Checked, (ULONG) &lTag, TAG_DONE);
            break;

        case GA_Disabled:
            GT_SetGadgetAttrs(hGadget, hWnd, NULL, GA_Disabled, (ULONG) wParam, TAG_DONE);
            break;

        default:
            vTrace(GetCatalogStr(hCat, MSG_0627, "*** E0105 : classe de message %d non implémentée"), iMsg);
            break;
    }

    return lTag;
}

int GetDlgItem(HWND hWnd, int iGad)
{
    return iGad;
}

int GetDlgCtrlID(int iGad)
{
    return iGad;
}

void SetScrollInfo(int iGad, int iDummy, SCROLLINFO *hSi, BOOL bDummy)
{
    if (!hWndDlg)
    {
        vTrace(GetCatalogStr(hCat, MSG_0628, "*** E0106 : hWnd nul"));
        return;
    }

    Gadget *hGadget = hWndDlg -> FirstGadget;

    while (hGadget
        && !(hGadget -> GadgetType != 259                         // ????? Apparemment les sliders créent 2 gadgets dont 100%de type 259 qui n'est pas le bon !
          && hGadget -> GadgetID == iGad
            )
          )
        hGadget = hGadget -> NextGadget;

    if (!hGadget)
    {
        vTrace(GetCatalogStr(hCat, MSG_0629, "*** E0107 : Gadget %d fenêtre %s non trouvé"), iGad, hWndDlg -> Title);
        return;
    }

    if ((hSi -> fMask) & SIF_RANGE)
    {
        GT_SetGadgetAttrs(hGadget, hWndDlg, NULL, GTSL_Min, (ULONG) (hSi -> nMin), TAG_DONE);
        GT_SetGadgetAttrs(hGadget, hWndDlg, NULL, GTSL_Max, (ULONG) (hSi -> nMax), TAG_DONE);
    }

    if ((hSi -> fMask) & SIF_POS)
    {
        GT_SetGadgetAttrs(hGadget, hWndDlg, NULL, GTSL_Level, (ULONG) (hSi -> nPos), TAG_DONE);
    }
}

BOOL GetScrollInfo(int iGad, int iDummy, SCROLLINFO *hSi, BOOL bDummy)
{
    if (!hWndDlg)
    {
        vTrace(GetCatalogStr(hCat, MSG_0630, "*** E0108 : hWnd nul"));
        return FALSE;
    }

    Gadget *hGadget = hWndDlg -> FirstGadget;

    while (hGadget
        && !(hGadget -> GadgetType != 259                         // ????? Apparemment les sliders créent 2 gadgets dont 100%de type 259 qui n'est pas le bon !
          && hGadget -> GadgetID == iGad
            )
          )
        hGadget = hGadget -> NextGadget;

    if (!hGadget)
    {
        vTrace(GetCatalogStr(hCat, MSG_0631, "*** E0109 : Gadget %d fenêtre %s non trouvé"), iGad, hWndDlg -> Title);
        return FALSE;
    }

    if ((hSi -> fMask) & SIF_RANGE)
    {
        GT_GetGadgetAttrs(hGadget, hWndDlg, NULL, GTSL_Min, (ULONG) &(hSi -> nMin), TAG_DONE);
        GT_GetGadgetAttrs(hGadget, hWndDlg, NULL, GTSL_Max, (ULONG) &(hSi -> nMax), TAG_DONE);
    }

    if ((hSi -> fMask) & SIF_POS)
    {
        GT_GetGadgetAttrs(hGadget, hWndDlg, NULL, GTSL_Level, (ULONG) &(hSi -> nPos), TAG_DONE);
    }
    return TRUE;
}

