1151 lines
38 KiB
C
1151 lines
38 KiB
C
/*
|
|
* PATCH.C
|
|
*
|
|
* Copyright (C) 1990 Microsoft Corporation.
|
|
*
|
|
* Edit patchmaps dialog box and support functions.
|
|
*/
|
|
|
|
/* 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>
|
|
#include <port1632.h>
|
|
#include <string.h>
|
|
#include "hack.h"
|
|
#include "midimap.h"
|
|
#include "cphelp.h"
|
|
#include "midi.h"
|
|
#include "extern.h"
|
|
|
|
#if defined(WIN32)
|
|
#define _based(x)
|
|
#endif //WIN32
|
|
|
|
/*-=-=-=-=- Prototypes -=-=-=-=-*/
|
|
|
|
static SZCODE aszPatchNumFormat[] = "%3d";
|
|
static MMAPERR PASCAL MmaperrPatchInit(HWND);
|
|
static MMAPERR PASCAL MmaperrPatchInitNew(VOID);
|
|
static VOID PASCAL PatchEnumKeys(HWND);
|
|
static VOID PASCAL PatchSize(HWND, BOOL);
|
|
static VOID PASCAL PatchPaint(VOID);
|
|
static VOID PASCAL PatchArrowScroll(WPARAM, LPARAM);
|
|
static VOID PASCAL PatchWindowScroll(HWND, UINT, int);
|
|
static VOID PASCAL PatchEditMsg(UINT id , WORD NotifCode);
|
|
static VOID PASCAL PatchComboMsg(HWND hDlg, WORD NotifCode);
|
|
static VOID PASCAL PatchButtonDown(HWND, LONG);
|
|
static VOID PASCAL PatchSetFocus(HWND, UINT, int);
|
|
static VOID PASCAL PatchActiveLine(UINT, UINT);
|
|
static int PASCAL PatchSave(HWND, BOOL);
|
|
|
|
/*-=-=-=-=- Global Definitions -=-=-=-=-*/
|
|
|
|
#define PAL_SHOW 0 // show active line
|
|
#define PAL_HIDE 1 // hide active line
|
|
|
|
#define PSF_REDRAW 0x0001 // redraw where line used to be
|
|
#define PSF_SHOWIFHIDDEN 0x0002 // show line if hidden
|
|
|
|
#define DEF_PATCH_ROWS 16 // number of default patch rows
|
|
|
|
/*-=-=-=-=- Global Variables -=-=-=-=-*/
|
|
|
|
static HWND hCombo, // keymap combo-box control handle
|
|
hScroll, // scroll bar control handle
|
|
hVolEdit, // volume edit control handle
|
|
hVolArrow; // volume arrow control handle
|
|
static HGLOBAL hPatchMap;
|
|
static int nKeys, // number of key maps in mapfile
|
|
iPatchBase,
|
|
xArrowOffset, // patch arrow ctrl positional offset
|
|
xVolArrowOffset; // volume arrow ctrl positional offset
|
|
|
|
static char szCaption[80];
|
|
static char szCaptionFormat[80];
|
|
|
|
/*-=-=-=-=- Functions -=-=-=-=-*/
|
|
|
|
/*
|
|
* PATCHBOX
|
|
*/
|
|
BOOL FAR PASCAL _loadds PatchBox( HWND hDlg,
|
|
UINT uMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
int iRet = FALSE;
|
|
char szBuf [50];
|
|
MMAPERR mmaperr;
|
|
|
|
switch (uMessage) {
|
|
case WM_INITDIALOG :
|
|
hWnd = hDlg;
|
|
SetFocus(GetDlgItem(hDlg, ID_PATCHNUMEDIT));
|
|
if ((mmaperr = MmaperrPatchInit(hDlg)) != MMAPERR_SUCCESS) {
|
|
VShowError(hDlg, mmaperr);
|
|
EndDialog(hDlg, FALSE);
|
|
}
|
|
SetScrollRange(hScroll, SB_CTL, 0, iVertMax, FALSE);
|
|
SetScrollPos(hScroll, SB_CTL, iVertPos, TRUE);
|
|
PlaceWindow(hWnd);
|
|
return FALSE;
|
|
|
|
case WM_COMMAND :
|
|
{ WORD id = LOWORD(wParam);
|
|
#if defined(WIN16)
|
|
WORD NotifCode = HIWORD(lParam);
|
|
HWND hwnd = LOWORD(lParam);
|
|
#else
|
|
WORD NotifCode = HIWORD(wParam);
|
|
HWND hwnd = (HWND)lParam;
|
|
#endif //WIN16
|
|
switch(id) {
|
|
case IDH_DLG_MIDI_PATCHEDIT:
|
|
goto DoHelp;
|
|
|
|
case ID_PATCHGHOSTEDITFIRST:
|
|
|
|
/* assume the user back-tabbed before the first
|
|
* control on the current row, so jump to the
|
|
* previous row (if iCurPos > 0) or the last row
|
|
* (if iCurPos == 0)
|
|
*/
|
|
if (fHidden) // we shouldn't get these
|
|
break; // messages when we're hidden -jyg
|
|
|
|
if (NotifCode != EN_SETFOCUS)
|
|
break;
|
|
if (iCurPos < 0)
|
|
/* do nothing */ ;
|
|
else if (iCurPos > 0)
|
|
iCurPos--;
|
|
else
|
|
{
|
|
if (iVertPos != 0)
|
|
{
|
|
/* at top -- scroll up one line */
|
|
PatchWindowScroll(hDlg, SB_LINEUP, 0);
|
|
iCurPos = 0;
|
|
}
|
|
else
|
|
{
|
|
PatchWindowScroll(hDlg, SB_THUMBPOSITION,iVertMax);
|
|
iCurPos = nLines - 1;
|
|
|
|
PatchSetFocus(hDlg, PSF_REDRAW|PSF_SHOWIFHIDDEN, 0L);
|
|
PatchActiveLine(PAL_SHOW, SWP_SHOWWINDOW);
|
|
}
|
|
}
|
|
PatchSetFocus(hDlg, PSF_REDRAW, 1);
|
|
SetFocus(hCombo);
|
|
break;
|
|
|
|
case ID_PATCHGHOSTEDITLAST:
|
|
|
|
/* assume the user forward-tabbed beyond the last
|
|
* control on the current row, so jump to the
|
|
* next row (if iCurPos < nLines - 1) or the first row
|
|
* (if iCurPos == nLines - 1)
|
|
*/
|
|
if (fHidden) //we shouldn't get these messages
|
|
break; //when we're hidden -jyg
|
|
|
|
if (NotifCode != EN_SETFOCUS)
|
|
break;
|
|
if (iCurPos < 0)
|
|
/* do nothing */ ;
|
|
else if (iCurPos < nLines - 1)
|
|
iCurPos++;
|
|
else
|
|
{
|
|
if (iVertPos != iVertMax)
|
|
{
|
|
/* at bottom -- scroll down one line */
|
|
PatchWindowScroll(hDlg, SB_LINEDOWN, 0);
|
|
iCurPos = nLines - 1;
|
|
}
|
|
else
|
|
{
|
|
/* wrap to the top cell */
|
|
PatchWindowScroll(hDlg, SB_THUMBPOSITION,-iVertMax);
|
|
iCurPos = 0;
|
|
|
|
PatchSetFocus(hDlg, PSF_REDRAW|PSF_SHOWIFHIDDEN, 0L);
|
|
PatchActiveLine(PAL_SHOW, SWP_SHOWWINDOW);
|
|
}
|
|
}
|
|
PatchSetFocus(hDlg, PSF_REDRAW, 1);
|
|
SetFocus(hEdit);
|
|
|
|
#if defined(WIN16)
|
|
SendMessage(hEdit, EM_SETSEL, (WPARAM)0, MAKELPARAM(0, 32767));
|
|
#else
|
|
SendMessage(hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
|
|
#endif //WIN16
|
|
break;
|
|
|
|
case IDOK :
|
|
case IDCANCEL :
|
|
if (NotifCode != BN_CLICKED)
|
|
break;
|
|
if (!fReadOnly && (id == IDOK) && fModified) {
|
|
iRet = PatchSave(hDlg, TRUE);
|
|
if (iRet == IDCANCEL)
|
|
break;
|
|
iRet = (iRet == IDYES);
|
|
}
|
|
else
|
|
iRet = FALSE;
|
|
|
|
GlobalFree(hPatchMap);
|
|
nKeys = 0;
|
|
EndDialog(hDlg, iRet);
|
|
break;
|
|
|
|
case ID_PATCHNUMEDIT :
|
|
case ID_PATCHVOLEDIT :
|
|
PatchEditMsg(id, NotifCode);
|
|
break;
|
|
|
|
case ID_PATCHCOMBO :
|
|
PatchComboMsg(hDlg, NotifCode);
|
|
break;
|
|
|
|
case ID_PATCHBASED :
|
|
if (NotifCode != BN_CLICKED)
|
|
break;
|
|
iPatchBase = !iPatchBase;
|
|
wsprintf(szBuf, aszPatchNumber,
|
|
!iPatchBase);
|
|
SetWindowText(hwnd, szBuf);
|
|
PatchEditMsg(ID_PATCHNUMEDIT, EN_ACTIVATE);
|
|
SetFocus(hEdit);
|
|
#if defined(WIN16)
|
|
SendMessage(hEdit, EM_SETSEL, (WPARAM)0, MAKELPARAM(0, 32767));
|
|
#else
|
|
SendMessage(hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
|
|
#endif //WIN16
|
|
InvalidateRect(hWnd, &rcBox, TRUE);
|
|
break;
|
|
|
|
default :
|
|
return FALSE;
|
|
}
|
|
break;
|
|
} /* end of WM_COMMAND */
|
|
case WM_PAINT :
|
|
PatchPaint();
|
|
break;
|
|
|
|
case WM_LBUTTONDOWN :
|
|
PatchButtonDown(hDlg, (LONG)lParam);
|
|
break;
|
|
|
|
case WM_VSCROLL :
|
|
#if defined(WIN16)
|
|
if ((HWND)HIWORD(lParam) == hScroll)
|
|
PatchWindowScroll(hDlg, (WORD)wParam, (int)LOWORD(lParam));
|
|
else
|
|
PatchArrowScroll((WORD)wParam, (LONG)lParam);
|
|
#else
|
|
if ((HWND)(lParam) == hScroll)
|
|
PatchWindowScroll(hDlg, LOWORD(wParam), HIWORD(wParam));
|
|
else
|
|
PatchArrowScroll(LOWORD(wParam), lParam);
|
|
|
|
#endif //WIN16
|
|
break;
|
|
|
|
case WM_CLOSE :
|
|
PostMessage(hDlg, WM_COMMAND, (WPARAM)IDOK, (LPARAM)0);
|
|
break;
|
|
|
|
default:
|
|
if (uMessage == uHelpMessage) {
|
|
DoHelp:
|
|
WinHelp(hWnd, szMidiHlp, HELP_CONTEXT,
|
|
IDH_DLG_MIDI_PATCHEDIT);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
} /* PatchBox */
|
|
|
|
/*
|
|
* MmaperrPatchInit
|
|
*/
|
|
static MMAPERR PASCAL MmaperrPatchInit(
|
|
HWND hDlg)
|
|
{
|
|
PATCHMAP FAR* lpPatch;
|
|
LONG lDBU;
|
|
MMAPERR mmaperr;
|
|
UINT xBU,
|
|
yBU,
|
|
xWidth, // width of current column
|
|
xArrow, // width of arrow control
|
|
xEdit, // width of edit controls
|
|
yEdit, // height of edit/arrow controls
|
|
xCombo, // width of combo boxes
|
|
yCombo; // height of combo boxes
|
|
int i;
|
|
|
|
fHidden = FALSE;
|
|
iVertPos = 0;
|
|
iCurPos = 0;
|
|
nKeys = 0;
|
|
nLines = 0; // necessary?
|
|
iPatchBase = 1; // getprofile
|
|
|
|
hEdit = GetDlgItem(hWnd, ID_PATCHNUMEDIT);
|
|
hArrow = GetDlgItem(hWnd, ID_PATCHNUMARROW);
|
|
hVolEdit = GetDlgItem(hWnd, ID_PATCHVOLEDIT);
|
|
hVolArrow = GetDlgItem(hWnd, ID_PATCHVOLARROW);
|
|
hCombo = GetDlgItem(hWnd, ID_PATCHCOMBO);
|
|
hScroll = GetDlgItem(hWnd, ID_PATCHSCROLL);
|
|
|
|
if (fReadOnly)
|
|
{
|
|
EnableWindow(GetDlgItem(hWnd,IDOK),FALSE);
|
|
SendMessage(hWnd, DM_SETDEFID, (WPARAM)IDCANCEL, (LPARAM)0);
|
|
}
|
|
|
|
lDBU = GetDialogBaseUnits();
|
|
xBU = LOWORD(lDBU);
|
|
yBU = HIWORD(lDBU);
|
|
|
|
xArrow = (10 * xBU) / 4; // about yea big
|
|
xEdit = (40 * xBU) / 4; // 10 chars wide
|
|
yEdit = (10 * yBU) / 8; // cookie heaven
|
|
xCombo = (64 * xBU) / 4; // 16 chars wide
|
|
yCombo = (46 * yBU) / 8; // oreos
|
|
|
|
rcBox.left = (HORZMARGIN * xBU) / 4;
|
|
for (i = 0, rcBox.right = rcBox.left; i < 6; i++) {
|
|
rgxPos [i] = rcBox.right;
|
|
|
|
switch (i) {
|
|
|
|
case 0 :
|
|
// width of src patch # text (3.5 chars wide)
|
|
rcBox.right += xEdit;
|
|
break;
|
|
|
|
case 1 :
|
|
// width of src patch name text
|
|
rcBox.right += (72 * xBU) / 4; // 18 chars wide
|
|
break;
|
|
|
|
case 2 :
|
|
// width of dst patch # edit control
|
|
xWidth = xEdit;
|
|
SetWindowPos(hEdit, NULL, 0L, 0L,
|
|
xWidth, yEdit, SWP_NOZORDER | SWP_NOMOVE);
|
|
|
|
// set global arrow control offset to proper position
|
|
rcBox.right += xArrowOffset = xWidth - 1;
|
|
|
|
// width of dst patch # arrow control
|
|
xWidth = xArrow;
|
|
SetWindowPos(hArrow, NULL, 0L, 0L,
|
|
xWidth, yEdit, SWP_NOZORDER | SWP_NOMOVE);
|
|
rcBox.right += xWidth - 1;
|
|
break;
|
|
|
|
case 3 :
|
|
// width of volume % edit control
|
|
xWidth = xEdit;
|
|
SetWindowPos(hVolEdit, NULL, 0L, 0L,
|
|
xWidth, yEdit, SWP_NOZORDER | SWP_NOMOVE);
|
|
|
|
// set global arrow control offset to proper position
|
|
rcBox.right += xVolArrowOffset = xWidth - 1;
|
|
|
|
// width of volume % arrow control
|
|
xWidth = xArrow;
|
|
SetWindowPos(hVolArrow, NULL, 0L, 0L,
|
|
xWidth, yEdit, SWP_NOZORDER | SWP_NOMOVE);
|
|
rcBox.right += xWidth - 1;
|
|
break;
|
|
|
|
case 4 :
|
|
// width of keymap combo box. I'd use MMAP_MAXLEN
|
|
xWidth = xCombo;
|
|
SetWindowPos(hCombo, NULL, 0L, 0L,
|
|
xWidth, yCombo, SWP_NOZORDER | SWP_NOMOVE);
|
|
rcBox.right += xWidth - 1;
|
|
break;
|
|
|
|
case 5 :
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
if (!nKeys)
|
|
PatchEnumKeys(hCombo);
|
|
|
|
if (!fNew) {
|
|
if ((hPatchMap = GlobalAlloc(GHND, sizeof(PATCHMAP))) == NULL)
|
|
return MMAPERR_MEMORY;
|
|
lpPatch = (PATCHMAP FAR*)GlobalLock(hPatchMap);
|
|
if ((mmaperr = mapReadPatchMap(szCurrent, lpPatch)) == MMAPERR_SUCCESS)
|
|
if (lstrcmp(lpPatch->aszPatchMapDescription, szCurDesc)) {
|
|
lstrcpy(lpPatch->aszPatchMapDescription, szCurDesc);
|
|
fNew = TRUE;
|
|
}
|
|
GlobalUnlock(hPatchMap);
|
|
if (mmaperr != MMAPERR_SUCCESS) {
|
|
GlobalFree(hPatchMap);
|
|
hPatchMap = NULL;
|
|
return mmaperr;
|
|
}
|
|
} else if ((mmaperr = MmaperrPatchInitNew()) != MMAPERR_SUCCESS)
|
|
return mmaperr;
|
|
|
|
LoadString(hLibInst, IDS_PATCHES ,szCaptionFormat, sizeof(szCaptionFormat));
|
|
wsprintf(szCaption, szCaptionFormat, (LPSTR)szCurrent);
|
|
SetWindowText(hWnd, szCaption);
|
|
|
|
SendMessage(GetDlgItem(hWnd, ID_PATCHDESTMNEM),
|
|
WM_SETFONT, (WPARAM)hFont, (LPARAM)0);
|
|
SendMessage(GetDlgItem(hWnd, ID_PATCHVOLMNEM),
|
|
WM_SETFONT, (WPARAM)hFont, (LPARAM)0);
|
|
SendMessage(GetDlgItem(hWnd, ID_PATCHKEYMNEM),
|
|
WM_SETFONT, (WPARAM)hFont, (LPARAM)0);
|
|
PatchSize(hDlg, TRUE);
|
|
i = rcBox.top - yChar + 5;
|
|
SetWindowPos(GetDlgItem(hWnd, ID_PATCHDESTMNEM), NULL,
|
|
rgxPos [2] - xChar + 7, i, 0L, 0L, SWP_NOSIZE | SWP_NOZORDER);
|
|
SetWindowPos(GetDlgItem(hWnd, ID_PATCHVOLMNEM), NULL,
|
|
rgxPos [3] + xChar - 6, i, 0L, 0L, SWP_NOSIZE | SWP_NOZORDER);
|
|
SetWindowPos(GetDlgItem(hWnd, ID_PATCHKEYMNEM), NULL,
|
|
rgxPos [4] + xChar, i, 0L, 0L, SWP_NOSIZE | SWP_NOZORDER);
|
|
#if defined(WIN16)
|
|
SendMessage(hWnd, WM_COMMAND, (WPARAM)ID_PATCHBASED, MAKELPARAM(GetDlgItem(hWnd, ID_PATCHBASED), BN_CLICKED));
|
|
#else
|
|
SendMessage( hWnd
|
|
, WM_COMMAND
|
|
, (WPARAM)MAKELONG(ID_PATCHBASED, BN_CLICKED)
|
|
, (LPARAM)GetDlgItem(hWnd, ID_PATCHBASED)
|
|
);
|
|
#endif //WIN16
|
|
Modify(fNew);
|
|
return MMAPERR_SUCCESS;
|
|
} /* MmaperrPatchInit */
|
|
|
|
/*
|
|
* MmaperrPatchInitNew
|
|
*/
|
|
static MMAPERR PASCAL MmaperrPatchInitNew(
|
|
VOID)
|
|
{
|
|
PATCHMAP FAR* lpPatch;
|
|
UINT u;
|
|
|
|
if ((hPatchMap = GlobalAlloc(GHND,
|
|
(DWORD)sizeof(PATCHMAP))) == NULL)
|
|
return MMAPERR_MEMORY;
|
|
lpPatch = (PATCHMAP FAR*)GlobalLock(hPatchMap);
|
|
lstrcpy(lpPatch->aszPatchMapName, szCurrent);
|
|
lstrcpy(lpPatch->aszPatchMapDescription, szCurDesc);
|
|
for (u = 0; u < MIDIPATCHSIZE; u++) {
|
|
lpPatch->keymaps[u].bVolume = 100;
|
|
lpPatch->keymaps[u].bDestination = (BYTE)u;
|
|
lstrcpy(lpPatch->keymaps[u].aszKeyMapName, szNone);
|
|
}
|
|
GlobalUnlock(hPatchMap);
|
|
return MMAPERR_SUCCESS;
|
|
} /* MmaperrPatchInitNew */
|
|
|
|
/*
|
|
* PATCHENUMKEYS
|
|
*/
|
|
static
|
|
VOID PASCAL PatchEnumKeys(HWND hCombo)
|
|
{
|
|
mapEnumerate(MMAP_KEY, EnumFunc, MMENUM_BASIC, hCombo, NULL);
|
|
SendMessage(hCombo, CB_ADDSTRING, (WPARAM)0, (LPARAM)(LPSTR)szNone);
|
|
nKeys = (int)(LONG)SendMessage(hCombo, CB_GETCOUNT, (WPARAM)NULL, (LPARAM)0);
|
|
} /* PatchEnumKeys */
|
|
|
|
/*
|
|
* PATCHSIZE
|
|
*/
|
|
static
|
|
VOID PASCAL PatchSize(HWND hDlg, BOOL fMaximize)
|
|
{
|
|
HWND hBanana;
|
|
RECT rcBanana;
|
|
RECT rcOK,
|
|
rcWnd;
|
|
LONG lDBU;
|
|
UINT xBU,
|
|
yBU;
|
|
int xButton,
|
|
xCenter,
|
|
yTopMar,
|
|
yBotMar,
|
|
yLeftOver,
|
|
yBox,
|
|
yMiniBotMar;
|
|
|
|
lDBU = GetDialogBaseUnits();
|
|
xBU = LOWORD(lDBU);
|
|
yBU = HIWORD(lDBU);
|
|
|
|
// get the rectangle of the OK button
|
|
GetClientRect(GetDlgItem(hWnd, IDOK), &rcOK);
|
|
|
|
// get x-extent of button
|
|
xButton = rcOK.right - rcOK.left;
|
|
|
|
// top margin is 4 characters
|
|
yTopMar = (32 * yBU) / 8 - 6; // cookie land
|
|
|
|
// bottom margin is 2 * minimum bottom margin dialog units +
|
|
// height of button in pixels
|
|
yBotMar = (VERTMARGIN * 2 * yBU) / 8 + rcOK.bottom - rcOK.top;
|
|
|
|
if (fMaximize) {
|
|
// maximize the patch box
|
|
SetWindowPos(hWnd, NULL, 0L, 0L,
|
|
rcBox.right - rcBox.left +
|
|
(2 * HORZMARGIN * xBU) / 4 +
|
|
GetSystemMetrics(SM_CXVSCROLL) +
|
|
(GetSystemMetrics(SM_CXDLGFRAME) + 1) * 2,
|
|
(DEF_PATCH_ROWS * 10 * yBU) / 8 +
|
|
yTopMar + yBotMar +
|
|
GetSystemMetrics(SM_CYCAPTION) +
|
|
GetSystemMetrics(SM_CYDLGFRAME) * 2,
|
|
SWP_NOZORDER | SWP_NOMOVE);
|
|
}
|
|
|
|
// get the x and y extents of the client rectangle
|
|
GetClientRect(hWnd, &rcWnd);
|
|
xClient = rcWnd.right - rcWnd.left;
|
|
yClient = rcWnd.bottom - rcWnd.top;
|
|
|
|
// yChar is the height of one row in pixels - 1
|
|
yChar = (10 * yBU) / 8 - 1;
|
|
|
|
// xChar is the average width of a character
|
|
xChar = xBU;
|
|
|
|
// yBox is the room we actually have to display patchmap rows
|
|
yBox = yClient - yTopMar - yBotMar;
|
|
|
|
// nLines is the number of setup rows we can display
|
|
nLines = min(16, yBox / yChar);
|
|
|
|
// yLeftOver is how many pixels are left over
|
|
yLeftOver = yBox - nLines * yChar;
|
|
|
|
// add half the leftovers to the top margin
|
|
yTopMar += yLeftOver / 2;
|
|
|
|
// rcBox is the box of rows and columns inside the client area
|
|
SetRect(
|
|
&rcBox,
|
|
rcBox.left,
|
|
yTopMar,
|
|
rcBox.right,
|
|
yTopMar + nLines * yChar);
|
|
|
|
// xCenter is used to center the OK and CANCEL buttons horizontally
|
|
xCenter = (rcBox.right - rcBox.left - xButton * 3) / 4;
|
|
|
|
// yMiniBotMar is the spacing above and below the button
|
|
yMiniBotMar = (VERTMARGIN * yBU) / 8 + yLeftOver / 4;
|
|
|
|
SetWindowPos(
|
|
GetDlgItem(hWnd, IDOK),
|
|
NULL,
|
|
rcBox.left + xCenter,
|
|
rcBox.bottom + yMiniBotMar,
|
|
0L,
|
|
0L,
|
|
SWP_NOSIZE | SWP_NOZORDER);
|
|
|
|
SetWindowPos(
|
|
GetDlgItem(hWnd, IDCANCEL),
|
|
NULL,
|
|
rcBox.left + xButton + xCenter * 2,
|
|
rcBox.bottom + yMiniBotMar,
|
|
0L,
|
|
0L,
|
|
SWP_NOSIZE | SWP_NOZORDER);
|
|
|
|
SetWindowPos(
|
|
GetDlgItem(hWnd, IDH_DLG_MIDI_PATCHEDIT),
|
|
NULL,
|
|
rcBox.left + xButton * 2 + xCenter * 3,
|
|
rcBox.bottom + yMiniBotMar,
|
|
0L,
|
|
0L,
|
|
SWP_NOSIZE | SWP_NOZORDER);
|
|
|
|
// get the banana button
|
|
hBanana = GetDlgItem(hWnd, ID_PATCHBASED);
|
|
|
|
// get the rectangle of the banana button
|
|
GetClientRect(hBanana, &rcBanana);
|
|
|
|
// set the banana position
|
|
SetWindowPos(
|
|
hBanana,
|
|
NULL,
|
|
rcBox.left + (rcBox.right - rcBox.left - rcBanana.right) / 2,
|
|
(6 * yBU) / 8,
|
|
0L,
|
|
0L,
|
|
SWP_NOSIZE | SWP_NOZORDER);
|
|
|
|
SetWindowPos(
|
|
hScroll,
|
|
NULL,
|
|
rcBox.right,
|
|
rcBox.top,
|
|
GetSystemMetrics(SM_CXVSCROLL),
|
|
rcBox.bottom - rcBox.top + 1,
|
|
SWP_NOZORDER);
|
|
|
|
iVertMax = max(0, MIDIPATCHSIZE - nLines);
|
|
iVertPos = min(iVertMax, iVertPos);
|
|
SetScrollRange(hScroll, SB_CTL, 0, iVertMax, FALSE);
|
|
SetScrollPos(hScroll, SB_CTL, iVertPos, TRUE);
|
|
|
|
if (iCurPos >= 0 && iCurPos < nLines)
|
|
PatchSetFocus(hDlg, PSF_SHOWIFHIDDEN, 1);
|
|
else
|
|
PatchActiveLine(PAL_HIDE, SWP_NOREDRAW);
|
|
} /* PatchSize */
|
|
|
|
/*
|
|
* PATCHPAINT
|
|
*/
|
|
static
|
|
VOID PASCAL PatchPaint(VOID)
|
|
{
|
|
HPEN hPen = 0;
|
|
PATCHMAP FAR* lpPatch;
|
|
PAINTSTRUCT ps;
|
|
int i,
|
|
iVert,
|
|
iLeft,
|
|
nBegin,
|
|
nEnd,
|
|
iTop,
|
|
iBottom;
|
|
BOOL fSelected = FALSE;
|
|
char szBuf [50];
|
|
|
|
BeginPaint(hWnd, &ps);
|
|
|
|
if (!ps.rcPaint.bottom)
|
|
goto DonePainting;
|
|
|
|
hPen = SelectObject(ps.hdc, GetStockObject(BLACK_PEN));
|
|
hFont = SelectObject(ps.hdc, hFont);
|
|
fSelected = TRUE;
|
|
|
|
SetTextColor(ps.hdc, GetSysColor(COLOR_WINDOWTEXT));
|
|
SetBkMode(ps.hdc, TRANSPARENT);
|
|
|
|
if (ps.rcPaint.top < rcBox.top) {
|
|
iVert = rcBox.top - yChar + 5;
|
|
TextOut(ps.hdc, 11, iVert, aszSourcePatch, lstrlen(aszSourcePatch));
|
|
TextOut(ps.hdc, rgxPos [1] + xChar * 2 - 15, iVert,
|
|
aszSourcePatchName, lstrlen(aszSourcePatchName));
|
|
}
|
|
|
|
// calculate top and bottom y coordinates of invalid area
|
|
iTop = max(ps.rcPaint.top, rcBox.top);
|
|
|
|
// if top is below the box, forget about painting
|
|
if (iTop > rcBox.bottom)
|
|
goto DonePainting;
|
|
|
|
iBottom = min(ps.rcPaint.bottom, rcBox.bottom);
|
|
|
|
// calculate left x coordinate of invalid area
|
|
iLeft = max(ps.rcPaint.left, rcBox.left);
|
|
|
|
// calculate beginning and ending data row to be repainted
|
|
nBegin = max(0, (iTop - rcBox.top) / yChar);
|
|
nEnd = min(nLines, (iBottom - rcBox.top) / yChar);
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
MMoveTo(ps.hdc, rgxPos [i], iTop);
|
|
LineTo(ps.hdc, rgxPos [i], iBottom + 1);
|
|
}
|
|
// vertical position of first line we have to draw
|
|
iVert = rcBox.top + nBegin * yChar;
|
|
|
|
// lock the map
|
|
lpPatch = (PATCHMAP FAR*)GlobalLock(hPatchMap);
|
|
for (i = nBegin; i <= nEnd; i++, iVert += yChar) {
|
|
MMoveTo(ps.hdc, iLeft, iVert);
|
|
LineTo(ps.hdc, min(ps.rcPaint.right, rcBox.right), iVert);
|
|
|
|
if (i == nLines)
|
|
break;
|
|
|
|
if (iLeft < rgxPos [1]) {
|
|
wsprintf(szBuf, aszPatchNumFormat, iVertPos + iPatchBase + i);
|
|
TextOut(ps.hdc, rgxPos [0] + xChar, iVert + 2,
|
|
szBuf, 3);
|
|
}
|
|
if (iLeft < rgxPos [2]) {
|
|
if (!LoadString(hLibInst, IDS_PATCHMAP_BASE +
|
|
iVertPos + i + 1, szBuf, sizeof(szBuf)))
|
|
LoadString(hLibInst, IDS_RESERVED, szBuf, sizeof(szBuf));
|
|
TextOut(ps.hdc, rgxPos [1] + 2, iVert + 2,
|
|
szBuf, lstrlen(szBuf));
|
|
}
|
|
|
|
if (i == iCurPos)
|
|
continue;
|
|
|
|
if (iLeft < rgxPos [3]) {
|
|
wsprintf(szBuf, aszPatchNumFormat, lpPatch->keymaps[iVertPos + i].bDestination + iPatchBase);
|
|
TextOut(ps.hdc, rgxPos [2] + xChar * 2, iVert + 2,
|
|
szBuf, 3);
|
|
}
|
|
if (iLeft < rgxPos [4]) {
|
|
wsprintf(szBuf, aszPatchNumFormat, lpPatch->keymaps[iVertPos + i].bVolume);
|
|
TextOut(ps.hdc, rgxPos [3] + xChar * 2, iVert + 2,
|
|
szBuf, 3);
|
|
}
|
|
if (iLeft < rgxPos [5])
|
|
TextOut(ps.hdc, rgxPos [4] + 2, iVert + 2, lpPatch->keymaps[iVertPos + i].aszKeyMapName,
|
|
lstrlen(lpPatch->keymaps[iVertPos + i].aszKeyMapName));
|
|
}
|
|
GlobalUnlock(hPatchMap);
|
|
|
|
DonePainting:
|
|
if (fSelected) {
|
|
hFont = SelectObject(ps.hdc, hFont);
|
|
hPen = SelectObject(ps.hdc, hPen);
|
|
}
|
|
EndPaint(hWnd, &ps);
|
|
} /* PatchPaint */
|
|
|
|
/*
|
|
* PATCHARROWSCROLL
|
|
*
|
|
* Interpret a scroll message for the arrow control.
|
|
*/
|
|
static
|
|
VOID PASCAL PatchArrowScroll( WPARAM wParam, // scroll code only (even on 32 bit)
|
|
LPARAM lParam ) // (hwnd,posn) (16 bit), hwnd (32 bit)
|
|
// posn not actually used.
|
|
{
|
|
PATCHMAP FAR* lpPatch;
|
|
UINT uId;
|
|
BYTE bPatch,
|
|
bMax,
|
|
bMin;
|
|
|
|
lpPatch = (PATCHMAP FAR*)GlobalLock(hPatchMap);
|
|
|
|
#if defined(WIN16)
|
|
if ((HWND)HIWORD(lParam) == hArrow) {
|
|
#else
|
|
if ((HWND)lParam == hArrow) {
|
|
#endif
|
|
uId = ID_PATCHNUMEDIT;
|
|
bPatch = lpPatch->keymaps[iVertPos + iCurPos].bDestination + (BYTE)iPatchBase;
|
|
bMax = (BYTE)(127 + iPatchBase); // MMAP_MAXPATCHES
|
|
bMin = (BYTE)iPatchBase;
|
|
}
|
|
else {
|
|
uId = ID_PATCHVOLEDIT;
|
|
bPatch = lpPatch->keymaps[iVertPos + iCurPos].bVolume;
|
|
bMax = 200; // MMAP_MAXVOLUME
|
|
bMin = 0;
|
|
}
|
|
GlobalUnlock(hPatchMap);
|
|
|
|
switch (wParam) {
|
|
|
|
case SB_LINEDOWN :
|
|
if (bPatch-- == bMin)
|
|
bPatch = bMax;
|
|
break;
|
|
|
|
case SB_LINEUP :
|
|
if (bPatch++ == bMax)
|
|
bPatch = bMin;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
SetDlgItemInt(hWnd, uId, bPatch, FALSE);
|
|
} /* PatchArrowScroll */
|
|
|
|
/*
|
|
* PATCHWINDOWSCROLL
|
|
*/
|
|
static
|
|
VOID PASCAL PatchWindowScroll( HWND hDlg,
|
|
UINT wParam,
|
|
int iPos )
|
|
{
|
|
HDC hDC;
|
|
RECT rc;
|
|
int iVertInc;
|
|
BOOL fWillBeVisible; // will it be visible after scroll?
|
|
|
|
switch (wParam) {
|
|
|
|
case SB_LINEUP :
|
|
iVertInc = -1;
|
|
break;
|
|
|
|
case SB_LINEDOWN :
|
|
iVertInc = 1;
|
|
break;
|
|
|
|
case SB_PAGEUP :
|
|
iVertInc = min(-1, -nLines);
|
|
break;
|
|
|
|
case SB_PAGEDOWN :
|
|
iVertInc = max(1, nLines);
|
|
break;
|
|
|
|
case SB_THUMBTRACK :
|
|
case SB_THUMBPOSITION :
|
|
iVertInc = iPos - iVertPos;
|
|
break;
|
|
|
|
default :
|
|
iVertInc = 0;
|
|
}
|
|
|
|
|
|
iVertInc = max(-iVertPos, min(iVertInc, iVertMax - iVertPos));
|
|
|
|
if (iVertInc != 0)
|
|
{
|
|
iVertPos += iVertInc;
|
|
iCurPos -= iVertInc;
|
|
|
|
if (iCurPos < 0 || iCurPos >= nLines) {
|
|
SetFocus(NULL);
|
|
fWillBeVisible = FALSE;
|
|
}
|
|
else
|
|
fWillBeVisible = TRUE;
|
|
|
|
// Scroll to the correct position
|
|
|
|
SetScrollPos(hScroll, SB_CTL, iVertPos, TRUE);
|
|
|
|
hDC = GetDC(hWnd);
|
|
ScrollDC(hDC, 0L, -yChar * iVertInc, &rcBox, &rcBox, NULL, &rc);
|
|
ReleaseDC(hWnd, hDC);
|
|
|
|
if (!fHidden)
|
|
PatchActiveLine(PAL_HIDE, SWP_NOREDRAW);
|
|
|
|
if (fWillBeVisible) {
|
|
PatchSetFocus(hDlg, 0L, 0L);
|
|
PatchActiveLine(PAL_SHOW, SWP_NOREDRAW);
|
|
}
|
|
InvalidateRect(hWnd, &rc, TRUE);
|
|
UpdateWindow(hWnd);
|
|
}
|
|
} /* PatchWindowScroll */
|
|
|
|
/*
|
|
* PatchEditMsg
|
|
*
|
|
* This function deals with EN_UPDATE and EN_ACTIVATE messages sent
|
|
* to the patch number and volume percent edit controls through the
|
|
* WM_COMMAND message.
|
|
*/
|
|
static
|
|
VOID PASCAL PatchEditMsg( UINT id, WORD NotifCode )
|
|
{
|
|
PATCHMAP FAR* lpPatch;
|
|
UINT
|
|
uVal, // value of control
|
|
uMin, // min value allowed
|
|
uMax; // max value allowed
|
|
BOOL bTranslate;
|
|
|
|
if (NotifCode != EN_UPDATE && NotifCode != EN_ACTIVATE)
|
|
return;
|
|
|
|
lpPatch = (PATCHMAP FAR*)GlobalLock(hPatchMap);
|
|
|
|
switch (NotifCode) {
|
|
|
|
case EN_UPDATE :
|
|
if (id == ID_PATCHNUMEDIT) {
|
|
uMax = 127 + iPatchBase;// MMAP_MAXPATCHES
|
|
uMin = iPatchBase;
|
|
}
|
|
else {
|
|
uMax = 200; // MMAP_MAXVOLUME
|
|
uMin = 0;
|
|
}
|
|
|
|
uVal = (UINT)GetDlgItemInt(hWnd, id, &bTranslate, TRUE);
|
|
|
|
if ((int)uVal < (int)uMin) {
|
|
uVal = uMin;
|
|
SetDlgItemInt(hWnd, id, uVal, FALSE);
|
|
} else if (uVal > uMax) {
|
|
uVal = uMax;
|
|
SetDlgItemInt(hWnd, id, uVal, FALSE);
|
|
} else {
|
|
if (id == ID_PATCHNUMEDIT) {
|
|
uVal -= iPatchBase;
|
|
if (uVal != lpPatch->keymaps[iVertPos + iCurPos].bDestination) {
|
|
lpPatch->keymaps[iVertPos + iCurPos].bDestination = (BYTE)uVal;
|
|
Modify(TRUE);
|
|
}
|
|
} else if (uVal != lpPatch->keymaps[iVertPos + iCurPos].bVolume) {
|
|
lpPatch->keymaps[iVertPos + iCurPos].bVolume = (BYTE)uVal;
|
|
Modify(TRUE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case EN_ACTIVATE :
|
|
if (id == ID_PATCHNUMEDIT)
|
|
SetDlgItemInt(hWnd, id, lpPatch->keymaps[iVertPos + iCurPos].bDestination + iPatchBase, FALSE);
|
|
else
|
|
SetDlgItemInt(hWnd, id, lpPatch->keymaps[iVertPos + iCurPos].bVolume, FALSE);
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
|
|
}
|
|
|
|
GlobalUnlock(hPatchMap);
|
|
} /* PatchEditMsg */
|
|
|
|
/*
|
|
* PatchComboMsg
|
|
*
|
|
* This function deals with the CBN_ACTIVATE and CBN_SELCHANGE messages sent
|
|
* to the keymap name combo box through the WM_COMMAND message.
|
|
*/
|
|
static
|
|
VOID PASCAL PatchComboMsg(HWND hDlg, WORD NotifCode)
|
|
{
|
|
PATCHMAP FAR* lpPatch;
|
|
char szBuf [MMAP_MAXNAME];
|
|
|
|
if (NotifCode != CBN_ACTIVATE && NotifCode != CBN_SELCHANGE)
|
|
return;
|
|
|
|
lpPatch = (PATCHMAP FAR*)GlobalLock(hPatchMap);
|
|
|
|
switch (NotifCode) {
|
|
|
|
case CBN_ACTIVATE :
|
|
SendMessage(hCombo, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)(lpPatch->keymaps[iVertPos + iCurPos].aszKeyMapName));
|
|
break;
|
|
|
|
case CBN_SELCHANGE:
|
|
GetWindowText(hCombo, szBuf, MMAP_MAXNAME);
|
|
if (!lstrcmpi(szBuf, lpPatch->keymaps[iVertPos + iCurPos].aszKeyMapName))
|
|
break;
|
|
lstrcpy(lpPatch->keymaps[iVertPos + iCurPos].aszKeyMapName, szBuf);
|
|
Modify(TRUE);
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
}
|
|
|
|
GlobalUnlock(hPatchMap);
|
|
} /* PatchComboMsg */
|
|
|
|
/*
|
|
* PATCHBUTTONDOWN
|
|
*/
|
|
static
|
|
VOID PASCAL PatchButtonDown(HWND hDlg, LONG lParam)
|
|
{
|
|
int x = LOWORD(lParam),
|
|
y = HIWORD(lParam),
|
|
iPos;
|
|
UINT uFlags;
|
|
|
|
if (x < rcBox.left || x > rcBox.right)
|
|
return;
|
|
if (y < rcBox.top || y > rcBox.bottom)
|
|
return;
|
|
|
|
iPos = min(nLines - 1, (y - rcBox.top) / yChar);
|
|
|
|
if (iPos == iCurPos)
|
|
return;
|
|
|
|
if (iCurPos >= 0 && iCurPos < nLines) {
|
|
uFlags = PSF_REDRAW;
|
|
SendMessage(hCombo, CB_SHOWDROPDOWN, (WPARAM)FALSE, (LPARAM)0);
|
|
UpdateWindow(hWnd);
|
|
}
|
|
else
|
|
uFlags = PSF_SHOWIFHIDDEN;
|
|
|
|
iCurPos = iPos;
|
|
PatchSetFocus(hDlg, uFlags, x);
|
|
} /* PatchButtonDown */
|
|
|
|
/*
|
|
* PATCHSETFOCUS
|
|
*/
|
|
static
|
|
VOID PASCAL PatchSetFocus( HWND hDlg,
|
|
UINT uFlags,
|
|
int xPos )
|
|
{
|
|
RECT rc;
|
|
int yPos = rcBox.top + iCurPos * yChar;
|
|
|
|
PatchEditMsg(ID_PATCHNUMEDIT, EN_ACTIVATE);
|
|
PatchEditMsg(ID_PATCHVOLEDIT, EN_ACTIVATE);
|
|
PatchComboMsg(hDlg, CBN_ACTIVATE);
|
|
|
|
GetWindowRect(hEdit, &rc);
|
|
|
|
SetWindowPos(hEdit, NULL, rgxPos [2], yPos, 0L, 0L,
|
|
SWP_NOZORDER | SWP_NOSIZE);
|
|
SetWindowPos(hArrow, NULL, rgxPos [2] + xArrowOffset, yPos, 0L,
|
|
0L, SWP_NOZORDER | SWP_NOSIZE);
|
|
SetWindowPos(hVolEdit, NULL, rgxPos [3], yPos, 0L, 0L,
|
|
SWP_NOZORDER | SWP_NOSIZE);
|
|
SetWindowPos(hVolArrow, NULL, rgxPos [3] + xVolArrowOffset, yPos,
|
|
0L, 0L, SWP_NOZORDER | SWP_NOSIZE);
|
|
SetWindowPos(hCombo, NULL, rgxPos [4], yPos, 0L, 0L,
|
|
SWP_NOZORDER | SWP_NOSIZE);
|
|
|
|
if (fHidden && uFlags & PSF_SHOWIFHIDDEN) {
|
|
PatchActiveLine(PAL_SHOW, 0L);
|
|
UpdateWindow(hEdit);
|
|
UpdateWindow(hArrow);
|
|
UpdateWindow(hVolEdit);
|
|
UpdateWindow(hVolArrow);
|
|
UpdateWindow(hCombo);
|
|
}
|
|
|
|
if (uFlags & PSF_REDRAW && rc.right) {
|
|
ScreenToClient(hWnd, (LPPOINT)&rc);
|
|
ScreenToClient(hWnd, (LPPOINT)&rc + 1);
|
|
rc.right = rcBox.right + 1;
|
|
InvalidateRect(hWnd, &rc, FALSE);
|
|
UpdateWindow(hWnd);
|
|
}
|
|
|
|
if (xPos < rgxPos [3]) {
|
|
if (!fHidden)
|
|
SetFocus(hEdit);
|
|
#if defined(WIN16)
|
|
SendMessage(hEdit, EM_SETSEL, (WPARAM)NULL, MAKELPARAM(0, 32767));
|
|
#else
|
|
SendMessage(hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
|
|
#endif //WIN16
|
|
}
|
|
else if (xPos < rgxPos [4]) {
|
|
if (!fHidden)
|
|
SetFocus(hVolEdit);
|
|
#if defined(WIN16)
|
|
SendMessage(hVolEdit, EM_SETSEL, (WPARAM)NULL, MAKELPARAM(0, 32767));
|
|
#else
|
|
SendMessage(hVolEdit, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
|
|
#endif //WIN16
|
|
}
|
|
else if (xPos < rgxPos [5] && !fHidden)
|
|
SetFocus(hCombo);
|
|
} /* PatchSetFocus */
|
|
|
|
/*
|
|
* PATCHACTIVELINE
|
|
*/
|
|
static
|
|
VOID PASCAL PatchActiveLine( UINT uCase,
|
|
UINT uFlags )
|
|
{
|
|
static const UINT uDefFlags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER;
|
|
|
|
switch (uCase) {
|
|
|
|
case PAL_SHOW :
|
|
if (!fHidden)
|
|
return;
|
|
|
|
uFlags |= SWP_SHOWWINDOW;
|
|
fHidden = FALSE;
|
|
break;
|
|
|
|
case PAL_HIDE :
|
|
if (fHidden)
|
|
return;
|
|
|
|
uFlags |= SWP_HIDEWINDOW;
|
|
fHidden = TRUE;
|
|
break;
|
|
|
|
default :
|
|
break;
|
|
|
|
}
|
|
uFlags |= uDefFlags;
|
|
SetWindowPos(hEdit, NULL, 0L, 0L, 0L, 0L, uFlags);
|
|
SetWindowPos(hArrow, NULL, 0L, 0L, 0L, 0L, uFlags);
|
|
SetWindowPos(hVolEdit, NULL, 0L, 0L, 0L, 0L, uFlags);
|
|
SetWindowPos(hVolArrow, NULL, 0L, 0L, 0L, 0L, uFlags);
|
|
SetWindowPos(hCombo, NULL, 0L, 0L, 0L, 0L, uFlags);
|
|
|
|
if (uCase == PAL_SHOW && !fHidden)
|
|
SetFocus(hEdit);
|
|
} /* PatchActiveLine */
|
|
|
|
/*
|
|
* PATCHSAVE
|
|
*/
|
|
static int PASCAL PatchSave(
|
|
HWND hDlg,
|
|
BOOL bQuery)
|
|
{
|
|
PATCHMAP FAR* lpPatch;
|
|
MMAPERR mmaperr;
|
|
int iRet = 0; // a value other than IDCANCEL or IDYES
|
|
|
|
if (bQuery) {
|
|
iRet = QuerySave();
|
|
if (iRet != IDYES)
|
|
return iRet;
|
|
}
|
|
lpPatch = (PATCHMAP FAR*)GlobalLock(hPatchMap);
|
|
mmaperr = mapWrite(MMAP_PATCH, lpPatch);
|
|
GlobalUnlock(hPatchMap);
|
|
if (mmaperr != MMAPERR_SUCCESS) {
|
|
VShowError(hDlg, mmaperr);
|
|
return IDCANCEL;
|
|
}
|
|
Modify(FALSE);
|
|
if (fNew)
|
|
fNew = FALSE;
|
|
return iRet;
|
|
} /* PatchSave */
|