#include <windows.h>
#include <commdlg.h>
#include <shellapi.h>
#include <toolhelp.h>
#include <windowsx.h>
#include <direct.h>
#include <memory.h>
#include "rc.h"

///////////////////// MISC DEFINES   /////////////////////////

#define WNDPROC_PARAMS              HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam
#define DLGPROC_PARAMS              HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam
#define MAX_FILE_SIZE               128
#define MAXICONS                    32
#define MINTIME                     20
#define MAXTIME                     20000
#define WNDMENUPOS                  2
#define MAXANIMATIONS               16
#define FRAME_X                     280
#define FRAME_Y                     320
#define ICON_DY                     GetSystemMetrics (SM_CXICON)
#define ICON_DX                     GetSystemMetrics (SM_CYICON)
#define PADDING                     5
#define ID_CLIENT                   802
#define ID_STATBAR                  803
#define ID_TIMER                    1     // second param of SetTimer()
                                          // and KillTimer()

/////////////////////// DATA STRUCTURES ///////////////////////////


/* There are 8 animations possible at one time.  So, we use an
   array of 8 ANIMSTRUCT structures.  Each MDI child window created
   has a corresponding number, which is its index into the array. */

typedef struct tagANIMSTRUCT
{
    HWND    hWnd;                    // mdi child window handle
    HWND    hWndTarget;              // target window handle. 
    HICON   hIcons[MAXICONS];        // handles to icons loaded into memory.
    HICON   hPrevIcon;               // actual application icon (before anim)
    short   sNumIcons;               // number of icons in array
    short   sIndex;                  // current icon displayed (index)
    short   sTimeInt;                // stored timer interval.
    short   sCountDn;                // countdown until icon change.
    char    szEXELink[MAX_FILE_SIZE]; // filename of linked executable.
    char    szFileName[MAX_FILE_SIZE];// file name of script (0 if Untitled).
    BOOL    bIsEXELoaded;            // if task is loaded, true.
    BOOL    bIsAnimating;            // if is actually doing the deed.
    BOOL    bAutoAnimate;            // automatically animate upon load.
}   ANIMSTRUCT, FAR * LPANIMSTRUCT;

/////////////////// WINDOW-SPECIFIC DATA MACROS ////////////////

// These are the offsets to the window extra bytes
#define WW_HWNDLIST                 0
#define WW_WINDOWNUM                2
#define WW_ISDIRTY                  4
#define WW_ENDOFWORDS               6

// Use these functions to set window words
#define SET_HWNDLIST(x,v)           SetWindowWord (x,WW_HWNDLIST,v)
#define SET_WINDOWNUM(x,v)          SetWindowWord (x,WW_WINDOWNUM,v)
#define SET_ISDIRTY(x,v)            SetWindowWord (x,WW_ISDIRTY,v)

#define SET_ISANIMATING(x,v)        _animStruct[x].bIsAnimating = (BOOL)(v)
#define SET_EXELOADED(x,v)          _animStruct[x].bIsEXELoaded = (BOOL)(v)
#define SET_AUTOANIMATE(x,v)        _animStruct[x].bAutoAnimate = (BOOL)(v)
#define SET_HWNDANIM(x,v)           _animStruct[x].hWnd = (HWND)(v)
#define SET_NUMICONS(x,v)           _animStruct[x].sNumIcons = (short)(v)
#define SET_INDEX(x,v)              _animStruct[x].sIndex = (short)(v)
#define SET_HPREVICON(x,v)          _animStruct[x].hPrevIcon = (HICON)(v)
#define SET_TIMEINT(x,v)            _animStruct[x].sTimeInt = (short)(v)
#define SET_COUNTDOWN(x,v)          _animStruct[x].sCountDn = (short)(v)
#define SET_HWNDTARGET(x,v)         _animStruct[x].hWndTarget = (HWND)(v)


// Use these functions to get window word data
#define HWNDLIST(x)                 (HWND)GetWindowWord (x,WW_HWNDLIST)
#define WINDOWNUM(x)                (short)GetWindowWord (x,WW_WINDOWNUM)
#define ISDIRTY(x)                  (BOOL)GetWindowWord (x,WW_ISDIRTY)

#define HWNDANIM(x)                 (HWND)_animStruct[x].hWnd
#define ISANIMATING(x)              (BOOL)_animStruct[x].bIsAnimating
#define AUTOANIMATE(x)              (BOOL)_animStruct[x].bAutoAnimate
#define EXELOADED(x)                (BOOL)_animStruct[x].bIsEXELoaded
#define NUMICONS(x)                 (short)_animStruct[x].sNumIcons
#define INDEX(x)                    (short)_animStruct[x].sIndex
#define HPREVICON(x)                (HICON)_animStruct[x].hPrevIcon
#define TIMEINT(x)                  (short)_animStruct[x].sTimeInt
#define COUNTDOWN(x)                (short)_animStruct[x].sCountDn
#define HWNDTARGET(x)               (HWND)_animStruct[x].hWndTarget
#define HICONS(x)                   _animStruct[x].hIcons
#define SZFILENAME(x)               (char *)_animStruct[x].szFileName
#define SZEXELINK(x)                (char *)_animStruct[x].szEXELink

//////////////////////  OTHER MACROS  ///////////////////////////////

// Invalidates status bar to be redrawn, or updated.
#define UPDATE_STATBAR              InvalidateRect(_hwndStatus,NULL,TRUE)

#define LoadStr(x,y)    LoadString(_hInst,(UINT)(x),(LPSTR)(y),sizeof(y))

// my own version of WINDOWSX.H for MDI controls (you may want
// to add this in to your WINDOWSX.H file):

#define MDI_GetActive(x)  (HWND)(DWORD)(SendMessage((HWND)(x), \
    WM_MDIGETACTIVE,(WPARAM)0,(LPARAM)0L))

#define MDI_Create(x,y)   \
    (UINT)( IsWindow((HWND)(x)) ? \
            SendMessage((HWND)(x), WM_MDICREATE, (WPARAM)0, \
            (LPARAM)(LPMDICREATESTRUCT)(y)) : NULL)

#define MDI_Destroy(x,y) SendMessage((HWND)(x),WM_MDIDESTROY, \
    (WPARAM)(y),(LPARAM)0L)

#ifdef DEBUG
#define OD(x)                       OutputDebugString ((LPSTR)x)
#endif

#define Color(x)                    (COLORREF)GetSysColor(x)

///////////////////  EXTERNAL VARIABLES   //////////////////////////

extern HINSTANCE        _hInst;
extern HWND             _hwndFrame, _hwndClient, _hwndStatus;
extern HMENU            _hmenuMain, _hmenuMainWindow, _hmenuChild, 
                        _hmenuChildWindow;
extern LONG             _lPageFlags;

extern char             _szAppName[32];
extern char             _szChildClass[32];
extern char             _szTitleBar[32];
extern char             _szStatBarClass[32];
extern char             _szUntitled[32];
extern char             _szExtension[5];
extern char             _szTimeInt[32];
extern char             _szInfo[32];
extern char             _szNumIcons[32];
extern char             _szLinkFile[32];
extern char             _szIconSection[32];
extern char             _szIcon[32];
extern char             _szAutoAnimateKey[32];

extern FARPROC          _lpfnTimer;
extern FARPROC          _lpfnNotify;
extern FARPROC          _lpfnAbout;
extern FARPROC          _lpfnBroadcast;
extern FARPROC          _lpfnSettings;
extern HWND             _hTargethWnd;
extern HPEN             _hpnGray;
extern HPEN             _hpnBlack;
extern HPEN             _hpnWhite;
extern int              _nTimerInterval;
extern int              _nStatBarDY;
extern ANIMSTRUCT       _animStruct[MAXANIMATIONS];


extern LPSTR            _lpszIconFilter[3];       // filter for *.ICO extension
extern LPSTR            _lpszScriptFilter[5];     // filter for *.ANM and *.* 
extern LPSTR            _lpszEXEFilter[5];        // filter for *.EXE and *.COM


//////////////////  PROTOTYPE DECLARATIONS  ////////////////////////

#ifdef __cplusplus
extern "C" {
#endif 

// MAIN.C 
extern VOID WINAPI              CenterWindow (HWND);      
extern BOOL WINAPI              RestorePosition (HWND,short);
extern VOID WINAPI              RecordPosition (HWND);
extern short WINAPI             IntFromString (LPSTR FAR *);
extern HWND WINAPI              GetWindowListbox (VOID);
extern short WINAPI             GetWindowNumber(VOID);
extern BOOL WINAPI              DeleteCurSel (HWND);
extern VOID WINAPI              DeletePreviousHandles (HWND);
extern VOID WINAPI              SetupIconHandles (HWND);
extern BOOL WINAPI              CheckForDoubles (HWND);
extern VOID WINAPI              MESSAGE (WORD);
extern UINT WINAPI              GetTextWidth (HDC,LPSTR);
extern UINT WINAPI              GetTextHeight (HDC,LPSTR);
extern UINT WINAPI              GetANSITextHeight (VOID);
extern HWND WINAPI              GetAppTaskWindow (char *);
extern BOOL _export CALLBACK    NotifyProc (WORD,DWORD);

// FRAME.C 
extern LRESULT _export CALLBACK FrameProc (WNDPROC_PARAMS);
extern BOOL _export CALLBACK    BroadcastProc (HWND,LONG);
extern VOID WINAPI              RefreshAnimations (VOID);

// CHILD.C 
extern LRESULT _export CALLBACK ChildProc (WNDPROC_PARAMS);

// STATBAR.C 
extern LRESULT _export CALLBACK StatusBarProc (WNDPROC_PARAMS);

// ABOUT.C
extern BOOL _export CALLBACK    About (DLGPROC_PARAMS);

// TIMER.C
extern VOID _export CALLBACK    TimerCallback (HWND,UINT,UINT,DWORD);
extern VOID WINAPI              InvalidateAll (HWND, HICON);

// SETTINGS.C
extern BOOL _export CALLBACK    SettingsDlg (DLGPROC_PARAMS);

// SHOWTASK.C 
extern HANDLE _export CALLBACK  ShowTaskDlg(DLGPROC_PARAMS);
extern BOOL _export CALLBACK    EnumCallback (HWND, LONG);

// FILEIO.C 
extern BOOL WINAPI              ShowCommonDialog (HWND, LPSTR * , LPSTR, LPSTR, LPSTR, BOOL);
extern VOID WINAPI              SaveIconsToFile (HWND, WORD);
extern BOOL WINAPI              OpenIconsInFile (char *);
extern BOOL WINAPI              LinkToExecutable (LPSTR);
extern BOOL WINAPI              GetPathIfNoPath (LPSTR);
#ifdef __cplusplus
}
#endif
