WindowsXP-SP1/shell/comdlg32/dlgs.c

1108 lines
31 KiB
C

/*++
Copyright (c) 1990-1998, Microsoft Corporation All rights reserved.
Module Name:
dlgs.c
Abstract:
This module contains the common functions for the Win32 common dialogs.
Revision History:
--*/
// precompiled headers
#include "precomp.h"
#pragma hdrstop
#include "util.h"
//
// Global Variables.
//
extern BOOL bInitializing;
extern DWORD g_tlsiExtError;
//
// Function Prototypes.
//
LONG
RgbInvertRgb(
LONG rgbOld);
const struct _ERRORMAP
{
DWORD dwCommDlgError;
DWORD dwWin32Error;
} ERRORMAP[] =
{
{ CDERR_INITIALIZATION , ERROR_INVALID_PARAMETER},
{ PDERR_INITFAILURE , ERROR_INVALID_PARAMETER},
{ CDERR_STRUCTSIZE , ERROR_INVALID_PARAMETER},
{ CDERR_NOTEMPLATE , ERROR_INVALID_PARAMETER},
{ CDERR_NOHINSTANCE , ERROR_INVALID_PARAMETER},
{ CDERR_NOHOOK , ERROR_INVALID_PARAMETER},
{ CDERR_MEMALLOCFAILURE , ERROR_OUTOFMEMORY},
{ CDERR_LOCKRESFAILURE , ERROR_INVALID_HANDLE},
{ CDERR_DIALOGFAILURE , E_FAIL},
{ PDERR_SETUPFAILURE , ERROR_INVALID_PARAMETER},
{ PDERR_RETDEFFAILURE , ERROR_INVALID_PARAMETER},
{ FNERR_BUFFERTOOSMALL , ERROR_INSUFFICIENT_BUFFER},
{ FRERR_BUFFERLENGTHZERO, ERROR_INSUFFICIENT_BUFFER},
{ FNERR_INVALIDFILENAME , ERROR_INVALID_NAME},
{ PDERR_NODEFAULTPRN , E_FAIL},
{ CFERR_NOFONTS , E_FAIL},
{ CFERR_MAXLESSTHANMIN , ERROR_INVALID_PARAMETER},
};
////////////////////////////////////////////////////////////////////////////
//
// StoreExtendedError
//
// Stores an extended error code for the next call to
// CommDlgExtendedError.
//
////////////////////////////////////////////////////////////////////////////
void StoreExtendedError(
DWORD dwError)
{
int i;
for (i=0; i < ARRAYSIZE(ERRORMAP); i++)
{
if (ERRORMAP[i].dwCommDlgError == dwError)
{
SetLastError(ERRORMAP[i].dwWin32Error);
break;
}
}
TlsSetValue(g_tlsiExtError, UlongToPtr(dwError));
}
////////////////////////////////////////////////////////////////////////////
//
// GetStoredExtendedError
//
// Retieves the stored extended error code.
//
////////////////////////////////////////////////////////////////////////////
DWORD GetStoredExtendedError(void)
{
DWORD dwError;
dwError = PtrToUlong(TlsGetValue(g_tlsiExtError));
return (dwError);
}
////////////////////////////////////////////////////////////////////////////
//
// CommDlgExtendedError
//
// Provides additional information about dialog failure.
// This should be called immediately after failure.
//
// Returns: LO word - error code
// HI word - error specific info
//
////////////////////////////////////////////////////////////////////////////
DWORD WINAPI CommDlgExtendedError()
{
return (GetStoredExtendedError());
}
////////////////////////////////////////////////////////////////////////////
//
// HourGlass
//
// Turn hourglass on or off.
//
// bOn - specifies ON or OFF
//
////////////////////////////////////////////////////////////////////////////
VOID HourGlass(
BOOL bOn)
{
//
// Change cursor to hourglass.
//
if (!bInitializing)
{
if (!bMouse)
{
ShowCursor(bCursorLock = bOn);
}
SetCursor(LoadCursor(NULL, bOn ? IDC_WAIT : IDC_ARROW));
}
}
////////////////////////////////////////////////////////////////////////////
//
// LoadAlterBitmap
//
// Loads a bitmap given its name and gives all the pixels that are
// a certain color a new color.
//
// Returns: NULL - failed
// handle to the bitmap loaded - success
//
////////////////////////////////////////////////////////////////////////////
HBITMAP WINAPI LoadAlterBitmap(
int id,
DWORD rgbReplace,
DWORD rgbInstead)
{
LPBITMAPINFOHEADER qbihInfo;
HDC hdcScreen;
BOOL fFound;
HANDLE hresLoad;
HANDLE hres;
LPLONG qlng;
DWORD *qlngReplace; // points to bits that are replaced
LPBYTE qbBits;
HANDLE hbmp;
LPBITMAPINFOHEADER lpBitmapInfo;
UINT cbBitmapSize;
hresLoad = FindResource(g_hinst, MAKEINTRESOURCE(id), RT_BITMAP);
if (hresLoad == HNULL)
{
return (HNULL);
}
hres = LoadResource(g_hinst, hresLoad);
if (hres == HNULL)
{
return (HNULL);
}
//
// Lock the bitmap data and make a copy of it for the mask and the
// bitmap.
//
cbBitmapSize = SizeofResource(g_hinst, hresLoad);
lpBitmapInfo = (LPBITMAPINFOHEADER)LockResource(hres);
qbihInfo = (LPBITMAPINFOHEADER)LocalAlloc(LPTR, cbBitmapSize);
if ((lpBitmapInfo == NULL) || (qbihInfo == NULL))
{
return (NULL);
}
memcpy((TCHAR *)qbihInfo, (TCHAR *)lpBitmapInfo, cbBitmapSize);
//
// Get a pointer into the color table of the bitmaps, cache the
// number of bits per pixel.
//
rgbReplace = RgbInvertRgb(rgbReplace);
rgbInstead = RgbInvertRgb(rgbInstead);
qlng = (LPLONG)((LPSTR)(qbihInfo) + qbihInfo->biSize);
fFound = FALSE;
while (!fFound)
{
if (*qlng == (LONG)rgbReplace)
{
fFound = TRUE;
qlngReplace = (DWORD *)qlng;
*qlng = (LONG)rgbInstead;
}
qlng++;
}
//
// First skip over the header structure.
//
qbBits = (LPBYTE)(qbihInfo + 1);
//
// Skip the color table entries, if any.
//
qbBits += (1 << (qbihInfo->biBitCount)) * sizeof(RGBQUAD);
//
// Create a color bitmap compatible with the display device.
//
hdcScreen = GetDC(HNULL);
if (hdcScreen != HNULL)
{
hbmp = CreateDIBitmap( hdcScreen,
qbihInfo,
(LONG)CBM_INIT,
qbBits,
(LPBITMAPINFO)qbihInfo,
DIB_RGB_COLORS );
ReleaseDC(HNULL, hdcScreen);
}
//
// Reset color bits to original value.
//
*qlngReplace = (LONG)rgbReplace;
LocalFree(qbihInfo);
return (hbmp);
}
////////////////////////////////////////////////////////////////////////////
//
// RgbInvertRgb
//
// Reverses the byte order of the RGB value (for file format).
//
// Returns the new color value (RGB to BGR).
//
////////////////////////////////////////////////////////////////////////////
LONG RgbInvertRgb(
LONG rgbOld)
{
LONG lRet;
BYTE R, G, B;
R = GetRValue(rgbOld);
G = GetGValue(rgbOld);
B = GetBValue(rgbOld);
lRet = (LONG)RGB(B, G, R);
return (lRet);
}
////////////////////////////////////////////////////////////////////////////
//
// HbmpLoadBmp
//
// Loads in a bitmap.
//
// Returns: Bitmap handle - success
// HNULL - failure
//
////////////////////////////////////////////////////////////////////////////
#if 0
HBITMAP HbmpLoadBmp(
WORD bmp)
{
HBITMAP hbmp;
CHAR szBitmap[cbResNameMax];
hbmp = HNULL;
if (LoadString(g_hinst, bmp, (LPTSTR)szBitmap, cbResNameMax - 1))
{
hbmp = LoadBitmap(g_hinst, (LPCTSTR)szBitmap);
}
return (hbmp);
}
#endif
////////////////////////////////////////////////////////////////////////////
//
// AddNetButton
//
// Attempts to add a network button to the open, save, or print dialogs.
//
// hDlg - dialog to add button to
// hInstance - instance handle for dlg
// dyBottomMargin - DUs to bottom edge
//
////////////////////////////////////////////////////////////////////////////
#define xDUsToPels(DUs, lDlgBaseUnits) \
(int)(((DUs) * (int)LOWORD((lDlgBaseUnits))) / 4)
#define yDUsToPels(DUs, lDlgBaseUnits) \
(int)(((DUs) * (int)HIWORD((lDlgBaseUnits))) / 8)
VOID AddNetButton(
HWND hDlg,
HANDLE hInstance,
int dyBottomMargin,
BOOL bAddAccel,
BOOL bTryLowerRight,
BOOL bTryLowerLeft)
{
LONG lDlgBaseUnits;
RECT rcDlg, rcCtrl, rcTmp;
LONG xButton, yButton;
LONG dxButton, dyButton;
LONG dxDlgFrame, dyDlgFrame;
LONG yDlgHeight, xDlgWidth;
HWND hwndButton, hCtrl, hLastCtrl, hTmp, hSave;
HFONT hFont;
POINT ptTopLeft, ptTopRight, ptCenter, ptBtmLeft, ptBtmRight, ptTopLeftTmp;
TCHAR szNetwork[MAX_PATH];
//
// Make sure a network button (psh14) doesn't already exist in
// the dialog.
//
if (GetDlgItem(hDlg, psh14))
{
return;
}
//
// Get dialog coordinate info.
//
lDlgBaseUnits = GetDialogBaseUnits();
dxDlgFrame = GetSystemMetrics(SM_CXDLGFRAME);
dyDlgFrame = GetSystemMetrics(SM_CYDLGFRAME);
GetWindowRect(hDlg, &rcDlg);
rcDlg.left += dxDlgFrame;
rcDlg.right -= dxDlgFrame;
rcDlg.top += dyDlgFrame + GetSystemMetrics(SM_CYCAPTION);
rcDlg.bottom -= dyDlgFrame;
//
// Get the OK button.
//
if (!(hCtrl = GetDlgItem(hDlg, IDOK)))
{
return;
}
GetWindowRect(hCtrl, &rcCtrl);
ptTopLeft.x = rcCtrl.left;
ptTopLeft.y = rcCtrl.top;
//
// Make sure the OK button isn't outside the dialog.
//
if (!PtInRect(&rcDlg, ptTopLeft))
{
//
// Try the CANCEL button.
//
if (!(hCtrl = GetDlgItem(hDlg, IDCANCEL)))
{
//
// Both OK and CANCEL do not exist, so return.
//
return;
}
//
// The check for the Cancel button outside the dialog is handled
// below.
//
GetWindowRect(hCtrl, &rcCtrl);
}
hSave = hCtrl;
#ifdef UNICODE
//
// Get the full hDlg value if coming from WOW.
//
if (IS_INTRESOURCE(hDlg))
{
HWND hNewDlg = GetParent(hCtrl);
if (hDlg == (HWND)LOWORD(hNewDlg))
{
hDlg = hNewDlg;
}
}
#endif
//
// Save the coordinate info of the button.
//
dxButton = rcCtrl.right - rcCtrl.left;
dyButton = rcCtrl.bottom - rcCtrl.top;
xButton = rcCtrl.left;
yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
yDlgHeight = rcDlg.bottom - yDUsToPels(dyBottomMargin, lDlgBaseUnits);
//
// Try to insert the network button in the lower right corner
// of dialog box.
//
if (bTryLowerRight && (hTmp = GetDlgItem(hDlg, cmb2)))
{
//
// See if the network button can be inserted in the
// lower right corner of the dialog box.
//
hLastCtrl = hCtrl;
GetWindowRect(hTmp, &rcTmp);
yButton = rcTmp.top;
//
// Set the coordinates of the new button.
//
ptTopLeft.x = ptBtmLeft.x = xButton;
ptTopLeft.y = ptTopRight.y = yButton;
ptTopRight.x = ptBtmRight.x = xButton + dxButton;
ptBtmLeft.y = ptBtmRight.y = yButton + dyButton;
ptCenter.x = xButton + dxButton / 2;
ptCenter.y = yButton + dyButton / 2;
ScreenToClient(hDlg, (LPPOINT)&ptTopLeft);
ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft);
ScreenToClient(hDlg, (LPPOINT)&ptTopRight);
ScreenToClient(hDlg, (LPPOINT)&ptBtmRight);
ScreenToClient(hDlg, (LPPOINT)&ptCenter);
//
// See if the new button is over any other buttons.
//
if (((yButton + dyButton) < yDlgHeight) &&
((ChildWindowFromPoint(hDlg, ptTopLeft) == hDlg) &&
(ChildWindowFromPoint(hDlg, ptTopRight) == hDlg) &&
(ChildWindowFromPoint(hDlg, ptCenter) == hDlg) &&
(ChildWindowFromPoint(hDlg, ptBtmLeft) == hDlg) &&
(ChildWindowFromPoint(hDlg, ptBtmRight) == hDlg)))
{
//
// If the last control is the OK button and there is a
// HELP button, then the last control should be the
// HELP button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
(hCtrl = GetDlgItem(hDlg, pshHelp)))
{
GetWindowRect(hCtrl, &rcCtrl);
ptTopLeftTmp.x = rcCtrl.left;
ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the HELP button isn't outside the dialog
// and then set the last control to be the HELP button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp))
{
hLastCtrl = hCtrl;
}
}
//
// If the last control is still the OK button and there is a
// CANCEL button, then the last control should be the
// CANCEL button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
(hCtrl = GetDlgItem(hDlg, IDCANCEL)))
{
GetWindowRect(hCtrl, &rcCtrl);
ptTopLeftTmp.x = rcCtrl.left;
ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the CANCEL button isn't outside the dialog
// and then set the last control to be the CANCEL button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp))
{
hLastCtrl = hCtrl;
}
}
goto FoundPlace;
}
//
// Reset yButton.
//
yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
}
//
// Try to insert the network button vertically below the other
// control buttons.
//
while (hCtrl != NULL)
{
//
// Move vertically down and see if there is space.
//
hLastCtrl = hCtrl;
GetWindowRect(hCtrl, &rcCtrl);
yButton = rcCtrl.bottom + yDUsToPels(4, lDlgBaseUnits);
//
// Make sure there is still room in the dialog.
//
if ((yButton + dyButton) > yDlgHeight)
{
//
// No space.
//
break;
}
//
// Set the coordinates of the new button.
//
ptTopLeft.x = ptBtmLeft.x = xButton;
ptTopLeft.y = ptTopRight.y = yButton;
ptTopRight.x = ptBtmRight.x = xButton + dxButton;
ptBtmLeft.y = ptBtmRight.y = yButton + dyButton;
ptCenter.x = xButton + dxButton / 2;
ptCenter.y = yButton + dyButton / 2;
ScreenToClient(hDlg, (LPPOINT)&ptTopLeft);
ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft);
ScreenToClient(hDlg, (LPPOINT)&ptTopRight);
ScreenToClient(hDlg, (LPPOINT)&ptBtmRight);
ScreenToClient(hDlg, (LPPOINT)&ptCenter);
//
// See if the new button is over any other buttons.
//
if (((hCtrl = ChildWindowFromPoint(hDlg, ptTopLeft)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptTopRight)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptCenter)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptBtmLeft)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptBtmRight)) == hDlg))
{
goto FoundPlace;
}
}
//
// Try to insert the network button in the lower left corner of
// the dialog box.
//
if (bTryLowerLeft)
{
//
// Get the width of the dialog to make sure the button doesn't
// go off the side of the dialog.
//
xDlgWidth = rcDlg.right - xDUsToPels(FILE_RIGHT_MARGIN, lDlgBaseUnits);
//
// Use the OK or CANCEL button saved earlier to get the size of
// the buttons.
//
hCtrl = hSave;
//
// Start at the far left of the dialog.
//
// NOTE: We know that hCtrl is not NULL at this point because
// otherwise we would have returned earlier.
//
// The print dialogs have a left margin of 8.
//
GetWindowRect(hCtrl, &rcCtrl);
xButton = rcDlg.left + xDUsToPels(FILE_LEFT_MARGIN + 3, lDlgBaseUnits);
yButton = rcCtrl.top;
while (1)
{
hLastCtrl = hCtrl;
//
// Make sure there is still room in the dialog.
//
if ((xButton + dxButton) > xDlgWidth)
{
//
// No space.
//
break;
}
//
// Set the coordinates of the new button.
//
ptTopLeft.x = ptBtmLeft.x = xButton;
ptTopLeft.y = ptTopRight.y = yButton;
ptTopRight.x = ptBtmRight.x = xButton + dxButton;
ptBtmLeft.y = ptBtmRight.y = yButton + dyButton;
ptCenter.x = xButton + dxButton / 2;
ptCenter.y = yButton + dyButton / 2;
ScreenToClient(hDlg, (LPPOINT)&ptTopLeft);
ScreenToClient(hDlg, (LPPOINT)&ptBtmLeft);
ScreenToClient(hDlg, (LPPOINT)&ptTopRight);
ScreenToClient(hDlg, (LPPOINT)&ptBtmRight);
ScreenToClient(hDlg, (LPPOINT)&ptCenter);
//
// See if the new button is over any other buttons.
//
if ( ( ((hCtrl = ChildWindowFromPoint(hDlg, ptTopLeft)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptTopRight)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptCenter)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptBtmLeft)) == hDlg) &&
((hCtrl = ChildWindowFromPoint(hDlg, ptBtmRight)) == hDlg) ) )
{
//
// If the last control is the OK button and there is a
// HELP button, then the last control should be the
// HELP button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
(hCtrl = GetDlgItem(hDlg, pshHelp)))
{
GetWindowRect(hCtrl, &rcCtrl);
ptTopLeftTmp.x = rcCtrl.left;
ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the HELP button isn't outside the dialog
// and then set the last control to be the HELP button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp))
{
hLastCtrl = hCtrl;
}
}
//
// If the last control is still the OK button and there is a
// CANCEL button, then the last control should be the
// CANCEL button.
//
if ((hLastCtrl == GetDlgItem(hDlg, IDOK)) &&
(hCtrl = GetDlgItem(hDlg, IDCANCEL)))
{
GetWindowRect(hCtrl, &rcCtrl);
ptTopLeftTmp.x = rcCtrl.left;
ptTopLeftTmp.y = rcCtrl.top;
//
// Make sure the CANCEL button isn't outside the dialog
// and then set the last control to be the CANCEL button.
//
if (PtInRect(&rcDlg, ptTopLeftTmp))
{
hLastCtrl = hCtrl;
}
}
goto FoundPlace;
}
//
// Make sure we encountered another control and that we
// didn't go off the end of the dialog.
//
if (!hCtrl)
{
break;
}
//
// Move over to the right and see if there is space.
//
GetWindowRect(hCtrl, &rcCtrl);
xButton = rcCtrl.right + xDUsToPels(4, lDlgBaseUnits);
}
}
return;
FoundPlace:
xButton = ptTopLeft.x;
yButton = ptTopLeft.y;
//If it a mirrored Dlg then the direction will be to the right.
if (IS_WINDOW_RTL_MIRRORED(hDlg))
xButton -= dxButton;
#ifndef UNICODE
//
// For non-localized apps that don't include the network button as part
// of their template, don't add a Far East one because the characters
// will not be displayed correctly.
//
{
#define NetworkButtonText TEXT("Network...")
#define NetworkButtonTextAccel TEXT("Net&work...")
CPINFO cpinfo;
if ((GetCPInfo(CP_ACP, &cpinfo)) && (cpinfo.MaxCharSize > 1))
{
TEXTMETRIC tm;
HFONT hPrevFont;
HWND hIDOK = GetDlgItem(hDlg, IDOK);
HDC hDC = GetDC(hIDOK);
hFont = (HFONT)SendMessage(hIDOK, WM_GETFONT, 0, 0L);
if (hFont != NULL)
{
hPrevFont = SelectObject(hDC, hFont);
GetTextMetrics(hDC, &tm);
SelectObject(hDC, hPrevFont);
ReleaseDC(hIDOK, hDC);
if (tm.tmCharSet == ANSI_CHARSET)
{
lstrcpy( szNetwork,
bAddAccel ? NetworkButtonTextAccel : NetworkButtonText );
goto CreateNetworkButton;
}
}
}
}
#endif
if (CDLoadString( g_hinst,
(bAddAccel ? iszNetworkButtonTextAccel : iszNetworkButtonText),
(LPTSTR)szNetwork,
MAX_PATH ))
{
#ifndef UNICODE
CreateNetworkButton:
#endif
hwndButton = CreateWindow( TEXT("button"),
szNetwork,
WS_VISIBLE | WS_CHILD | WS_GROUP |
WS_TABSTOP | BS_PUSHBUTTON,
xButton,
yButton,
dxButton,
dyButton,
hDlg,
NULL,
hInstance,
NULL );
if (hwndButton != NULL)
{
SetWindowLong(hwndButton, GWL_ID, psh14);
SetWindowPos( hwndButton,
hLastCtrl,
0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );
hFont = (HFONT)SendDlgItemMessage(hDlg, IDOK, WM_GETFONT, 0, 0L);
SendMessage(hwndButton, WM_SETFONT, (WPARAM)hFont, MAKELPARAM(TRUE,0));
}
}
}
////////////////////////////////////////////////////////////////////////////
//
// IsNetworkInstalled
//
////////////////////////////////////////////////////////////////////////////
BOOL IsNetworkInstalled()
{
if (GetSystemMetrics(SM_NETWORK) & RNC_NETWORKS)
{
return (TRUE);
}
else
{
return (FALSE);
}
}
#ifdef WINNT
////////////////////////////////////////////////////////////////////////////
//
// Ssync_ANSI_UNICODE_Struct_For_WOW (This is exported for WOW)
//
// For WOW support on NT only.
//
// When a 16-bit app calls one of the comdlg API's, WOW thunks the 16-bit
// comdlg struct passed by the app to a 32-bit ANSI struct. Comdlg32 code
// then thunks the 32-bit ANSI struct into a UNICODE struct. This scheme
// creates a problem for WOW apps because on Win3.1, the app and comdlg16
// share the same structure. When either updates the struct, the other is
// aware of the change.
//
// This function allows us to sychronize the UNICODE struct with the app's
// 16-bit struct & vice versa from WOW.
//
////////////////////////////////////////////////////////////////////////////
VOID Ssync_ANSI_UNICODE_Struct_For_WOW(
HWND hDlg,
BOOL fDirection,
DWORD dwID)
{
switch (dwID)
{
case ( WOW_CHOOSECOLOR ) :
{
Ssync_ANSI_UNICODE_CC_For_WOW(hDlg, fDirection);
break;
}
case ( WOW_CHOOSEFONT ) :
{
Ssync_ANSI_UNICODE_CF_For_WOW(hDlg, fDirection);
break;
}
case ( WOW_OPENFILENAME ) :
{
Ssync_ANSI_UNICODE_OFN_For_WOW(hDlg, fDirection);
break;
}
case ( WOW_PRINTDLG ) :
{
Ssync_ANSI_UNICODE_PD_For_WOW(hDlg, fDirection);
break;
}
// case not needed for FINDREPLACE
}
}
#endif
#ifdef WX86
////////////////////////////////////////////////////////////////////////////
//
// Wx86GetX86Callback
//
// Creates a RISC-callable alias for a x86 hook function pointer.
//
// lpfnHook - x86 address of hook
//
// Returns a function pointer which can be called from RISC.
//
////////////////////////////////////////////////////////////////////////////
PVOID Wx86GetX86Callback(
PVOID lpfnHook)
{
if (!lpfnHook)
{
return (NULL);
}
if (!pfnAllocCallBx86)
{
HMODULE hMod;
if (!Wx86CurrentTib())
{
//
// Wx86 is not running in this thread. Assume a RISC app has
// passed a bad flag value and that lpfnHook is already a RISC
// function pointer.
//
return (lpfnHook);
}
hMod = GetModuleHandle(TEXT("wx86.dll"));
if (hMod == NULL)
{
//
// Wx86 is running, but wx86.dll is not loaded! This should
// never happen, but if it does, assume lpfnHook is already a
// RISC pointer.
//
return (lpfnHook);
}
pfnAllocCallBx86 = (PALLOCCALLBX86)GetProcAddress( hMod,
"AllocCallBx86" );
if (!pfnAllocCallBx86)
{
//
// Something has gone terribly wrong!
//
return (lpfnHook);
}
}
//
// Call into Wx86.dll to create a RISC-to-x86 callback which takes
// 4 parameters and has no logging.
//
return (*pfnAllocCallBx86)(lpfnHook, 4, NULL, NULL);
}
#endif
////////////////////////////////////////////////////////////////////////////
//
// CDLoadString
//
////////////////////////////////////////////////////////////////////////////
int CDLoadString(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax)
{
return CDLoadStringEx(CP_ACP, hInstance, uID, lpBuffer, nBufferMax);
}
// CDLoadStringEx takes a codepage, so we can store unicode strings in the resource file
int CDLoadStringEx(UINT cp, HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax)
{
HRSRC hResInfo;
int cch = 0;
LPWSTR lpwsz;
LANGID LangID;
if (!GET_BIDI_LOCALIZED_SYSTEM_LANGID(NULL)) {
#ifdef WINNT
return LoadString(hInstance, uID, lpBuffer, nBufferMax);
#else
lpwsz = (LPWSTR) LocalAlloc(NONZEROLPTR, nBufferMax * sizeof(WCHAR));
if (lpwsz)
{
int iRet;
LoadStringWrapW(hInstance, uID, lpwsz, nBufferMax);
iRet = WideCharToMultiByte(cp, 0, lpwsz, -1, lpBuffer, nBufferMax, NULL, NULL);
LocalFree(lpwsz);
return iRet;
}
return 0;
#endif
}
LangID = (LANGID)TlsGetValue(g_tlsLangID);
if (!LangID || MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) == LangID) {
return LoadString(hInstance, uID, lpBuffer, nBufferMax);
}
if (!lpBuffer || (nBufferMax-- == 0))
return 0;
// String Tables are broken up into 16 string resources. Find the resource
// containing the string we are interested in.
if (hResInfo = FindResourceExFallback(hInstance, RT_STRING, MAKEINTRESOURCE((uID>>4)+1), LangID)) {
// Load the resource. Note LoadResource returns an address.
if (lpwsz = (LPWSTR)LoadResource(hInstance, hResInfo)) {
// Move past the other strings in this resource.
// (16 strings in a segment -> & 0x0F)
for (uID %= 16; uID; uID--) {
lpwsz += *lpwsz + 1;
}
cch = min(*lpwsz, nBufferMax - 1);
#ifdef UNICODE
// Copy the string into the buffer;
memcpy(lpBuffer, lpwsz+1, cch*sizeof(WCHAR));
#else
// Copy the string into the buffer, converting to Ansi.
cch= WideCharToMultiByte( CP_ACP, 0, lpwsz+1, cch, lpBuffer, cch, NULL, NULL);
#endif
}
}
lpBuffer[cch] = 0;
return cch;
}
#define ENGLISH_APP 0
#define MIRRORED_APP 1
#define BIDI_APP 2
DWORD GetAppType(HWND hWnd) {
DWORD dwExStyle = 0;
HWND hWndT = hWnd;
DWORD dwAppType = ENGLISH_APP;
#ifdef CHECK_OWNER
//Check the window and its owners.
while (!dwExStyle && hWndT) {
dwExStyle = GetWindowLongA(hWndT, GWL_EXSTYLE) & (WS_EX_RIGHT | WS_EX_RTLREADING | RTL_MIRRORED_WINDOW);
hWndT = GetWindow(hWndT, GW_OWNER);
}
if (!dwExStyle) {
#endif
//If we still did not find then check the parents.
hWndT = hWnd;
while (!dwExStyle && hWndT) {
dwExStyle = GetWindowLongA(hWndT, GWL_EXSTYLE) & (WS_EX_RIGHT | WS_EX_RTLREADING | RTL_MIRRORED_WINDOW);
hWndT = GetParent(hWndT);
}
#ifdef CHECK_OWNER
}
#endif
if (dwExStyle & RTL_MIRRORED_WINDOW) {
dwAppType = MIRRORED_APP;
} else if (dwExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING)) {
dwAppType = BIDI_APP;
}
return dwAppType;
}
DWORD GetTemplateType(HANDLE hDlgTemplate)
{
DWORD dwExStyle = 0;
DWORD dwAppType = ENGLISH_APP;
LPDLGTEMPLATE pDlgTemplate;
pDlgTemplate = (LPDLGTEMPLATE)LockResource(hDlgTemplate);
if (pDlgTemplate) {
if (((LPDLGTEMPLATEEX) pDlgTemplate)->wSignature == 0xFFFF) {
dwExStyle = ((LPDLGTEMPLATEEX) pDlgTemplate)->dwExStyle;
} else {
dwExStyle = pDlgTemplate->dwExtendedStyle;
}
}
if (dwExStyle & RTL_MIRRORED_WINDOW) {
dwAppType = MIRRORED_APP;
} else if (dwExStyle & (WS_EX_RIGHT | WS_EX_RTLREADING)) {
dwAppType = BIDI_APP;
}
return dwAppType;
}
LANGID GetDialogLanguage(HWND hwndOwner, HANDLE hDlgTemplate)
{
LANGID LangID = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
DWORD dwType;
if (GET_BIDI_LOCALIZED_SYSTEM_LANGID(&LangID)) {
if (hDlgTemplate == NULL) {
dwType = GetAppType(hwndOwner);
} else {
dwType = GetTemplateType(hDlgTemplate);
}
switch (dwType) {
case ENGLISH_APP :
LangID = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
break;
case MIRRORED_APP:
LangID = MAKELANGID(PRIMARYLANGID(LangID), SUBLANG_DEFAULT);
break;
case BIDI_APP :
LangID = MAKELANGID(PRIMARYLANGID(LangID), SUBLANG_SYS_DEFAULT);
break;
}
}
return LangID;
}