WindowsXP-SP1/shell/osshell/control/midi/midi.c
2020-09-30 16:53:49 +02:00

1200 lines
47 KiB
C

/*
* MIDI.C
*
* Copyright (C) 1990 Microsoft Corporation.
*
* The MIDI control panel applet.
*
* History:
*
* t-mikemc 10-Apr-90 Created.
*/
/* Revision history:
March 92 Ported to 16/32 common code by Laurie Griffiths (LaurieGr)
*/
/*-=-=-=-=- Include Files -=-=-=-=-*/
#include "preclude.h"
#include <windows.h>
#include <mmsystem.h>
#if defined(WIN32)
#include <port1632.h>
#endif
#include "hack.h"
#include "midimap.h"
#include <cpl.h>
#include "cphelp.h"
#include "cparrow.h"
#include "midi.h"
/*-=- poop -=-*/
#define MM_MAXRESLEN 32 // arbitrary maximum resource string length
/*-=-=-=-=- Prototypes -=-=-=-=-*/
INT_PTR CALLBACK MainBox (HWND, UINT, WPARAM, LPARAM);
BOOL NEAR PASCAL LibMain(HINSTANCE,UINT,LPSTR);
#if defined(WIN16)
#pragma alloc_text(_INIT, LibMain)
#endif //WIN16
LRESULT FAR PASCAL _loadds CPlApplet(HWND,UINT,WPARAM,LPARAM);
#if defined(WIN16)
#pragma alloc_text(_INIT, CPlApplet)
#endif //WIN16
void NEAR PASCAL InitCPL(void);
#if defined(WIN16)
#pragma alloc_text(_INIT, InitCPL)
#endif //WIN16
/*-=-=-=-=- Global Variables -=-=-=-=-*/
/* This many global variables is a sure sign of sickness. LaurieGr */
HINSTANCE hLibInst; // Library instance handle.
HGLOBAL hKeyMap; // Midikeymap handle.
HFONT hFont; // Dialog box font handle.
HWND hWnd, // Current window handle.
hCombo, // Combo box handle.
hEdit, // Edit control handle.
hArrow; // Arrow control handle.
RECT rcBox; // Clipping/scroll rectangle.
int rgxPos[8], // horizontal line positions.
yBox, // rows of data y extent
xClient, // Window client area x pixels.
yClient, // Window client area y pixels.
iCurPos, // Current position on screen.
iVertPos, // Current vertical scroll position.
iVertMax, // Maximum veritcal scroll position.
nLines, // Number of lines of data.
yChar, // Height of character in font.
xChar, // Width of average character in font.
iMap; // Current map type being edited.
char szCurrent[MMAP_MAXNAME], // Current map name.
szCurDesc[MMAP_MAXDESC], // Current map description.
szCurSetup[MMAP_MAXNAME], // Current setup
szNone[16], // Generic global string.
szMidiCtl[64], // Window caption for midicpl.
aszSourceKey[32],
aszSourceKeyName[40],
aszPatchNumber[40],
aszSourcePatch[32],
aszSourcePatchName[40],
aszSourceMnumonic[5],
aszSourceChannel[32],
aszActive[32],
szMidiHlp[24];
BOOL fModified, // Flag; Has the map been modified?
fChanged, // Flag; Has anything ever been changed?
fNew, // Flag; Is this a new map?
fHidden; // Flag; Is the acitve line hidden?
BOOL fReadOnly;
char aszClose[16];
static char aszCaptionFormat[24];
static SZCODE szHelpMessage[] = "ShellHelp";
static SZCODE aszTempPrefix[] = "mmr"; // limited to 3 characters
static SZCODE aszFontName[] = "MS Sans Serif";
static BOOL fAppletEntered; // Disallow multiple applet instances
UINT near uHelpMessage;
DWORD near dwContext;
typedef struct {
int idIcon;
int idName;
int idInfo;
BOOL bEnabled;
DWORD dwContext;
PSTR pszHelp;
} APPLET_INFO;
#define NUM_APPLETS 1
APPLET_INFO near applets[NUM_APPLETS];
/* Move the window, if necessary, to keep it on the desktop, as far as possible */
VOID PlaceWindow(HWND hwnd)
{
RECT rcWind; /* window rectangle */
HDC hdc; /* so we can get device capabilities -i.e. screen size */
int up; /* amount to move window up */
int left; /* amount to move window left */
int HorzRes; /* horizontal screen resolution in pixels */
int VertRes; /* vertical screen resolution in lines */
/* GetWindowRect(HWND_DESKTOP, &rcDesk) doesn't work! */
hdc = GetDC(hwnd);
HorzRes = GetDeviceCaps(hdc,HORZRES);
VertRes = GetDeviceCaps(hdc,VERTRES);
GetWindowRect(hwnd, &rcWind);
up = rcWind.bottom - VertRes; /* how much to move up to get onto screen... */
if (up<0) up = 0; /* don't bother to go down to get to the bottom */
if (up>rcWind.top) up = rcWind.top; /* don't ever go off the top */
left = rcWind.right - HorzRes; /* how much to move left to get all on screen... */
if (left<0) left = 0; /* don't bother to go right */
if (left>rcWind.left) left = rcWind.left; /* but don't ever go off the left */
SetWindowPos( hwnd, HWND_TOP, rcWind.left-left, rcWind.top-up, 0,0,SWP_NOSIZE);
} /* PlaceWindow */
VOID NEAR PASCAL CancelToClose(HWND hDlg)
{
if (!fReadOnly) {
char aszText[16];
GetDlgItemText(hDlg, IDOK, aszText, sizeof(aszText));
if (lstrcmp(aszText, aszClose))
SetDlgItemText(hDlg, IDOK, aszClose);
}
}
// - - - - - - - - -
// Windows entry point.
BOOL NEAR PASCAL LibMain(
HINSTANCE hInstance,
UINT uHeapSize,
LPSTR lpCmdLine)
{
hLibInst = hInstance;
return TRUE;
}
void NEAR PASCAL InitCPL(void)
{
if ( applets[0].idIcon == 0 )
{
LoadString(hLibInst, IDS_CLOSE, aszClose, sizeof(aszClose));
applets[0].idIcon = ID_ICON;
applets[0].idName = IDS_NAME;
applets[0].idInfo = IDS_INFO;
applets[0].bEnabled = TRUE;
applets[0].dwContext = IDH_CHILD_MIDI;
applets[0].pszHelp = szMidiHlp;
LoadString(hLibInst, IDS_NONE, szNone, sizeof(szNone));
LoadString(hLibInst, IDS_HELPFILE, szMidiHlp, sizeof(szMidiHlp));
LoadString(hLibInst, IDS_SOURCEKEY, aszSourceKey, sizeof(aszSourceKey));
LoadString(hLibInst, IDS_SOURCEKEYNAME, aszSourceKeyName, sizeof(aszSourceKeyName));
LoadString(hLibInst, IDS_PATCHNUMBER, aszPatchNumber, sizeof(aszPatchNumber));
LoadString(hLibInst, IDS_SOURCEPATCH, aszSourcePatch, sizeof(aszSourcePatch));
LoadString(hLibInst, IDS_SOURCEPATCHNAME, aszSourcePatchName, sizeof(aszSourcePatchName));
LoadString(hLibInst, IDS_SOURCEMNUMONIC, aszSourceMnumonic, sizeof(aszSourceMnumonic));
LoadString(hLibInst, IDS_SOURCECHANNEL, aszSourceChannel, sizeof(aszSourceChannel));
LoadString(hLibInst, IDS_ACTIVETITLE, aszActive, sizeof(aszActive));
}
}
#ifdef STUPID
/*
* ComboBox String Lookup, written because we
* let an intern design this applet.
*/
int FAR PASCAL ComboLookup(
HWND hCombo,
LPSTR szLookup)
{
int iEntries;
static char szBuf[29];
PSTR pstrBuf;
iEntries = (int)(LONG)SendMessage(hCombo,CB_GETCOUNT,(WPARAM)0,(LPARAM)0);
if (iEntries > CB_ERR)
{
do
{
iEntries--;
pstrBuf = szBuf;
if ((int)(LONG)SendMessage(hCombo,CB_GETLBTEXT,(WPARAM)iEntries,(LPARAM)(LPSTR)szBuf) == CB_ERR)
return CB_ERR;
if (lstrcmpi(szLookup,pstrBuf) == 0)
return iEntries;
}
while(iEntries);
}
return CB_ERR;
}
#endif
// Given an error code, display an error message. If the error code
// was invalid, displays a default bogus English-language text string.
VOID FAR PASCAL VShowError(
HWND hwnd, // Window to tie the message box to.
MMAPERR mmaperr) // Error code to display text for.
{
char asz[256];
LoadString(hLibInst, IDS_MMAPERR_BASE + mmaperr, asz, sizeof(asz));
MessageBox(hwnd, asz, NULL, MB_ICONEXCLAMATION | MB_OK);
}
// - - - - - - - - -
// Returns TRUE if the file exists and is correct, or was initialized
// properly. Returns FALSE if the user didn't want it initialized, or
// if the initialization failed.
//
// This function deals with English-language specific stuff. There is
// no good reason for this that I can see.
static BOOL FAR PASCAL FGetMapFile(
HWND hwnd)
{
char aszBuf[256];
DWORD dwVersion;
MMAPERR mmaperr;
//
// An error return from "mapFileVersion" indicates a problem that
// I don't want to go into too specifically at this time. The
// most likely event is that the file doesn't exist. The code in
// in this function assumes that this is what happened. If it
// was another problem, hopefully initializing the file will
// solve it. This can be looked into later.
//
dwVersion = mapFileVersion();
if ((HIWORD(dwVersion) == MMAPERR_SUCCESS) &&
(LOWORD(dwVersion) == 1))
return TRUE; // File was fine (opened + was right version).
//
// This code is executing if there was a problem opening the
// file. Hopefully this problem involved non-existence.
//
LoadString(hLibInst, IDS_CREATE_QUESTION, aszBuf, sizeof(aszBuf));
if (MessageBox(hwnd, aszBuf, szMidiCtl,
MB_YESNO | MB_ICONHAND) == IDYES)
if ((mmaperr = mapInitMapFile()) == MMAPERR_SUCCESS)
return TRUE;
else
VShowError(hwnd, mmaperr);
return FALSE;
}
// - - - - - - - - -
// Control panel entry point.
LRESULT FAR PASCAL _loadds CPlApplet(
HWND hCPlWnd,
UINT uMessage,
WPARAM lParam1,
LPARAM lParam2)
{
LPNEWCPLINFO lpCPlInfo;
BOOL fSuccess = TRUE;
BOOL fBackup;
LPSTR lpstrBakPath;
LPSTR lpstrCfgPath;
int iApplet;
switch (uMessage) {
case CPL_INIT :
InitCPL();
uHelpMessage = RegisterWindowMessage(szHelpMessage);
hWnd = hCPlWnd;
return (LRESULT)TRUE;
case CPL_GETCOUNT :
return (LRESULT)NUM_APPLETS;
case CPL_NEWINQUIRE :
lpCPlInfo = (LPNEWCPLINFO)lParam2;
iApplet = (int)(LONG)lParam1;
lpCPlInfo->hIcon = LoadIcon(hLibInst,
MAKEINTRESOURCE(applets[iApplet].idIcon));
LoadString(hLibInst, applets[iApplet].idName, lpCPlInfo->szName, sizeof(lpCPlInfo->szName));
LoadString(hLibInst, applets[iApplet].idInfo, lpCPlInfo->szInfo, sizeof(lpCPlInfo->szInfo));
lpCPlInfo->dwSize = sizeof(NEWCPLINFO);
lpCPlInfo->lData = (LONG)iApplet;
lpCPlInfo->dwHelpContext = applets[iApplet].dwContext;
lstrcpy(lpCPlInfo->szHelpFile, applets[iApplet].pszHelp);
return (LRESULT)TRUE;
case CPL_DBLCLK :
if (fAppletEntered)
break;
//
// We can enter into lots of bizarre states:
// We become READ-ONLY IF:
// We cannot lock the mapper.
// There is a disk or memory exception backing up the
// existing MIDIMAP.CFG file or the MIDIMAP.CFG
// is READ ONLY.
// We DO NOT use a backup IF:
// The mapper is locked.
// No MIDIMAP.CFG file is found.
// There is an exception dealing with backing up the
// the existing MIDIMAP.CFG file.
//
lpstrCfgPath = GlobalLock(GlobalAlloc(GHND,MAXPATHLEN));
if (lpstrCfgPath == NULL)
{
VShowError(hCPlWnd,IDS_MMAPERR_MEMORY);
break;
}
lpstrBakPath = GlobalLock(GlobalAlloc(GHND,MAXPATHLEN));
if (lpstrBakPath == NULL)
{
VShowError(hCPlWnd,IDS_MMAPERR_MEMORY);
goto exitfree;
}
fAppletEntered = TRUE;
if (!mapLock()) // Attempt to lock the mapper
{
char szApp[32],
szMessage[256];
LoadString(hLibInst, IDS_READONLYMODE, szMessage, sizeof(szMessage));
LoadString(hLibInst, IDS_TITLE, szApp, sizeof(szApp));
MessageBox(hCPlWnd, szMessage, szApp,
MB_ICONINFORMATION | MB_OK);
fBackup = FALSE; // No backups
fReadOnly = TRUE; // Read Only Mode
}
else
{
fBackup = TRUE; // Try to do a backup
fReadOnly = FALSE; // Not in READ ONLY mode
}
if (fBackup)
{
char szMapCfg[MMAP_MAXCFGNAME];
LoadString(hLibInst,IDS_MIDIMAPCFG,szMapCfg,MMAP_MAXCFGNAME);
GetSystemDirectory(lpstrCfgPath,MAXPATHLEN - sizeof(szMapCfg));
lstrcat(lpstrCfgPath,szMapCfg);
MGetTempFileName(0, aszTempPrefix,0,lpstrBakPath);
if (DupMapCfg(lpstrCfgPath,lpstrBakPath)) {
mapConnect(lpstrBakPath);
}
else
{
// No Backups.
fBackup = FALSE;
// if fReadOnly == TRUE, the exception
// has forced us into READ-ONLY mode
// else
// we didn't have a MIDIMAP.CFG file
// and we'll read/write directly.
if (fReadOnly)
mapUnlock();
DosDelete(lpstrBakPath); // GetTempFileName Creates a File of size 0
}
}
if (!FGetMapFile(hCPlWnd))
{
fSuccess = FALSE;
goto appexit;
}
// !!! Never unregisters the class, so this will come back
// FALSE on subsequent startups. This is of course bogus.
(VOID)RegisterArrowClass(hLibInst);
#if 0
if ((hFont = CreateFont(8, NULL, NULL, NULL,
FW_NORMAL, NULL, NULL, NULL,
ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
VARIABLE_PITCH | FF_DONTCARE, aszFontName)) == NULL)
goto appexit;
#else
{
LOGFONT lf;
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lf), (LPVOID)&lf, 0);
if (!(hFont = CreateFontIndirect(&lf)))
goto appexit;
}
#endif
fSuccess = (BOOL)DialogBox(hLibInst, MAKEINTRESOURCE(ID_MAINBOX),
hCPlWnd, MainBox);
UnregisterArrowClass(hLibInst);
DeleteObject(hFont);
appexit:
if (fBackup)
{
MDOUT("Disconnecting from mapper");
mapDisconnect();
if (fSuccess)
{
MDOUT("Updating Backup");
UpdateMapCfg(lpstrCfgPath,lpstrBakPath);
}
mapUnlock();
DosDelete(lpstrBakPath);
}
else
if (!fReadOnly)
{
mapUnlock();
if (!fSuccess)
DosDelete(lpstrCfgPath);
}
fAppletEntered = FALSE;
GlobalFree((HGLOBAL)lpstrBakPath);
exitfree: GlobalFree((HGLOBAL)lpstrCfgPath);
break;
}
return (LRESULT)0;
}
// - - - - - - - - -
// This will return either "MMAPERR_SUCCESS" if everything is fine,
// or will return "MMAPERR_INVALIDPORT" if the setup references a
// bogus port. These are both expected conditions.
//
// Unexpected conditions can also happen, which are returned.
static MMAPERR NEAR PASCAL MmaperrInvalidPortCheck(
LPSTR lszName) // Name of current setup.
{
LPMIDIMAP lpMap;
MMAPERR mmaperr;
DWORD dwSize;
HGLOBAL hMidiMap;
if ((dwSize = mapGetSize(MMAP_SETUP, lszName)) < MMAPERR_MAXERROR)
return (MMAPERR)dwSize;
if ((hMidiMap = GlobalAlloc(GHND, dwSize)) == NULL)
return MMAPERR_MEMORY;
lpMap = (LPMIDIMAP)GlobalLock(hMidiMap);
mmaperr = mapRead(MMAP_SETUP, lszName, (LPVOID)lpMap);
GlobalUnlock(hMidiMap);
GlobalFree(hMidiMap);
return mmaperr;
}
// - - - - - - - - -
// Converts a "MMAP_" into a "IDS_", i.e. converts "MMAP_SETUP" into
// "IDS_SETUP", which can be used to get the word "Setup" out of the
// "midi.rc" file.
static int PASCAL IdsGetMapNameId( int iMap)
{
if (iMap == MMAP_SETUP)
return IDS_SETUP;
if (iMap == MMAP_PATCH)
return IDS_PATCH;
return IDS_KEY;
}
// - - - - - - - - -
/*
* DELETEMAP
*
* This function returns TRUE if it is OK to delete whatever map
* exists in szCurrent.
*/
static BOOL NEAR PASCAL FConfirmDeleteMap(
HWND hwnd)
{
char szSetup[MMAP_MAXNAME],
szSrc[MM_MAXRESLEN],
szUsedBy[MM_MAXRESLEN],
szDel[50],
szCap[50],
szRsrc[256],
szBuf[256];
DWORD dwRet;
UINT uSrcID;
UINT uUsage;
MMAPERR mmaperr;
uSrcID = IdsGetMapNameId(iMap);
LoadString(hLibInst, uSrcID, szSrc, sizeof(szSrc));
LoadString(hLibInst, IDS_DELETE, szDel, sizeof(szDel));
wsprintf(szCap, szDel, (LPSTR)szSrc);
// AnsiUpperBuff(szSrc, 1); // Upper-case first character.
switch (iMap) {
case MMAP_SETUP:
if ((mmaperr = mapGetCurrentSetup(szSetup,
MMAP_MAXNAME)) != MMAPERR_SUCCESS) {
VShowError(hwnd, mmaperr);
return FALSE;
}
if (lstrcmpi(szSetup, szCurrent))
break;
LoadString(hLibInst, IDS_NODELISCURRENT, szRsrc, sizeof(szRsrc));
wsprintf(szBuf, szRsrc, (LPSTR)szCurrent);
MessageBox(hwnd, szBuf, szCap,
MB_ICONINFORMATION | MB_OK);
return FALSE;
case MMAP_PATCH:
case MMAP_KEY:
dwRet = mapGetUsageCount(iMap, szCurrent);
if (LOWORD(dwRet) != MMAPERR_SUCCESS) {
VShowError(hwnd, LOWORD(dwRet));
return FALSE;
}
if (!(uUsage = HIWORD(dwRet)))
break;
uSrcID--; // Patch->Setup, Key->Patch
if (uUsage > 1) // Make a singular a plural. This
uSrcID += 3; // "3" is commented in "midi.h".
LoadString(hLibInst, uSrcID, szUsedBy, sizeof(szUsedBy));
// AnsiLowerBuff(szUsedBy, 1); // Lower-case first character.
LoadString(hLibInst, IDS_NODELISREFERENCED, szRsrc, sizeof(szRsrc));
wsprintf(szBuf, szRsrc, (LPSTR)szSrc, (LPSTR)szCurrent,
uUsage, (LPSTR)szUsedBy);
MessageBox (hwnd, szBuf, szCap,
MB_ICONINFORMATION | MB_OK);
return FALSE;
}
LoadString(hLibInst, IDS_VERIFYDELETE, szRsrc, sizeof(szRsrc));
wsprintf(szBuf, szRsrc, (LPSTR)szSrc, (LPSTR)szCurrent);
return (IDYES == MessageBox (hwnd, szBuf, szCap,
MB_ICONEXCLAMATION | MB_YESNO));
}
static VOID NEAR PASCAL VFreeItemData(
HWND hdlg,
int idCtrl)
{
UINT uCount;
uCount = (UINT)SendDlgItemMessage(hdlg, idCtrl, CB_GETCOUNT, (WPARAM)NULL, (LPARAM)0);
for (; uCount--; ) {
HGLOBAL hDescription;
if ((hDescription = (HGLOBAL)(DWORD)SendDlgItemMessage(hdlg, idCtrl,
CB_GETITEMDATA, (WPARAM)uCount, (LPARAM)0)) != NULL)
GlobalFree(hDescription);
}
}
static VOID NEAR PASCAL GetMBData(
UINT uFlag,
LPMBDATA lpmbData)
{
switch (uFlag) {
case MMAP_SETUP:
lpmbData->lpfnBox = SetupBox;
lpmbData->idBox = DLG_SETUPEDIT;
break;
case MMAP_PATCH:
lpmbData->lpfnBox = PatchBox;
lpmbData->idBox = DLG_PATCHEDIT;
break;
case MMAP_KEY:
lpmbData->lpfnBox = KeyBox;
lpmbData->idBox = DLG_KEYEDIT;
break;
default:
lpmbData->lpfnBox = 0L;
lpmbData->idBox = 0;
break;
}
} /* GetMBData */
static BOOL PASCAL FEditMap(
HWND hwnd)
{
HWND hTmpWnd;
MBDATA mbData;
DWORD dwRet;
int iRet;
BOOL fInSetup;
char szSetup[MMAP_MAXNAME];
MMAPERR mmaperr;
if ((mmaperr = mapGetCurrentSetup(szSetup,
MMAP_MAXNAME)) != MMAPERR_SUCCESS) {
VShowError(hwnd, mmaperr);
return FALSE;
}
switch (iMap) {
case MMAP_SETUP :
fInSetup = (BOOL)!lstrcmpi(szCurrent, szSetup);
break;
case MMAP_PATCH :
dwRet = mapPatchMapInSetup(szCurrent, szSetup);
if (LOWORD(dwRet) != MMAPERR_SUCCESS)
return FALSE;
fInSetup = (BOOL)HIWORD(dwRet);
break;
case MMAP_KEY :
dwRet = mapKeyMapInSetup (szCurrent, szSetup);
if (LOWORD(dwRet) != MMAPERR_SUCCESS)
return FALSE;
fInSetup = (BOOL)HIWORD(dwRet);
break;
}
hTmpWnd = hWnd; // "hWnd", not "hwnd".
GetMBData(iMap, &mbData);
iRet = (int)DialogBox(hLibInst, MAKEINTRESOURCE(mbData.idBox),
hWnd, mbData.lpfnBox);
hWnd = hTmpWnd;
return iRet;
} /* FEditMap */
static VOID NEAR PASCAL EnableMain(
BOOL fEnable)
{
char aszNoEntries[48];
EnableWindow(hCombo, fEnable);
if (fReadOnly)
{
EnableWindow(GetDlgItem (hWnd, ID_MAINDELETE), FALSE);
EnableWindow(GetDlgItem (hWnd,ID_MAINNEW),FALSE);
}
else
EnableWindow(GetDlgItem (hWnd, ID_MAINDELETE), fEnable);
EnableWindow(GetDlgItem (hWnd, ID_MAINEDIT), fEnable);
EnableWindow(GetDlgItem (hWnd, ID_MAINDESC), fEnable);
EnableWindow(GetDlgItem (hWnd, ID_MAINNAME), fEnable);
if (!fEnable) {
LoadString(hLibInst, IDS_NOENTRIES, aszNoEntries, sizeof(aszNoEntries));
SetDlgItemText(hWnd, ID_MAINDESC, aszNoEntries);
}
} /* EnableMain */
static VOID NEAR PASCAL ShowMaps (int nMap)
{
if (iMap == nMap)
return;
iMap = nMap;
SendMessage(hWnd, WM_MY_INITDIALOG, (WPARAM)NULL, (LPARAM)0);
} /* ShowMaps */
INT_PTR CALLBACK MainBox(
HWND hdlg,
UINT uMessage,
WPARAM wParam,
LPARAM lParam)
{
static BOOL fChange, // has edittext changed?
fPatchEnum, // have patches been enum'd?
fKeyEnum, // have keys been enum'd?
fEnabled;
static UINT uDeleted; // which maps types deleted
static char aszInitialSetup[MMAP_MAXNAME]; // initial setup name
MMAPERR mmaperr;
HGLOBAL hDesc;
LPSTR lpDesc;
UINT uIdx;
int idCurCombo;
BOOL fEnum;
// char szBuf[128];
char szTmpDesc[MMAP_MAXDESC];
switch (uMessage) {
case WM_INITDIALOG:
// get the current setup name and store in
// static aszInitialSetup
fChanged = FALSE;
if ((mmaperr = mapGetCurrentSetup(aszInitialSetup,
MMAP_MAXNAME)) != MMAPERR_SUCCESS) {
exit00: VShowError(hdlg, mmaperr);
/*exit01:*/ EndDialog (hdlg, FALSE);
return TRUE;
}
lstrcpy(szCurSetup, aszInitialSetup);
// Load caption string and set the window text
LoadString(hLibInst, IDS_TITLE, szMidiCtl, sizeof(szMidiCtl));
hWnd = hdlg;
SetWindowText(hdlg, szMidiCtl);
/*!!
// check for invalid devices
if ((mmaperr = MmaperrInvalidPortCheck(
aszInitialSetup)) == MMAPERR_INVALIDPORT) {
if (!InvalidPortMsgBox(hdlg))
goto exit01;
}
else if (mmaperr != MMAPERR_SUCCESS)
goto exit00;
!!*/
// hide the patch and key comboboxes
ShowWindow(GetDlgItem(hdlg, ID_MAINPATCHCOMBO), SW_HIDE);
ShowWindow(GetDlgItem(hdlg, ID_MAINKEYCOMBO), SW_HIDE);
// enumerate setups into setup combo box
mmaperr = mapEnumerate( MMAP_SETUP
, EnumFunc
, MMENUM_INTOCOMBO
, GetDlgItem( hdlg, ID_MAINSETUPCOMBO)
, NULL
);
if ( mmaperr != MMAPERR_SUCCESS )
goto exit00;
// set up the auto-radiobuttons
CheckRadioButton(hdlg, ID_MAINFIRSTRADIO,
ID_MAINLASTRADIO, ID_MAINSETUP);
// intialize some variables
*szCurrent = 0;
hCombo = NULL;
iMap = MMAP_SETUP;
fEnabled = FALSE; // Fix for bug #2039. 13-Feb-90, BLM.
// It used to set the variable TRUE.
fChange = FALSE;
fPatchEnum = FALSE;
fKeyEnum = FALSE;
uDeleted = 0;
// fall through
case WM_MY_INITDIALOG:
fEnum = FALSE;
switch (iMap) {
case MMAP_SETUP:
idCurCombo = ID_MAINSETUPCOMBO;
uIdx = ComboLookup(GetDlgItem(hdlg,idCurCombo),(LPSTR)szCurSetup);//-jyg
break;
case MMAP_PATCH:
idCurCombo = ID_MAINPATCHCOMBO;
if (!fPatchEnum) {
fEnum = TRUE;
fPatchEnum = TRUE;
}
uIdx = 0;
break;
case MMAP_KEY:
idCurCombo = ID_MAINKEYCOMBO;
if (!fKeyEnum) {
fEnum = TRUE;
fKeyEnum = TRUE;
}
uIdx = 0;
break;
default:uIdx = 0;
idCurCombo = 0; /* kill compiler warning about use before set */
}
// hide the old combobox, if any
if (hCombo != NULL)
ShowWindow (hCombo, SW_HIDE);
// get the new combobox handle
hCombo = GetDlgItem (hdlg, idCurCombo);
// show the new combobox
ShowWindow(hCombo, SW_SHOW);
// if not done already, enumerate maps into the box
if (fEnum)
{ mmaperr = mapEnumerate(iMap, EnumFunc, MMENUM_INTOCOMBO, hCombo, NULL);
if (mmaperr != MMAPERR_SUCCESS)
goto exit00;
}
// set the current selection
uIdx = (UINT)SendMessage(hCombo, CB_SETCURSEL, (WPARAM)uIdx, (LPARAM)0);
// if no maps of that type, disable all necessary controls
if (uIdx == CB_ERR) {
*szCurrent = 0;
EnableMain(fEnabled = FALSE);
break;
}
// if we were disabled, enable us
if (!fEnabled)
EnableMain(fEnabled = TRUE);
// fill the edit control with description
#if defined(WIN16)
SendMessage(hdlg, WM_COMMAND, (WPARAM)ID_MAINCOMBO,
MAKELPARAM(hCombo, CBN_SELCHANGE));
#else
SendMessage( hdlg
, WM_COMMAND
, (WPARAM)MAKELONG(ID_MAINCOMBO, CBN_SELCHANGE)
, (LPARAM)hCombo
);
#endif // WIN16
break;
case WM_COMMAND:
{ WORD wNotifCode;
#if defined(WIN16)
wNotifCode = HIWORD(lParam);
#else
wNotifCode = HIWORD(wParam);
#endif //WIN16
switch (LOWORD(wParam)) {
case IDH_CHILD_MIDI:
goto DoHelp;
case IDOK:
if (fReadOnly || !fChanged)
{
PostMessage(hdlg,WM_COMMAND,(WPARAM)IDCANCEL,(LPARAM)0);
break;
}
// check for invalid ports
if ((mmaperr = MmaperrInvalidPortCheck(
szCurSetup)) == MMAPERR_INVALIDPORT) {
if (!InvalidPortMsgBox(hdlg))
break;
} else if (mmaperr != MMAPERR_SUCCESS)
goto exit00;
if (lstrcmpi(szCurSetup, aszInitialSetup))
{
mmaperr = mapSetCurrentSetup(
szCurSetup);
if (mmaperr !=
MMAPERR_SUCCESS)
goto exit00;
}
// this is where any deleted maps actually get the axe
//
// I'm going to leave this as is until I figure
// out how to deal with any errors that happen.
// brucemo
//
#if 0
if (uDeleted & MMAP_SETUP)
mapEnumerate( iMap = MMAP_SETUP
, EnumFunc
, MMENUM_DELETE
, GetDlgItem(hdlg,ID_MAINSETUPCOMBO)
, NULL
);
if (uDeleted & MMAP_PATCH)
mapEnumerate( iMap = MMAP_PATCH
, EnumFunc
, MMENUM_DELETE
, GetDlgItem(hdlg,ID_MAINPATCHCOMBO)
, NULL
);
if (uDeleted & MMAP_KEY)
mapEnumerate( iMap = MMAP_KEY
, EnumFunc,
, MMENUM_DELETE
, GetDlgItem (hdlg,ID_MAINKEYCOMBO)
, NULL
);
#endif
case IDCANCEL:
// clean up and go home
VFreeItemData(hdlg, ID_MAINSETUPCOMBO);
if (fPatchEnum)
VFreeItemData(hdlg, ID_MAINPATCHCOMBO);
if (fKeyEnum)
VFreeItemData(hdlg, ID_MAINKEYCOMBO);
if (LOWORD(wParam) == IDOK) // eh?
EndDialog(hdlg,TRUE);
else
EndDialog(hdlg,FALSE);
break;
case ID_MAINDELETE:
if (!FConfirmDeleteMap(hdlg))
break;
CancelToClose(hdlg);
// set a bit in the deleted word
uDeleted |= iMap;
// get the current selections index
uIdx = (UINT)SendMessage(hCombo,
CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
// get the handle to selections description
if ((hDesc = (HGLOBAL)(DWORD)SendMessage(hCombo,
CB_GETITEMDATA, (WPARAM)uIdx, (LPARAM)0)) != NULL)
GlobalFree(hDesc);
// delete the entry from the combobox
SendMessage(hCombo, CB_DELETESTRING, (WPARAM)uIdx, (LPARAM)0);
// -jyg-
mapEnumerate(iMap, EnumFunc, MMENUM_DELETE, hCombo, NULL);
// reset to initial setup or first entry
if (iMap == MMAP_SETUP)
{
uIdx = ComboLookup(hCombo,(LPSTR)aszInitialSetup); //-jyg
lstrcpy(szCurSetup,aszInitialSetup); // reset current string to initial setup
}
else
uIdx = 0;
uIdx = (UINT)SendMessage(hCombo, CB_SETCURSEL, (WPARAM)uIdx, (LPARAM)0);
// if deleted last one then disable window,
// otherwise update the edit control
if (uIdx == CB_ERR) {
EnableMain(fEnabled = FALSE);
SendMessage(hdlg, DM_SETDEFID, (WPARAM)ID_MAINNEW, (LPARAM)0);
SetFocus(GetDlgItem(hdlg, ID_MAINNEW));
} else
#if defined(WIN16)
SendMessage(hdlg, WM_COMMAND,
(WPARAM)ID_MAINCOMBO, MAKELPARAM(hCombo,
CBN_SELCHANGE));
#else
SendMessage( hdlg
, WM_COMMAND
, (WPARAM)MAKELONG(ID_MAINCOMBO, CBN_SELCHANGE)
, (LPARAM)hCombo
);
#endif //WIN16
break;
case ID_MAINNEW:
// if they don't specify a new map get outta here
fNew = TRUE;
if (!DialogBox(hLibInst, MAKEINTRESOURCE(ID_PROPBOX),
hdlg, (DLGPROC)PropBox)) {
fNew = FALSE;
break;
}
// if they don't want to save new map, restore
// name and description and get outta here
if (!FEditMap(hdlg)) {
fNew = FALSE;
GetWindowText(hCombo, (LPSTR)szCurrent,
MMAP_MAXNAME);
GetDlgItemText(hdlg, ID_MAINDESC, szCurDesc,
MMAP_MAXDESC);
break;
}
uIdx = ComboLookup(hCombo,(LPSTR)szCurrent);//-jyg
if (uIdx != CB_ERR) {
char aszName[MMAP_MAXNAME];
SendMessage(hCombo, CB_GETLBTEXT, (WPARAM)uIdx, (LPARAM)(LPSTR)aszName);
if (!lstrcmpi(aszName, szCurrent)) {
hDesc = (HGLOBAL)(DWORD)SendMessage(hCombo, CB_GETITEMDATA, (WPARAM)uIdx, (LPARAM)0);
if (hDesc != NULL)
GlobalFree(hDesc);
//break;
} else
uIdx = (UINT)CB_ERR;
}
if (uIdx == CB_ERR)
uIdx = (UINT)SendMessage(hCombo, CB_ADDSTRING,
(WPARAM)0, (LPARAM)(LPCSTR)szCurrent);
// make the new map the current one
SendMessage(hCombo, CB_SETCURSEL, (WPARAM)uIdx, (LPARAM)0);
if (IsDlgButtonChecked(hdlg, ID_MAINSETUP))
lstrcpy(szCurSetup, szCurrent);
// allocate buffer for map description data
if ((hDesc = GlobalAlloc(GHND, (DWORD)(sizeof(char) *
(lstrlen (szCurDesc) + 1)))) != NULL) {
lpDesc = (LPSTR)GlobalLock(hDesc);
lstrcpy(lpDesc, szCurDesc);
GlobalUnlock(hDesc);
}
SetDlgItemText (hdlg, ID_MAINDESC, szCurDesc);
// put the handle in the entrys item data
SendMessage(hCombo, CB_SETITEMDATA,
(WPARAM)uIdx, (LPARAM)hDesc);
// enable windows if it is the first map of type
if (!IsWindowEnabled(hCombo))
EnableMain(TRUE);
CancelToClose(hdlg);
break;
case ID_MAINEDIT:
if (!FEditMap(hdlg))
break;
CancelToClose(hdlg);
if (iMap != MMAP_SETUP)
break;
// reset to current setup
uIdx = ComboLookup(hCombo,(LPSTR)szCurSetup); //-jyg
SendMessage(hCombo, CB_SETCURSEL, (WPARAM)uIdx, (LPARAM)0);
#if defined(WIN16)
SendMessage(hdlg, WM_COMMAND, (WPARAM)ID_MAINCOMBO,
MAKELPARAM(hCombo, CBN_SELCHANGE));
#else
SendMessage( hdlg
, WM_COMMAND
, (WPARAM)MAKELONG(ID_MAINCOMBO, CBN_SELCHANGE)
, (LPARAM)hCombo
);
#endif //WIN16
break;
case ID_MAINSETUP:
ShowMaps(MMAP_SETUP);
break;
case ID_MAINPATCH:
ShowMaps(MMAP_PATCH);
break;
case ID_MAINKEY:
ShowMaps(MMAP_KEY);
break;
case ID_MAINSETUPCOMBO:
case ID_MAINPATCHCOMBO:
case ID_MAINKEYCOMBO:
case ID_MAINCOMBO:
if (wNotifCode == CBN_SELENDOK) {
CancelToClose(hdlg);
fChanged = TRUE;
}
if (wNotifCode != CBN_SELCHANGE)
return FALSE;
uIdx = (UINT)SendMessage(hCombo, CB_GETCURSEL,
(WPARAM)0, (LPARAM)0);
if (LOWORD(wParam) == ID_MAINSETUPCOMBO)
SendMessage(hCombo, CB_GETLBTEXT, (WPARAM)uIdx,
(LPARAM) (LPSTR) szCurSetup);
hDesc = (HGLOBAL)(DWORD)SendMessage(hCombo, CB_GETITEMDATA,
(WPARAM)uIdx, (LPARAM)0);
lpDesc = GlobalLock(hDesc);
lstrcpy(szCurDesc, lpDesc);
GlobalUnlock(hDesc);
SetDlgItemText (hdlg, ID_MAINDESC, szCurDesc);
SendMessage(hCombo, CB_GETLBTEXT, (WPARAM)uIdx,
(LPARAM)(LPSTR)szCurrent);
break;
case ID_MAINDESC:
// NOTE: this is not implemented.
if (wNotifCode == EN_CHANGE)
fChange = TRUE;
else if ((wNotifCode == EN_KILLFOCUS) && fChange) {
GetDlgItemText (hdlg, ID_MAINDESC, szTmpDesc,
MMAP_MAXDESC);
if (!lstrcmpi(szCurDesc, szTmpDesc)) {
// description change logic here.
// There's no API to changedesc!!
}
}
break;
default:
return FALSE;
}
} /* end of WM_COMMAND */
break;
default:
if (uMessage == uHelpMessage) {
DoHelp:
WinHelp(hWnd, szMidiHlp, HELP_CONTEXT,
IDH_CHILD_MIDI);
return TRUE;
}
else
return FALSE;
break;
}
return TRUE;
} /* MainBox */
BOOL FAR PASCAL InvalidPortMsgBox (
HWND hwnd)
{
int iRet;
char szBuf[256];
LoadString(hLibInst, IDS_INVALIDPORT, szBuf, sizeof(szBuf));
iRet = MessageBox (hwnd, szBuf, szMidiCtl,
MB_ICONSTOP | MB_YESNO);
return iRet == IDYES;
} /* InvalidPortMsgBox */
VOID FAR PASCAL Modify(
BOOL fSet)
{
fModified = fSet;
if (fModified)
fChanged = TRUE;
} /* Modify */
/*
* ENUMFUNC
*
* Enumerate setup, patchmap or keymap names.
*/
BOOL FAR PASCAL _loadds EnumFunc(
LPSTR lpName,
LPSTR lpDesc,
UINT uCase,
HWND hCombo,
LPSTR unused
)
{
HGLOBAL hMem;
LPSTR lpStr;
UINT uIdx;
MMAPERR mmaperr;
// see if we're dealing with 'delete' enumeration.
if (uCase == MMENUM_DELETE) {
uIdx = ComboLookup(hCombo, (LPSTR)lpName);//-jyg
if (uIdx != CB_ERR)
return TRUE;
mmaperr = mapDelete(iMap, lpName);
if (mmaperr == MMAPERR_SUCCESS)
return TRUE;
VShowError(hWnd, mmaperr);
return FALSE;
}
uIdx = (UINT)SendMessage(hCombo, CB_ADDSTRING, (WPARAM)NULL, (LPARAM)lpName);
// see if we're dealing with enumeration from the main dialog
if (uCase == MMENUM_INTOCOMBO) {
hMem = GlobalAlloc(GHND, (DWORD)(lstrlen(lpDesc) + 1));
if (hMem != NULL) {
lpStr = (LPSTR)GlobalLock(hMem);
lstrcpy(lpStr, lpDesc);
GlobalUnlock(hMem);
}
SendMessage( hCombo,
CB_SETITEMDATA, (WPARAM)uIdx, (LPARAM)hMem);
}
return TRUE;
} /* EnumFunc */
#if 0
/*
* SETWINDOWCAPTION
*
* Set the caption of a 'window', such as 'MIDI Setup: "foo"', even though
* these are actually dialog boxes.
*/
VOID FAR PASCAL SetWindowCaption(
VOID)
{
char szCaption[80],
szName[MM_MAXRESLEN];
LoadString(hLibInst, IdsGetMapNameId(iMap), szName, sizeof(szName));
wsprintf(szCaption, aszCaptionFormat,
(LPSTR)szName, (LPSTR)szCurrent);
SetWindowText(hWnd, szCaption);
} /* SetWindowCaption */
#endif //0
int FAR PASCAL QuerySave (VOID)
{
char szBuf[256];
char aszSave[64];
char aszFormat[128];
char szFunc[MM_MAXRESLEN];
LoadString(hLibInst, IdsGetMapNameId(iMap), szFunc, sizeof(szFunc));
if (fNew) {
// AnsiUpperBuff(szFunc, 1); // Upper-case first character.
LoadString(hLibInst, IDS_NEW_QUESTION, aszFormat, sizeof(aszFormat));
wsprintf (szBuf, aszFormat, (LPSTR)szCurrent, (LPSTR)szFunc);
}
else {
LoadString(hLibInst, IDS_CHANGE_QUESTION, aszFormat, sizeof(aszFormat));
wsprintf (szBuf, aszFormat, (LPSTR)szFunc, (LPSTR)szCurrent);
}
LoadString(hLibInst, IDS_SAVE_CHANGES, aszSave, sizeof(aszSave));
return MessageBox(hWnd, szBuf, aszSave, MB_YESNOCANCEL | MB_ICONEXCLAMATION);
} /* QuerySave */