You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
436 lines
12 KiB
436 lines
12 KiB
// Copyright (c) 1997-1999 Microsoft Corporation
|
|
#include "precomp.h"
|
|
|
|
#ifdef EXT_DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#include "util.h"
|
|
#include "shlwapi.h"
|
|
|
|
//----------------------------------------------------------------
|
|
HRESULT Extract(IDataObject *_DO, wchar_t* fmt, wchar_t* data)
|
|
{
|
|
HGLOBAL hMem = GlobalAlloc(GMEM_SHARE,1024);
|
|
wchar_t *pRet = NULL;
|
|
HRESULT hr = 0;
|
|
|
|
if(hMem != NULL)
|
|
{
|
|
memset(hMem, 0, 1024);
|
|
STGMEDIUM stgmedium = { TYMED_HGLOBAL, (HBITMAP) hMem};
|
|
|
|
CLIPFORMAT regFmt = (CLIPFORMAT)RegisterClipboardFormat(fmt);
|
|
|
|
FORMATETC formatetc = { regFmt,
|
|
NULL,
|
|
DVASPECT_CONTENT,
|
|
-1,
|
|
TYMED_HGLOBAL };
|
|
|
|
if((hr = _DO->GetDataHere(&formatetc, &stgmedium)) == S_OK )
|
|
{
|
|
wcscpy(data, (wchar_t*)hMem);
|
|
}
|
|
|
|
GlobalFree(hMem);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT Extract(IDataObject *_DO, wchar_t* fmt, bstr_t &data)
|
|
{
|
|
wchar_t temp[1024];
|
|
memset(temp, 0, 1024 * sizeof(wchar_t));
|
|
|
|
HRESULT hr = Extract(_DO, fmt, temp);
|
|
data = temp;
|
|
return hr;
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// FUNCTION: Int64ToString
|
|
//
|
|
// DESCRIPTION:
|
|
// Converts the numeric value of a _int64 to a text string.
|
|
// The string may optionally be formatted to include decimal places
|
|
// and commas according to current user locale settings.
|
|
//
|
|
// ARGUMENTS:
|
|
// n
|
|
// The 64-bit integer to format.
|
|
//
|
|
// szOutStr
|
|
// Address of the destination buffer.
|
|
//
|
|
// nSize
|
|
// Number of characters in the destination buffer.
|
|
//
|
|
// bFormat
|
|
// TRUE = Format per locale settings.
|
|
// FALSE = Leave number unformatted.
|
|
//
|
|
// pFmt
|
|
// Address of a number format structure of type NUMBERFMT.
|
|
// If NULL, the function automatically provides this information
|
|
// based on the user's default locale settings.
|
|
//
|
|
// dwNumFmtFlags
|
|
// Encoded flag word indicating which members of *pFmt to use in
|
|
// formatting the number. If a bit is clear, the user's default
|
|
// locale setting is used for the corresponding format value. These
|
|
// constants can be OR'd together.
|
|
//
|
|
// NUMFMT_IDIGITS
|
|
// NUMFMT_ILZERO
|
|
// NUMFMT_SGROUPING
|
|
// NUMFMT_SDECIMAL
|
|
// NUMFMT_STHOUSAND
|
|
// NUMFMT_INEGNUMBER
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
INT WINAPI Int64ToString(_int64 n, LPTSTR szOutStr, UINT nSize, BOOL bFormat,
|
|
NUMBERFMT *pFmt, DWORD dwNumFmtFlags)
|
|
{
|
|
INT nResultSize;
|
|
TCHAR szBuffer[_MAX_PATH + 1] = {0};
|
|
NUMBERFMT NumFmt;
|
|
TCHAR szDecimalSep[5] = {0};
|
|
TCHAR szThousandSep[5] = {0};
|
|
|
|
//
|
|
// Use only those fields in caller-provided NUMBERFMT structure
|
|
// that correspond to bits set in dwNumFmtFlags. If a bit is clear,
|
|
// get format value from locale info.
|
|
//
|
|
if (bFormat)
|
|
{
|
|
TCHAR szInfo[20] = {0};
|
|
|
|
if (NULL == pFmt)
|
|
dwNumFmtFlags = 0; // Get all format data from locale info.
|
|
|
|
if (dwNumFmtFlags & NUMFMT_IDIGITS)
|
|
{
|
|
NumFmt.NumDigits = pFmt->NumDigits;
|
|
}
|
|
else
|
|
{
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT,
|
|
LOCALE_IDIGITS,
|
|
szInfo,
|
|
ARRAYSIZE(szInfo));
|
|
_stscanf(szInfo, _T("%ld"), &(NumFmt.NumDigits));
|
|
|
|
// NumFmt.NumDigits = StrToLong(szInfo);
|
|
}
|
|
|
|
if (dwNumFmtFlags & NUMFMT_ILZERO)
|
|
{
|
|
NumFmt.LeadingZero = pFmt->LeadingZero;
|
|
}
|
|
else
|
|
{
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT,
|
|
LOCALE_ILZERO,
|
|
szInfo,
|
|
ARRAYSIZE(szInfo));
|
|
_stscanf(szInfo, _T("%ld"), &(NumFmt.LeadingZero));
|
|
|
|
// NumFmt.LeadingZero = StrToLong(szInfo);
|
|
}
|
|
|
|
if (dwNumFmtFlags & NUMFMT_SGROUPING)
|
|
{
|
|
NumFmt.Grouping = pFmt->Grouping;
|
|
}
|
|
else
|
|
{
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT,
|
|
LOCALE_SGROUPING,
|
|
szInfo,
|
|
ARRAYSIZE(szInfo));
|
|
_stscanf(szInfo, _T("%ld"), &(NumFmt.Grouping));
|
|
|
|
// NumFmt.Grouping = StrToLong(szInfo);
|
|
}
|
|
|
|
if (dwNumFmtFlags & NUMFMT_SDECIMAL)
|
|
{
|
|
NumFmt.lpDecimalSep = pFmt->lpDecimalSep;
|
|
}
|
|
else
|
|
{
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT,
|
|
LOCALE_SDECIMAL,
|
|
szDecimalSep,
|
|
ARRAYSIZE(szDecimalSep));
|
|
NumFmt.lpDecimalSep = szDecimalSep;
|
|
}
|
|
|
|
if (dwNumFmtFlags & NUMFMT_STHOUSAND)
|
|
{
|
|
NumFmt.lpThousandSep = pFmt->lpThousandSep;
|
|
}
|
|
else
|
|
{
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT,
|
|
LOCALE_STHOUSAND,
|
|
szThousandSep,
|
|
ARRAYSIZE(szThousandSep));
|
|
NumFmt.lpThousandSep = szThousandSep;
|
|
}
|
|
|
|
if (dwNumFmtFlags & NUMFMT_INEGNUMBER)
|
|
{
|
|
NumFmt.NegativeOrder = pFmt->NegativeOrder;
|
|
}
|
|
else
|
|
{
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT,
|
|
LOCALE_INEGNUMBER,
|
|
szInfo,
|
|
ARRAYSIZE(szInfo));
|
|
|
|
|
|
_stscanf(szInfo, _T("%ld"), &(NumFmt.NegativeOrder));
|
|
// NumFmt.NegativeOrder = StrToLong(szInfo);
|
|
}
|
|
|
|
pFmt = &NumFmt;
|
|
}
|
|
|
|
Int64ToStr( n, szBuffer);
|
|
|
|
//
|
|
// Format the number string for the locale if the caller wants a
|
|
// formatted number string.
|
|
//
|
|
if (bFormat)
|
|
{
|
|
if ( 0 != ( nResultSize = GetNumberFormat( LOCALE_USER_DEFAULT, // User's locale
|
|
0, // No flags
|
|
szBuffer, // Unformatted number string
|
|
pFmt, // Number format info
|
|
szOutStr, // Output buffer
|
|
nSize )) ) // Chars in output buffer.
|
|
{
|
|
// Remove nul terminator char from return size count.
|
|
--nResultSize;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// GetNumberFormat call failed, so just return the number string
|
|
// unformatted.
|
|
//
|
|
DWORD err = GetLastError();
|
|
lstrcpyn(szOutStr, szBuffer, nSize);
|
|
nResultSize = lstrlen(szOutStr);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// a-khint; give it back raw.
|
|
lstrcpyn(szOutStr, szBuffer, nSize);
|
|
nResultSize = lstrlen(szOutStr);
|
|
}
|
|
return nResultSize;
|
|
}
|
|
//---------------------------------------------------------------
|
|
void Int64ToStr( _int64 n, LPTSTR lpBuffer)
|
|
{
|
|
TCHAR szTemp[MAX_INT64_SIZE] = {0};
|
|
_int64 iChr;
|
|
|
|
iChr = 0;
|
|
|
|
do {
|
|
szTemp[iChr++] = TEXT('0') + (TCHAR)(n % 10);
|
|
n = n / 10;
|
|
} while (n != 0);
|
|
|
|
do {
|
|
iChr--;
|
|
*lpBuffer++ = szTemp[iChr];
|
|
} while (iChr != 0);
|
|
|
|
*lpBuffer++ = '\0';
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
// takes a DWORD add commas etc to it and puts the result in the buffer
|
|
LPTSTR WINAPI AddCommas64(_int64 n, LPTSTR pszResult)
|
|
{
|
|
TCHAR szTemp[MAX_COMMA_NUMBER_SIZE] = {0};
|
|
TCHAR szSep[5] = {0};
|
|
NUMBERFMT nfmt;
|
|
|
|
nfmt.NumDigits=0;
|
|
nfmt.LeadingZero=0;
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, ARRAYSIZE(szSep));
|
|
_stscanf(szSep, _T("%d"), &(nfmt.Grouping));
|
|
// nfmt.Grouping = StrToInt(szSep);
|
|
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, ARRAYSIZE(szSep));
|
|
nfmt.lpDecimalSep = nfmt.lpThousandSep = szSep;
|
|
nfmt.NegativeOrder= 0;
|
|
|
|
Int64ToStr(n, szTemp);
|
|
|
|
if (GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &nfmt, pszResult, ARRAYSIZE(szTemp)) == 0)
|
|
lstrcpy(pszResult, szTemp);
|
|
|
|
return pszResult;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// takes a DWORD add commas etc to it and puts the result in the buffer
|
|
LPTSTR WINAPI AddCommas(DWORD dw, LPTSTR pszResult)
|
|
{
|
|
return AddCommas64( dw, pszResult );
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
long StrToLong(LPTSTR x)
|
|
{
|
|
long val;
|
|
_stscanf(x, _T("%ld"), &val);
|
|
|
|
return val;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
/*
|
|
int StrToInt(LPTSTR x)
|
|
{
|
|
int val;
|
|
_stscanf(x, _T("%d"), &val);
|
|
|
|
return val;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
#define LEN_MID_ELLIPSES 4
|
|
#define LEN_END_ELLIPSES 3
|
|
#define MIN_CCHMAX LEN_MID_ELLIPSES + LEN_END_ELLIPSES
|
|
|
|
// PathCompactPathEx
|
|
// Output:
|
|
// "."
|
|
// ".."
|
|
// "..."
|
|
// "...\"
|
|
// "...\."
|
|
// "...\.."
|
|
// "...\..."
|
|
// "...\Truncated filename..."
|
|
// "...\whole filename"
|
|
// "Truncated path\...\whole filename"
|
|
// "Whole path\whole filename"
|
|
// The '/' might be used instead of a '\' if the original string used it
|
|
// If there is no path, but only a file name that does not fit, the output is:
|
|
// "truncated filename..."
|
|
|
|
BOOL MyPathCompactPathEx(LPTSTR pszOut,
|
|
LPCTSTR pszSrc,
|
|
UINT cchMax,
|
|
DWORD dwFlags)
|
|
{
|
|
if(pszSrc)
|
|
{
|
|
TCHAR * pszFileName, *pszWalk;
|
|
UINT uiFNLen = 0;
|
|
int cchToCopy = 0, n;
|
|
TCHAR chSlash = TEXT('0');
|
|
|
|
ZeroMemory(pszOut, cchMax * sizeof(TCHAR));
|
|
|
|
if((UINT)lstrlen(pszSrc)+1 < cchMax)
|
|
{
|
|
lstrcpy(pszOut, pszSrc);
|
|
ATLASSERT(pszOut[cchMax-1] == TEXT('\0'));
|
|
return TRUE;
|
|
}
|
|
|
|
// Determine what we use as a slash - a / or a \ (default \)
|
|
pszWalk = (TCHAR*)pszSrc;
|
|
chSlash = TEXT('\\');
|
|
// Scan the entire string as we want the path separator closest to the end
|
|
// eg. "file://\\Themesrv\desktop\desktop.htm"
|
|
while(*pszWalk)
|
|
{
|
|
if((*pszWalk == TEXT('/')) || (*pszWalk == TEXT('\\')))
|
|
chSlash = *pszWalk;
|
|
|
|
pszWalk = FAST_CharNext(pszWalk);
|
|
}
|
|
|
|
pszFileName = PathFindFileName(pszSrc);
|
|
uiFNLen = lstrlen(pszFileName);
|
|
|
|
// if the whole string is a file name
|
|
if(pszFileName == pszSrc && cchMax > LEN_END_ELLIPSES)
|
|
{
|
|
lstrcpyn(pszOut, pszSrc, cchMax - LEN_END_ELLIPSES);
|
|
#ifndef UNICODE
|
|
if(IsTrailByte(pszSrc, pszSrc+cchMax-LEN_END_ELLIPSES))
|
|
*(pszOut+cchMax-LEN_END_ELLIPSES-1) = TEXT('\0');
|
|
#endif
|
|
lstrcat(pszOut, TEXT("..."));
|
|
ASSERT(pszOut[cchMax-1] == TEXT('\0'));
|
|
return TRUE;
|
|
}
|
|
|
|
// Handle all the cases where we just use ellipses ie '.' to '.../...'
|
|
if((cchMax < MIN_CCHMAX))
|
|
{
|
|
for(n = 0; n < (int)cchMax-1; n++)
|
|
{
|
|
if((n+1) == LEN_MID_ELLIPSES)
|
|
pszOut[n] = chSlash;
|
|
else
|
|
pszOut[n] = TEXT('.');
|
|
}
|
|
ASSERT(0==cchMax || pszOut[cchMax-1] == TEXT('\0'));
|
|
return TRUE;
|
|
}
|
|
|
|
// Ok, how much of the path can we copy ? Buffer - (Lenght of MID_ELLIPSES + Len_Filename)
|
|
cchToCopy = cchMax - (LEN_MID_ELLIPSES + uiFNLen);
|
|
if (cchToCopy < 0)
|
|
cchToCopy = 0;
|
|
#ifndef UNICODE
|
|
if (cchToCopy > 0 && IsTrailByte(pszSrc, pszSrc+cchToCopy))
|
|
cchToCopy--;
|
|
#endif
|
|
|
|
lstrcpyn(pszOut, pszSrc, cchToCopy);
|
|
|
|
// Now throw in the ".../" or "...\"
|
|
lstrcat(pszOut, TEXT(".../"));
|
|
pszOut[lstrlen(pszOut) - 1] = chSlash;
|
|
|
|
//Finally the filename and ellipses if necessary
|
|
if(cchMax > (LEN_MID_ELLIPSES + uiFNLen))
|
|
{
|
|
lstrcat(pszOut, pszFileName);
|
|
}
|
|
else
|
|
{
|
|
cchToCopy = cchMax - LEN_MID_ELLIPSES - LEN_END_ELLIPSES;
|
|
#ifndef UNICODE
|
|
if(cchToCopy >0 && IsTrailByte(pszFileName, pszFileName+cchToCopy))
|
|
cchToCopy--;
|
|
#endif
|
|
lstrcpyn(pszOut + LEN_MID_ELLIPSES, pszFileName, cchToCopy);
|
|
lstrcat(pszOut, TEXT("..."));
|
|
}
|
|
ASSERT(pszOut[cchMax-1] == TEXT('\0'));
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
*/
|