zduke/source/win32/eaxedit.cpp
Rachael Alexanderson 129a83b4e4 - import
2020-07-17 04:59:23 -04:00

1374 lines
37 KiB
C++

#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0500
#define _WIN32_IE 0x0500
#include <windows.h>
#include <commctrl.h>
#include <commdlg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "resource.h"
#include "s_sound.h"
#include "templates.h"
#include "cmdlib.h"
#include "c_dispatch.h"
#include "c_cvars.h"
#include "doomstat.h"
// More w32api lackings
#ifndef TTM_SETTITLE
#define TTM_SETTITLEA (WM_USER+32)
#define TTM_SETTITLEW (WM_USER+33)
#ifdef UNICODE
#define TTM_SETTITLE TTM_SETTITLEW
#else
#define TTM_SETTITLE TTM_SETTITLEA
#endif
#endif
#ifndef TTF_TRACK
#define TTF_TRACK 0x0020
#endif
#ifndef TTF_TRANSPARENT
#define TTF_TRANSPARENT 0x0100
#endif
#ifndef OFN_ENABLESIZING
#define OFN_ENABLESIZING 0x00800000
typedef struct w32apiFixedOFNA {
DWORD lStructSize;
HWND hwndOwner;
HINSTANCE hInstance;
LPCSTR lpstrFilter;
LPSTR lpstrCustomFilter;
DWORD nMaxCustFilter;
DWORD nFilterIndex;
LPSTR lpstrFile;
DWORD nMaxFile;
LPSTR lpstrFileTitle;
DWORD nMaxFileTitle;
LPCSTR lpstrInitialDir;
LPCSTR lpstrTitle;
DWORD Flags;
WORD nFileOffset;
WORD nFileExtension;
LPCSTR lpstrDefExt;
LPARAM lCustData;
LPOFNHOOKPROC lpfnHook;
LPCSTR lpTemplateName;
void *pvReserved;
DWORD dwReserved;
DWORD FlagsEx;
} FIXEDOPENFILENAMEA;
#define OPENFILENAME FIXEDOPENFILENAMEA
#endif
extern HINSTANCE g_hInst;
extern HWND Window;
extern bool ForceWindowed;
EXTERN_CVAR (Bool, fullscreen)
extern ReverbContainer *ForcedEnvironment;
HWND EAXEditWindow;
HWND hPropList;
POINT PropListMaxSize;
LONG PropListHeightDiff;
POINT EditWindowSize;
POINT DoneLocation;
WNDPROC StdEditProc;
LONG NewLeft;
LONG SaveLeft;
LONG RevertLeft;
POINT TestLocation;
bool SpawnEAXWindow;
REVERB_PROPERTIES SavedProperties;
ReverbContainer *CurrentEnv;
CUSTOM_CVAR (Bool, eaxedit_test, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL)
{
if (EAXEditWindow != 0)
{
CheckDlgButton (EAXEditWindow, IDC_TESTEAX, self ? BST_CHECKED : BST_UNCHECKED);
if (self)
{
ForcedEnvironment = CurrentEnv;
}
else
{
ForcedEnvironment = NULL;
}
}
}
struct MySaveData
{
const ReverbContainer *Default;
const ReverbContainer **Saves;
UINT NumSaves;
MySaveData (const ReverbContainer *def)
: Default (def), Saves (NULL), NumSaves (0) {}
~MySaveData ()
{
if (Saves) delete[] Saves;
}
};
struct EnvControl
{
const char *Name;
int EditControl;
int SliderControl;
int Min;
int Max;
float REVERB_PROPERTIES::*Float;
int REVERB_PROPERTIES::*Int;
HWND EditHWND;
HWND SliderHWND;
};
struct EnvFlag
{
const char *Name;
int CheckboxControl;
unsigned int Flag;
HWND CheckboxHWND;
};
void PopulateEnvDropDown (HWND hCtl);
void SetupEnvControls (HWND hDlg);
void UpdateControls (const ReverbContainer *env, HWND hDlg);
void UpdateControl (const EnvControl *control, int value, bool slider);
EnvControl EnvControls[] =
{
{ "Environment", 0, 0, 0, 25, 0, &REVERB_PROPERTIES::Environment },
{ "EnvironmentSize", IDCE_ENVIRONMENTSIZE, IDCS_ENVIRONMENTSIZE, 1000, 100000, &REVERB_PROPERTIES::EnvSize, 0 },
{ "EnvironmentDiffusion", IDCE_ENVIRONMENTDIFFUSION, IDCS_ENVIRONMENTDIFFUSION, 0, 1000, &REVERB_PROPERTIES::EnvDiffusion, 0 },
{ "Room", IDCE_ROOM, IDCS_ROOM, -10000, 0, 0, &REVERB_PROPERTIES::Room },
{ "RoomHF", IDCE_ROOMHF, IDCS_ROOMHF, -10000, 0, 0, &REVERB_PROPERTIES::RoomHF },
{ "RoomLF", IDCE_ROOMLF, IDCS_ROOMLF, -10000, 0, 0, &REVERB_PROPERTIES::RoomLF },
{ "DecayTime", IDCE_DECAYTIME, IDCS_DECAYTIME, 100, 20000, &REVERB_PROPERTIES::DecayTime, 0 },
{ "DecayHFRatio", IDCE_DECAYHFRATIO, IDCS_DECAYHFRATIO, 100, 2000, &REVERB_PROPERTIES::DecayHFRatio, 0 },
{ "DecayLFRatio", IDCE_DECAYLFRATIO, IDCS_DECAYLFRATIO, 100, 2000, &REVERB_PROPERTIES::DecayLFRatio, 0 },
{ "Reflections", IDCE_REFLECTIONS, IDCS_REFLECTIONS, -10000, 1000, 0, &REVERB_PROPERTIES::Reflections },
{ "ReflectionsDelay", IDCE_REFLECTIONSDELAY, IDCS_REFLECTIONSDELAY, 0, 300, &REVERB_PROPERTIES::ReflectionsDelay, 0 },
{ "ReflectionsPanX", IDCE_REFLECTIONSPANX, IDCS_REFLECTIONSPANX, -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan0, 0 },
{ "ReflectionsPanY", IDCE_REFLECTIONSPANY, IDCS_REFLECTIONSPANY, -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan1, 0 },
{ "ReflectionsPanZ", IDCE_REFLECTIONSPANZ, IDCS_REFLECTIONSPANZ, -2000000, 2000000, &REVERB_PROPERTIES::ReflectionsPan2, 0 },
{ "Reverb", IDCE_REVERB, IDCS_REVERB, -10000, 2000, 0, &REVERB_PROPERTIES::Reverb },
{ "ReverbDelay", IDCE_REVERBDELAY, IDCS_REVERBDELAY, 0, 100, &REVERB_PROPERTIES::ReverbDelay, 0 },
{ "ReverbPanX", IDCE_REVERBPANX, IDCS_REVERBPANX, -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan0, 0 },
{ "ReverbPanY", IDCE_REVERBPANY, IDCS_REVERBPANY, -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan1, 0 },
{ "ReverbPanZ", IDCE_REVERBPANZ, IDCS_REVERBPANZ, -2000000, 2000000, &REVERB_PROPERTIES::ReverbPan2, 0 },
{ "EchoTime", IDCE_ECHOTIME, IDCS_ECHOTIME, 75, 250, &REVERB_PROPERTIES::EchoTime, 0 },
{ "EchoDepth", IDCE_ECHODEPTH, IDCS_ECHODEPTH, 0, 1000, &REVERB_PROPERTIES::EchoDepth, 0 },
{ "ModulationTime", IDCE_MODULATIONTIME, IDCS_MODULATIONTIME, 40, 4000, &REVERB_PROPERTIES::ModulationTime, 0 },
{ "ModulationDepth", IDCE_MODULATIONDEPTH, IDCS_MODULATIONDEPTH, 0, 1000, &REVERB_PROPERTIES::ModulationDepth, 0 },
{ "AirAbsorptionHF", IDCE_AIRABSORPTIONHF, IDCS_AIRABSORPTIONHF, -100000, 0, &REVERB_PROPERTIES::AirAbsorptionHF, 0 },
{ "HFReference", IDCE_HFREFERENCE, IDCS_HFREFERENCE, 1000000, 20000000, &REVERB_PROPERTIES::HFReference, 0 },
{ "LFReference", IDCE_LFREFERENCE, IDCS_LFREFERENCE, 20000, 1000000, &REVERB_PROPERTIES::LFReference, 0 },
{ "RoomRolloffFactor", IDCE_ROOMROLLOFFFACTOR, IDCS_ROOMROLLOFFFACTOR, 0, 10000, &REVERB_PROPERTIES::RoomRolloffFactor, 0 },
{ "Diffusion", 0, 0, 0, 100000, &REVERB_PROPERTIES::Diffusion, 0 },
{ "Density", 0, 0, 0, 100000, &REVERB_PROPERTIES::Density, 0 },
};
EnvFlag EnvFlags[] =
{
{ "bReflectionsScale", IDC_REFLECTIONSSCALE, REVERB_FLAGS_REFLECTIONSSCALE },
{ "bReflectionsDelayScale", IDC_REFLECTIONSDELAYSCALE, REVERB_FLAGS_REFLECTIONSDELAYSCALE },
{ "bDecayTimeScale", IDC_DECAYTIMESCALE, REVERB_FLAGS_DECAYTIMESCALE },
{ "bDecayHFLimit", IDC_DECAYHFLIMIT, REVERB_FLAGS_DECAYHFLIMIT },
{ "bReverbScale", IDC_REVERBSCALE, REVERB_FLAGS_REVERBSCALE },
{ "bReverbDelayScale", IDC_REVERBDELAYSCALE, REVERB_FLAGS_REVERBDELAYSCALE },
{ "bEchoTimeScale", IDC_ECHOTIMESCALE, REVERB_FLAGS_ECHOTIMESCALE },
{ "bModulationTimeScale", IDC_MODULATIONTIMESCALE, REVERB_FLAGS_MODULATIONTIMESCALE }
};
LRESULT AddEnvToDropDown (HWND hCtl, bool showID, const ReverbContainer *env)
{
char buff[128];
LRESULT i;
if (showID)
{
sprintf (buff, "(%3d,%3d) %s", HIBYTE(env->ID), LOBYTE(env->ID), env->Name);
i = SendMessage (hCtl, CB_ADDSTRING, 0, (LPARAM)buff);
}
else
{
i = SendMessage (hCtl, CB_ADDSTRING, 0, (LPARAM)env->Name);
}
SendMessage (hCtl, CB_SETITEMDATA, i, (LPARAM)env);
return i;
}
void PopulateEnvDropDown (HWND hCtl, bool showIDs, const ReverbContainer *defEnv)
{
const ReverbContainer *env;
WPARAM envCount = 0;
LPARAM strCount = 0;
LRESULT i;
for (env = Environments; env != NULL; env = env->Next)
{
envCount++;
strCount += strlen (env->Name) + 1;
}
SendMessage (hCtl, WM_SETREDRAW, FALSE, 0);
SendMessage (hCtl, CB_RESETCONTENT, 0, 0);
SendMessage (hCtl, CB_INITSTORAGE, envCount, showIDs ?
strCount + envCount * 10 : strCount);
for (env = Environments; env != NULL; env = env->Next)
{
AddEnvToDropDown (hCtl, showIDs, env);
}
SendMessage (hCtl, WM_SETREDRAW, TRUE, 0);
if (defEnv == NULL)
{
SendMessage (hCtl, CB_SETCURSEL, 0, 0);
SetFocus (hCtl);
}
else
{
for (i = 0; i < (LPARAM)envCount; ++i)
{
if ((const ReverbContainer *)SendMessage (hCtl, CB_GETITEMDATA, i, 0)
== defEnv)
{
SendMessage (hCtl, CB_SETCURSEL, i, 0);
break;
}
}
}
}
void SetIDEdits (HWND hDlg, WORD id)
{
char text[4];
sprintf (text, "%d", HIBYTE(id));
SendMessage (GetDlgItem (hDlg, IDC_EDITID1), WM_SETTEXT, 0, (LPARAM)text);
sprintf (text, "%d", LOBYTE(id));
SendMessage (GetDlgItem (hDlg, IDC_EDITID2), WM_SETTEXT, 0, (LPARAM)text);
}
void PopulateEnvList (HWND hCtl, bool show, const ReverbContainer *defEnv)
{
const ReverbContainer *env;
int i;
LVITEM item;
SendMessage (hCtl, WM_SETREDRAW, FALSE, 0);
item.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
item.stateMask = LVIS_SELECTED|LVIS_FOCUSED;
item.iSubItem = 0;
for (env = Environments, i = 0; env != NULL; env = env->Next, ++i)
{
if (!env->Builtin || show)
{
item.iItem = i;
item.pszText = (LPSTR)env->Name;
item.lParam = (LPARAM)env;
item.state = env == defEnv ? LVIS_SELECTED|LVIS_FOCUSED : 0;
SendMessage (hCtl, LVM_INSERTITEM, 0, (LPARAM)&item);
}
}
SendMessage (hCtl, WM_SETREDRAW, TRUE, 0);
}
WORD FirstFreeID (WORD base, bool builtin)
{
int tryCount = 0;
int priID = HIBYTE(base);
// If the original sound is built-in, start searching for a new
// primary ID at 30.
if (builtin)
{
for (priID = 30; priID < 256; ++priID)
{
if (S_FindEnvironment (priID << 8) == NULL)
{
break;
}
}
if (priID == 256)
{ // Oh well.
priID = 30;
}
}
for (;;)
{
WORD lastID = Environments->ID;
const ReverbContainer *env = Environments->Next;
// Find the lowest-numbered free ID with the same primary ID as base
// If none are available, add 100 to base's primary ID and try again.
// If that fails, then the primary ID gets incremented
// by 1 until a match is found. If all the IDs searchable by this
// algorithm are in use, then you're in trouble.
while (env != NULL)
{
if (HIBYTE(env->ID) > priID)
{
break;
}
if (HIBYTE(env->ID) == priID)
{
if (HIBYTE(lastID) == priID)
{
if (LOBYTE(env->ID) - LOBYTE(lastID) > 1)
{
return lastID+1;
}
}
lastID = env->ID;
}
env = env->Next;
}
if (LOBYTE(lastID) == 255)
{
if (tryCount == 0)
{
base += 100*256;
tryCount = 1;
}
else
{
base += 256;
}
}
else if (builtin && lastID == 0)
{
return priID << 8;
}
else
{
return lastID+1;
}
}
}
LRESULT CALLBACK EditControlProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char buff[16];
double val;
const EnvControl *env;
MSG *msg;
switch (uMsg)
{
case WM_GETDLGCODE:
msg = (MSG *)lParam;
if (msg && LOWORD(msg->message) == WM_KEYDOWN)
{
// Do not close the dialog if Enter was pressed
// inside an edit control.
if (msg->wParam == VK_RETURN || msg->wParam == VK_ESCAPE)
{
return DLGC_WANTALLKEYS;
}
}
break;
case WM_CHAR:
// Only allow numeric symbols.
if (wParam >= ' ' && wParam <= 127 &&
(wParam < '0' || wParam > '9') &&
wParam != '.' &&
wParam != '-' &&
wParam != '+')
{
return 0;
}
break;
case WM_KEYDOWN:
if (wParam != VK_RETURN)
{
if (wParam == VK_ESCAPE)
{ // Put the original value back in the edit control.
env = (const EnvControl *)GetWindowLongPtr (hWnd, GWLP_USERDATA);
int vali = SendMessage (env->SliderHWND, TBM_GETPOS, 0, 0);
if (env->Float)
{
sprintf (buff, "%d.%03d", vali/1000, abs(vali%1000));
}
else
{
sprintf (buff, "%d", vali);
}
CallWindowProc (StdEditProc, hWnd, WM_SETTEXT, 0, (LPARAM)buff);
CallWindowProc (StdEditProc, hWnd, EM_SETSEL, 0, -1);
return 0;
}
break;
}
// intentional fallthrough
case WM_KILLFOCUS:
// Validate the new value and update the corresponding slider.
env = (const EnvControl *)GetWindowLongPtr (hWnd, GWLP_USERDATA);
val = 0.0;
if (CallWindowProc (StdEditProc, hWnd, WM_GETTEXT, 16, (LPARAM)buff) > 0)
{
val = atof (buff);
}
if (env->Float)
{
val *= 1000.0;
}
if (val < env->Min) val = env->Min;
else if (val > env->Max) val = env->Max;
UpdateControl (env, int(val), true);
break;
}
return CallWindowProc (StdEditProc, hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK EditControlProcNoDeci (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// This is just like the above WndProc, except it only accepts integers.
if (uMsg == WM_CHAR && wParam == '.')
{
return 0;
}
return EditControlProc (hWnd, uMsg, wParam, lParam);
}
void SetupEnvControls (HWND hDlg)
{
size_t i;
for (i = 0; i < sizeof(EnvControls)/sizeof(EnvControls[0]); ++i)
{
if (EnvControls[i].EditControl == 0)
continue;
EnvControls[i].EditHWND = GetDlgItem (hDlg, EnvControls[i].EditControl);
EnvControls[i].SliderHWND = GetDlgItem (hDlg, EnvControls[i].SliderControl);
SendMessage (EnvControls[i].SliderHWND, TBM_SETRANGEMIN, FALSE, EnvControls[i].Min);
SendMessage (EnvControls[i].SliderHWND, TBM_SETRANGEMAX, TRUE, EnvControls[i].Max);
SendMessage (EnvControls[i].EditHWND, EM_LIMITTEXT, 10, 0);
StdEditProc = (WNDPROC)SetWindowLongPtr (EnvControls[i].EditHWND, GWLP_WNDPROC,
(LONG_PTR)(EnvControls[i].Float ? EditControlProc : EditControlProcNoDeci));
SetWindowLongPtr (EnvControls[i].EditHWND, GWLP_USERDATA, (LONG_PTR)&EnvControls[i]);
SetWindowLongPtr (EnvControls[i].SliderHWND, GWLP_USERDATA, (LONG_PTR)&EnvControls[i]);
}
for (i = 0; i < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++i)
{
EnvFlags[i].CheckboxHWND = GetDlgItem (hDlg, EnvFlags[i].CheckboxControl);
SetWindowLongPtr (EnvFlags[i].CheckboxHWND, GWLP_USERDATA, (LONG_PTR)&EnvFlags[i]);
}
}
void UpdateControl (const EnvControl *control, int value, bool slider)
{
char buff[16];
if (slider)
{
SendMessage (control->SliderHWND, TBM_SETPOS, TRUE, value);
}
if (control->Float)
{
sprintf (buff, "%d.%03d", value/1000, abs(value%1000));
if (CurrentEnv != NULL)
{
CurrentEnv->Properties.*control->Float = float(value) / 1000.0;
}
}
else
{
sprintf (buff, "%d", value);
if (CurrentEnv != NULL)
{
CurrentEnv->Properties.*control->Int = value;
}
}
SendMessage (control->EditHWND, WM_SETTEXT, 0, (LPARAM)buff);
if (CurrentEnv != NULL)
{
CurrentEnv->Modified = true;
}
}
void UpdateControls (ReverbContainer *env, HWND hDlg)
{
char buff[4];
size_t i;
if (env == NULL)
return;
CurrentEnv = NULL;
for (i = 0; i < sizeof(EnvControls)/sizeof(EnvControls[0]); ++i)
{
EnvControl *ctrl = &EnvControls[i];
if (ctrl->Float)
{
float v = env->Properties.*ctrl->Float * 1000;
UpdateControl (ctrl, int(v >= 0.0 ? v + 0.5 : v - 0.5), true);
}
else
{
UpdateControl (ctrl, env->Properties.*ctrl->Int, true);
}
EnableWindow (ctrl->EditHWND, !env->Builtin);
EnableWindow (ctrl->SliderHWND, !env->Builtin);
}
for (i = 0; i < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++i)
{
SendMessage (EnvFlags[i].CheckboxHWND, BM_SETCHECK,
(env->Properties.Flags & EnvFlags[i].Flag) ? BST_CHECKED : BST_UNCHECKED, 0);
EnableWindow (EnvFlags[i].CheckboxHWND, !env->Builtin);
}
EnableWindow (GetDlgItem (hDlg, IDC_REVERT), !env->Builtin);
sprintf (buff, "%d", HIBYTE(env->ID));
SendMessage (GetDlgItem (hDlg, IDC_ID1), WM_SETTEXT, 0, (LPARAM)buff);
sprintf (buff, "%d", LOBYTE(env->ID));
SendMessage (GetDlgItem (hDlg, IDC_ID2), WM_SETTEXT, 0, (LPARAM)buff);
SavedProperties = env->Properties;
CurrentEnv = env;
if (SendMessage (GetDlgItem (hDlg, IDC_TESTEAX), BM_GETCHECK, 0,0) == BST_CHECKED)
{
ForcedEnvironment = env;
}
}
INT_PTR CALLBACK EAXProp (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
const EnvControl *env;
SCROLLINFO si;
int yPos;
switch (uMsg)
{
case WM_INITDIALOG:
SetupEnvControls (hDlg);
return FALSE;
case WM_VSCROLL:
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo (hDlg, SB_VERT, &si);
yPos = si.nPos;
switch (LOWORD(wParam))
{
case SB_TOP: si.nPos = si.nMin; break;
case SB_BOTTOM: si.nPos = si.nMax; break;
case SB_LINEUP: si.nPos -= 16; break;
case SB_LINEDOWN: si.nPos += 16; break;
case SB_PAGEUP: si.nPos -= si.nPage; break;
case SB_PAGEDOWN: si.nPos += si.nPage; break;
case SB_THUMBTRACK: si.nPos = si.nTrackPos; break;
}
si.fMask = SIF_POS;
SetScrollInfo (hDlg, SB_VERT, &si, TRUE);
GetScrollInfo (hDlg, SB_VERT, &si);
if (si.nPos != yPos)
{
ScrollWindow (hDlg, 0, yPos - si.nPos, NULL, NULL);
UpdateWindow (hDlg);
}
return TRUE;
case WM_HSCROLL:
env = (const EnvControl *)GetWindowLongPtr ((HWND)lParam, GWLP_USERDATA);
UpdateControl (env, SendMessage ((HWND)lParam, TBM_GETPOS, 0, 0), false);
return TRUE;
case WM_SIZE:
if (wParam != SIZE_MAXSHOW && wParam != SIZE_MAXHIDE)
{
si.cbSize = sizeof(si);
si.fMask = SIF_POS;
GetScrollInfo (hDlg, SB_VERT, &si);
yPos = si.nPos;
// If we let the scroll bar disappear, then when that happens,
// it will resize the window before SetScrollInfo returns.
// Rather than checking for recursive WM_SIZE messages, I choose
// to force the scroll bar to always be present. The dialog is
// really designed with the appearance of the scroll bar in
// mind anyway, since it does nothing to resize the controls
// horizontally.
si.fMask = SIF_POS|SIF_PAGE|SIF_DISABLENOSCROLL;
si.nPage = HIWORD(lParam);
SetScrollInfo (hDlg, SB_VERT, &si, TRUE);
GetScrollInfo (hDlg, SB_VERT, &si);
if (si.nPos != yPos)
{
ScrollWindow (hDlg, 0, yPos - si.nPos, NULL, NULL);
UpdateWindow (hDlg);
}
}
return TRUE;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED && CurrentEnv != NULL)
{
for (size_t i = 0; i < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++i)
{
if ((HWND)lParam == EnvFlags[i].CheckboxHWND)
{
if (SendMessage ((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED)
{
CurrentEnv->Properties.Flags |= EnvFlags[i].Flag;
}
else
{
CurrentEnv->Properties.Flags &= ~EnvFlags[i].Flag;
}
return TRUE;;
}
}
}
return FALSE;
}
return FALSE;
}
void SuggestNewName (const ReverbContainer *env, HWND hEdit)
{
const ReverbContainer *probe;
char text[32];
size_t len;
int number, numdigits;
strncpy (text, env->Name, 31);
text[31] = 0;
len = strlen (text);
while (text[len-1] >= '0' && text[len-1] <= '9')
{
len--;
}
number = atoi (text + len);
if (number < 1)
{
number = 1;
}
if (text[len-1] != ' ' && len < 31)
{
text[len++] = ' ';
}
for (; number < 100000; ++number)
{
if (number < 10) numdigits = 1;
else if (number < 100) numdigits = 2;
else if (number < 1000) numdigits = 3;
else if (number < 10000)numdigits = 4;
else numdigits = 5;
if (len + numdigits > 31)
{
len = 31 - numdigits;
}
sprintf (text + len, "%d", number);
probe = Environments;
while (probe != NULL)
{
if (stricmp (probe->Name, text) == 0)
break;
probe = probe->Next;
}
if (probe == NULL)
{
break;
}
}
if (probe == NULL)
{
SetWindowText (hEdit, text);
}
}
void ShowErrorTip (HWND ToolTip, TOOLINFO &ti, HWND hDlg, const char *title)
{
SendMessage (ToolTip, TTM_SETTITLE, 3, (LPARAM)title);
ti.cbSize = sizeof(ti);
ti.hinst = g_hInst;
SendMessage (ToolTip, TTM_UPDATETIPTEXT, 0, (LPARAM)&ti);
GetClientRect (ti.hwnd, &ti.rect);
POINT pt = { (ti.rect.left + ti.rect.right) / 2, ti.rect.bottom - 4 };
ClientToScreen (ti.hwnd, &pt);
SendMessage (ToolTip, TTM_TRACKACTIVATE, FALSE, 0);
SendMessage (ToolTip, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));
SendMessage (ToolTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);
SetFocus (ti.hwnd);
SendMessage (ti.hwnd, EM_SETSEL, 0, -1);
MessageBeep (MB_ICONEXCLAMATION);
SetTimer (hDlg, 11223, 10000, NULL);
}
INT_PTR CALLBACK NewEAXProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
const ReverbContainer *rev;
TOOLINFO ti;
char buff[33], buff4[4];
int id1, id2;
static HWND ToolTip;
HWND hWnd;
int i;
switch (uMsg)
{
case WM_INITDIALOG:
hWnd = GetDlgItem (hDlg, IDC_ENVIRONMENTLIST);
PopulateEnvList (hWnd, true, (const ReverbContainer *)lParam);
SendMessage (GetDlgItem (hDlg, IDC_SPINID1), UDM_SETRANGE, 0, MAKELONG(255,0));
SendMessage (GetDlgItem (hDlg, IDC_SPINID2), UDM_SETRANGE, 0, MAKELONG(255,0));
SendMessage (GetDlgItem (hDlg, IDC_EDITID1), EM_LIMITTEXT, 3, 0);
SendMessage (GetDlgItem (hDlg, IDC_EDITID2), EM_LIMITTEXT, 3, 0);
hWnd = GetDlgItem (hDlg, IDC_NEWENVNAME);
SendMessage (hWnd, EM_LIMITTEXT, 31, 0);
SuggestNewName ((const ReverbContainer *)lParam, hWnd);
SetIDEdits (hDlg, FirstFreeID (((const ReverbContainer *)lParam)->ID,
((const ReverbContainer *)lParam)->Builtin));
ToolTip = CreateWindowEx (WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON|TTS_CLOSE,
0, 0, 0, 0,
hDlg, NULL, g_hInst, NULL);
if (ToolTip)
{
ti.cbSize = sizeof(ti);
ti.uFlags = TTF_TRACK | TTF_TRANSPARENT;
ti.hinst = g_hInst;
ti.lpszText = "";
for (i = 0; i < 3; ++i)
{
ti.uId = i;
ti.hwnd = GetDlgItem (hDlg, IDC_NEWENVNAME+i);
GetClientRect (ti.hwnd, &ti.rect);
SendMessage (ToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
}
}
return 1;
case WM_TIMER:
if (wParam == 11223)
{
SendMessage (ToolTip, TTM_TRACKACTIVATE, FALSE, 0);
KillTimer (hDlg, 11223);
}
return 1;
case WM_MOVE:
// Just hide the tool tip if the user moves the window.
SendMessage (ToolTip, TTM_TRACKACTIVATE, FALSE, 0);
return 1;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
id1 = 256; id2 = 256;
buff[0] = 0;
if (0 == GetWindowText (GetDlgItem (hDlg, IDC_NEWENVNAME), buff, 32) ||
S_FindEnvironment (buff) != NULL)
{
static CHAR *texts[2] =
{
"That name is already used.",
"Please enter a name."
};
ti.uId = 0;
ti.hwnd = GetDlgItem (hDlg, IDC_NEWENVNAME);
ti.lpszText = buff[0] ? texts[0] : texts[1];
ShowErrorTip (ToolTip, ti, hDlg, "Bad Name");
return 0;
}
if (0 < GetWindowText (GetDlgItem (hDlg, IDC_EDITID1), buff4, 4))
{
id1 = atoi (buff4);
}
if (0 < GetWindowText (GetDlgItem (hDlg, IDC_EDITID2), buff4, 4))
{
id2 = atoi (buff4);
}
if (id1 > 255 || id2 > 255)
{
ti.uId = id1 > 255 ? 1 : 2;
ti.hwnd = GetDlgItem (hDlg, IDC_EDITID1 + ti.uId - 1);
ti.lpszText = "Please enter a number between 0 and 255.";
ShowErrorTip (ToolTip, ti, hDlg, "Bad Value");
}
else if (NULL != (rev = S_FindEnvironment (MAKEWORD (id2, id1))))
{
static char foo[80];
ti.uId = 2;
ti.hwnd = GetDlgItem (hDlg, IDC_EDITID2);
sprintf (foo, "This ID is already used by \"%s\".", rev->Name);
ti.lpszText = foo;
ShowErrorTip (ToolTip, ti, hDlg, "Bad ID");
}
else
{
LVITEM item;
hWnd = GetDlgItem (hDlg, IDC_ENVIRONMENTLIST);
i = SendMessage (hWnd, LVM_GETNEXTITEM, -1, LVNI_ALL|LVNI_SELECTED);
if (i == -1)
{
MessageBeep (MB_ICONEXCLAMATION);
return 0;
}
item.iItem = i;
item.iSubItem = 0;
item.mask = LVIF_PARAM;
if (!SendMessage (hWnd, LVM_GETITEM, 0, (LPARAM)&item))
{
MessageBeep (MB_ICONEXCLAMATION);
return 0;
}
ReverbContainer *env = new ReverbContainer;
rev = (ReverbContainer *)item.lParam;
env->Builtin = false;
env->ID = MAKEWORD (id2, id1);
env->Name = copystring (buff);
env->Next = NULL;
env->Properties = rev->Properties;
S_AddEnvironment (env);
EndDialog (hDlg, (INT_PTR)env);
}
return 0;
case IDCANCEL:
EndDialog (hDlg, 0);
break;
}
return 0;
case WM_NOTIFY:
if (wParam == IDC_ENVIRONMENTLIST && ((LPNMHDR)lParam)->code == LVN_ITEMCHANGED)
{
LPNMLISTVIEW nmlv = (LPNMLISTVIEW)lParam;
if (nmlv->iItem != -1 &&
(nmlv->uNewState & LVIS_SELECTED) &&
!(nmlv->uOldState & LVIS_SELECTED))
{
SuggestNewName ((const ReverbContainer *)nmlv->lParam, GetDlgItem (hDlg, IDC_NEWENVNAME));
SetIDEdits (hDlg, FirstFreeID (((const ReverbContainer *)nmlv->lParam)->ID,
((const ReverbContainer *)lParam)->Builtin));
}
}
return 0;
}
return FALSE;
}
UINT_PTR CALLBACK SaveHookProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
static LONG ButtonsLeftOffset;
static LONG ListRightOffset;
static LONG GroupRightOffset;
MySaveData *msd;
HWND hWnd;
LVITEM item;
int i, count;
RECT rect1, rect2;
UINT ns;
switch (msg)
{
case WM_INITDIALOG:
GetClientRect (hDlg, &rect1);
GetWindowRect (GetDlgItem (hDlg, IDC_SELECTALL), &rect2);
ScreenToClient (hDlg, (LPPOINT)&rect2.left);
ButtonsLeftOffset = rect2.left - rect1.right;
GetWindowRect (GetDlgItem (hDlg, IDC_ENVLIST), &rect2);
ListRightOffset = (rect2.right - rect2.left) - rect1.right;
GetWindowRect (GetDlgItem (hDlg, IDC_SAVEGROUP), &rect2);
GroupRightOffset = (rect2.right - rect2.left) - rect1.right;
hWnd = GetDlgItem (hDlg, IDC_ENVLIST);
PopulateEnvList (hWnd, false,
((MySaveData *)(((LPOPENFILENAME)lParam)->lCustData))->Default);
SetWindowLongPtr (hDlg, DWLP_USER, (LONG_PTR)((LPOPENFILENAME)lParam)->lCustData);
return 1;
case WM_ERASEBKGND:
SetWindowLongPtr (hDlg, DWLP_MSGRESULT, 1);
return 1;
case WM_SIZE:
if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
{
GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_SAVEGROUP), &rect1);
SetWindowPos (hWnd, NULL, 0, 0, LOWORD(lParam) + GroupRightOffset, rect1.bottom-rect1.top, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_DEFERERASE);
GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_SELECTALL), &rect1);
ScreenToClient (hDlg, (LPPOINT)&rect1.left);
SetWindowPos (hWnd, NULL, LOWORD(lParam)+ButtonsLeftOffset, rect1.top, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER);
GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_SELECTNONE), &rect1);
ScreenToClient (hDlg, (LPPOINT)&rect1.left);
SetWindowPos (hWnd, NULL, LOWORD(lParam)+ButtonsLeftOffset, rect1.top, 0, 0, SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER);
GetWindowRect (hWnd = GetDlgItem (hDlg, IDC_ENVLIST), &rect1);
SetWindowPos (hWnd, NULL, 0, 0, LOWORD(lParam) + ListRightOffset, rect1.bottom-rect1.top, SWP_DEFERERASE|SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER);
}
return 1;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_SELECTALL:
case IDC_SELECTNONE:
hWnd = GetDlgItem (hDlg, IDC_ENVLIST);
SendMessage (hWnd, WM_SETREDRAW, FALSE, 0);
count = ListView_GetItemCount (hWnd);
item.iSubItem = 0;
item.mask = LVIF_STATE;
item.stateMask = LVIS_SELECTED;
item.state = LOWORD(wParam)==IDC_SELECTALL ? LVIS_SELECTED : 0;
for (i = 0; i < count; ++i)
{
item.iItem = i;
ListView_SetItem (hWnd, &item);
}
if (LOWORD(wParam) == IDC_SELECTALL)
{
SetFocus (hWnd);
}
SendMessage (hWnd, WM_SETREDRAW, TRUE, 0);
return 1;
}
return 0;
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case CDN_INITDONE:
hWnd = GetParent (hDlg);
GetWindowRect (hWnd, &rect1);
GetWindowRect (hDlg, &rect2);
SetWindowPos (hDlg, NULL, 0, 0, rect1.right-rect1.left, rect2.bottom-rect2.top, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER);
return 1;
case CDN_FILEOK:
msd = (MySaveData *)GetWindowLongPtr (hDlg, DWLP_USER);
hWnd = GetDlgItem (hDlg, IDC_ENVLIST);
ns = ListView_GetSelectedCount (hWnd);
if (ns == 0)
{
msd->NumSaves = 0;
if (IDNO == MessageBox (hDlg,
"You have not selected any EAX environments to save.\n"
"Do you want to cancel the save operation?",
"Nothing Selected",
MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2))
{
SetWindowLongPtr (hDlg, DWL_MSGRESULT, 1);
return 1;
}
}
else
{
UINT x;
msd->Saves = new const ReverbContainer *[ns];
item.iItem = -1;
item.iSubItem = 0;
item.mask = LVIF_PARAM;
for (x = 0; x != ns; )
{
item.iItem = ListView_GetNextItem (hWnd, item.iItem, LVNI_SELECTED);
if (item.iItem != -1 && ListView_GetItem (hWnd, &item))
{
msd->Saves[x++] = (const ReverbContainer *)item.lParam;
}
}
msd->NumSaves = x;
}
return 0;
}
return 0;
default:
return 0;
}
}
void ExportEnvironments (const char *filename, UINT count, const ReverbContainer **envs)
{
FILE *f;
retry:
f = fopen (filename, "w");
if (f != NULL)
{
for (UINT i = 0; i < count; ++i)
{
const ReverbContainer *env = envs[i];
const ReverbContainer *base;
size_t j;
if ((unsigned int)env->Properties.Environment < 26)
{
base = DefaultEnvironments[env->Properties.Environment];
}
else
{
base = NULL;
}
fprintf (f, "\"%s\" %u %u\n{\n", env->Name, HIBYTE(env->ID), LOBYTE(env->ID));
for (j = 0; j < sizeof(EnvControls)/sizeof(EnvControls[0]); ++j)
{
const EnvControl *ctl = &EnvControls[j];
if (ctl->Name &&
(j == 0 ||
(ctl->Float && base->Properties.*ctl->Float != env->Properties.*ctl->Float) ||
(ctl->Int && base->Properties.*ctl->Int != env->Properties.*ctl->Int))
)
{
fprintf (f, "\t%s ", ctl->Name);
if (ctl->Float)
{
float v = env->Properties.*ctl->Float * 1000;
int vi = int(v >= 0.0 ? v + 0.5 : v - 0.5);
fprintf (f, "%d.%03d\n", vi/1000, abs(vi%1000));
}
else
{
fprintf (f, "%d\n", env->Properties.*ctl->Int);
}
}
}
for (j = 0; j < sizeof(EnvFlags)/sizeof(EnvFlags[0]); ++j)
{
if (EnvFlags[j].Flag & (env->Properties.Flags ^ base->Properties.Flags))
{
fprintf (f, "\t%s %s\n", EnvFlags[j].Name,
EnvFlags[j].Flag & env->Properties.Flags ? "true" : "false");
}
}
fprintf (f, "}\n\n");
}
fclose (f);
}
else
{
LPVOID lpMsgBuf;
FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
if (IDRETRY == MessageBox (EAXEditWindow, (LPCTSTR)lpMsgBuf, "Save Failed!", MB_RETRYCANCEL|MB_ICONERROR))
{
LocalFree (lpMsgBuf);
goto retry;
}
LocalFree (lpMsgBuf);
}
}
void SaveEnvironments (HWND owner, const ReverbContainer *defEnv)
{
MySaveData msd (defEnv);
OPENFILENAME ofn;
char filename[PATH_MAX];
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = owner;
ofn.hInstance = g_hInst;
ofn.lpstrFilter = "Text Files\0*.txt\0All Files\0*.*\0";
ofn.lpstrCustomFilter = NULL;
ofn.nMaxCustFilter = 0;
ofn.nFilterIndex = 1;
ofn.lpstrFile = filename;
ofn.nMaxFile = sizeof(filename);
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = "Save EAX Environments As...";
ofn.Flags = OFN_ENABLEHOOK|OFN_ENABLESIZING|OFN_ENABLETEMPLATE|OFN_EXPLORER|
OFN_NOCHANGEDIR|OFN_OVERWRITEPROMPT;
ofn.nFileOffset = 0;
ofn.nFileExtension = 0;
ofn.lpstrDefExt = "txt";
ofn.lCustData = (LPARAM)&msd;
ofn.lpfnHook = SaveHookProc;
ofn.lpTemplateName = MAKEINTRESOURCE(IDD_SAVEEAX);
ofn.pvReserved = NULL;
ofn.dwReserved = 0;
ofn.FlagsEx = 0;
filename[0] = 0;
if (GetSaveFileName ((tagOFNA *)&ofn) && msd.NumSaves != 0)
{
ExportEnvironments (filename, msd.NumSaves, msd.Saves);
}
}
INT_PTR CALLBACK EAXProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SCROLLINFO scrollInfo;
HWND hWnd;
RECT rect;
POINT ul;
ReverbContainer *env;
switch (uMsg)
{
case WM_INITDIALOG:
hPropList = CreateDialog (g_hInst, MAKEINTRESOURCE(IDD_EAXPROPERTYLIST), hDlg, EAXProp);
hWnd = GetDlgItem (hDlg, IDC_DUMMY);
GetWindowRect (hPropList, &rect);
PropListMaxSize.x = rect.right - rect.left;
PropListMaxSize.y = rect.bottom - rect.top;
GetWindowRect (hWnd, &rect);
DestroyWindow (hWnd);
ul.x = rect.left;
ul.y = rect.top;
ScreenToClient (hDlg, &ul);
PropListMaxSize.x = rect.right - rect.left;
scrollInfo.cbSize = sizeof(scrollInfo);
scrollInfo.fMask = SIF_RANGE|SIF_POS|SIF_PAGE|SIF_DISABLENOSCROLL;
scrollInfo.nMin = 0;
scrollInfo.nMax = PropListMaxSize.y;
scrollInfo.nPos = 0;
scrollInfo.nPage = rect.bottom - rect.top;
SetScrollInfo (hPropList, SB_VERT, &scrollInfo, TRUE);
MoveWindow (hPropList, ul.x, ul.y, PropListMaxSize.x, rect.bottom - rect.top, FALSE);
ShowWindow (hPropList, SW_SHOW);
// Windows should have a layout control like MUI so that I don't have
// to do any extra work to make the dialog resizable.
GetClientRect (hDlg, &rect);
PropListHeightDiff = (rect.bottom - rect.top) - scrollInfo.nPage;
// Using a scroll bar to create a size box seems like an odd way of
// doing things.
hWnd = CreateWindow(
"Scrollbar",
(LPSTR)NULL,
WS_CHILD | WS_VISIBLE | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN | WS_CLIPSIBLINGS,
0,0,rect.right,rect.bottom,
hDlg,
(HMENU)IDC_SIZEBOX,
g_hInst,
NULL);
TestLocation.x = DoneLocation.x = rect.right;
TestLocation.y = DoneLocation.y = rect.bottom;
GetWindowRect (GetDlgItem (hDlg, IDOK), &rect);
ScreenToClient (hDlg, (LPPOINT)&rect.left);
DoneLocation.x -= rect.left;
DoneLocation.y -= rect.top;
GetWindowRect (GetDlgItem (hDlg, IDC_TESTEAX), &rect);
ScreenToClient (hDlg, (LPPOINT)&rect.left);
TestLocation.x -= rect.left;
TestLocation.y -= rect.top;
GetWindowRect (hDlg, &rect);
EditWindowSize.x = rect.right - rect.left;
EditWindowSize.y = (rect.bottom - rect.top) - scrollInfo.nPage;
GetWindowRect (GetDlgItem (hDlg, IDC_NEW), &rect);
ScreenToClient (hDlg, (LPPOINT)&rect.left);
NewLeft = rect.left;
GetWindowRect (GetDlgItem (hDlg, IDC_SAVE), &rect);
ScreenToClient (hDlg, (LPPOINT)&rect.left);
SaveLeft = rect.left;
GetWindowRect (GetDlgItem (hDlg, IDC_REVERT), &rect);
ScreenToClient (hDlg, (LPPOINT)&rect.left);
RevertLeft = rect.left;
hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT);
PopulateEnvDropDown (hWnd, IsDlgButtonChecked (hDlg, IDC_SHOWIDS)==BST_CHECKED, NULL);
EAXProc (hDlg, WM_COMMAND, MAKELONG(IDC_CURRENTENVIRONMENT,CBN_SELENDOK), (LPARAM)hWnd);
CheckDlgButton (hDlg, IDC_TESTEAX, eaxedit_test ? BST_CHECKED : BST_UNCHECKED);
return 0;
case WM_SIZE:
if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
{
GetClientRect (hWnd = GetDlgItem (hDlg, IDC_SIZEBOX), &rect);
SetWindowPos (hWnd, HWND_BOTTOM, LOWORD(lParam)-rect.right, HIWORD(lParam)-rect.bottom, 0, 0, SWP_NOSIZE);
SetWindowPos (hPropList, NULL, 0, 0, PropListMaxSize.x, HIWORD(lParam)-PropListHeightDiff, SWP_NOMOVE|SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_DEFERERASE);
SetWindowPos (GetDlgItem (hDlg, IDOK), NULL, LOWORD(lParam)-DoneLocation.x, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE);
SetWindowPos (GetDlgItem (hDlg, IDC_NEW), NULL, NewLeft, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE);
SetWindowPos (GetDlgItem (hDlg, IDC_SAVE), NULL, SaveLeft, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE);
SetWindowPos (GetDlgItem (hDlg, IDC_REVERT), NULL, RevertLeft, HIWORD(lParam)-DoneLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE);
SetWindowPos (GetDlgItem (hDlg, IDC_TESTEAX), NULL, LOWORD(lParam)-TestLocation.x, HIWORD(lParam)-TestLocation.y, 0, 0, SWP_NOZORDER|SWP_NOOWNERZORDER|SWP_NOSIZE);
}
return 0;
case WM_NCDESTROY:
EAXEditWindow = 0;
//new FS_Switcher;
ForceWindowed = false;
if (fullscreen)
{
setmodeneeded = true;
}
ForcedEnvironment = NULL;
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
case IDCANCEL:
DestroyWindow (hPropList);
DestroyWindow (hDlg);
return 1;
case IDC_NEW:
hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT);
env = (ReverbContainer *)DialogBoxParam (g_hInst,
MAKEINTRESOURCE(IDD_NEWEAX), hDlg, NewEAXProc,
SendMessage (hWnd, CB_GETITEMDATA,
SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0));
if (env != NULL)
{
LRESULT i = AddEnvToDropDown (hWnd,
SendMessage (GetDlgItem (hDlg, IDC_SHOWIDS), BM_GETCHECK, 0, 0)==BST_CHECKED,
env);
SendMessage (hWnd, CB_SETCURSEL, i, 0);
UpdateControls (env, hDlg);
hWnd = GetDlgItem (hPropList, IDCE_ENVIRONMENTSIZE);
SetFocus (hWnd);
SendMessage (hWnd, EM_SETSEL, 0, -1);
}
return 0;
case IDC_REVERT:
hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT);
env = (ReverbContainer *)SendMessage (hWnd, CB_GETITEMDATA,
SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0);
env->Properties = SavedProperties;
UpdateControls (env, hDlg);
return 0;
case IDC_SAVE:
hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT);
SaveEnvironments (hDlg,
(ReverbContainer *)SendMessage (hWnd, CB_GETITEMDATA,
SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0));
return 0;
case IDC_TESTEAX:
if (HIWORD(wParam) == BN_CLICKED)
{
eaxedit_test = (SendMessage ((HWND)lParam, BM_GETCHECK, 0, 0) == BST_CHECKED);
}
break;
case IDC_SHOWIDS:
if (HIWORD(wParam) == BN_CLICKED)
{
hWnd = GetDlgItem (hDlg, IDC_CURRENTENVIRONMENT);
PopulateEnvDropDown (hWnd,
SendMessage ((HWND)lParam, BM_GETCHECK, 0, 0)==BST_CHECKED,
(ReverbContainer *)SendMessage (hWnd, CB_GETITEMDATA,
SendMessage (hWnd, CB_GETCURSEL, 0, 0), 0));
EAXProc (hDlg, WM_COMMAND, MAKELONG(IDC_CURRENTENVIRONMENT,CBN_SELENDOK),
(LPARAM)hWnd);
return 0;
}
break;
case IDC_CURRENTENVIRONMENT:
if (HIWORD(wParam) == CBN_SELENDOK)
{
env = (ReverbContainer *)SendMessage ((HWND)lParam, CB_GETITEMDATA,
SendMessage ((HWND)lParam, CB_GETCURSEL, 0, 0), 0);
UpdateControls (env, hDlg);
}
return 0;
}
return 1;
case WM_GETMINMAXINFO:
((MINMAXINFO *)lParam)->ptMaxTrackSize.x =
((MINMAXINFO *)lParam)->ptMinTrackSize.x = EditWindowSize.x;
((MINMAXINFO *)lParam)->ptMaxTrackSize.y = EditWindowSize.y + PropListMaxSize.y + 5;
GetClientRect (GetDlgItem (hDlg, IDOK), &rect);
((MINMAXINFO *)lParam)->ptMinTrackSize.y = rect.bottom * 10;
return 0;
}
return FALSE;
}
void ShowEAXEditor ()
{
EAXEditWindow = CreateDialog (g_hInst, MAKEINTRESOURCE(IDD_EAXEDIT), Window, EAXProc);
}
CCMD (eaxedit)
{
if (EAXEditWindow != 0)
{
SetForegroundWindow (EAXEditWindow);
}
else
{
ForceWindowed = true;
if (fullscreen)
{
setmodeneeded = true;
SpawnEAXWindow = true;
}
else
{
ShowEAXEditor ();
}
}
}