932 lines
27 KiB
C++
932 lines
27 KiB
C++
// Copyright (c)1993-1997 Microsoft Corporation, All Rights Reserved
|
|
// Brian A. Moore
|
|
//
|
|
// This file is used for Mac only functions to assist in the Mac port of
|
|
// inetcomm.
|
|
// --------------------------------------------------------------------------------
|
|
#include "pch.hxx"
|
|
#ifdef MAC
|
|
#include "dllmain.h"
|
|
#include <stdio.h>
|
|
#include "resource.h"
|
|
|
|
#ifdef DEBUG
|
|
#define PRIVATE
|
|
#else // !DEBUG
|
|
#define PRIVATE static
|
|
#endif // DEBUG
|
|
|
|
#define HEX_ESCAPE L'%'
|
|
#define URL_ESCAPE_PERCENT 0x00001000
|
|
#define POUND L'#'
|
|
#define QUERY L'?'
|
|
|
|
#define TERMSTR(pch) *(pch) = L'\0'
|
|
|
|
PRIVATE CONST WORD isSafe[96] =
|
|
|
|
/* Bit 0 alphadigit -- 'a' to 'z', '0' to '9', 'A' to 'Z'
|
|
** Bit 1 Hex -- '0' to '9', 'a' to 'f', 'A' to 'F'
|
|
** Bit 2 valid scheme -- alphadigit | "-" | "." | "+"
|
|
** Bit 3 mark -- "%" | "$"| "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" | ","
|
|
*/
|
|
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
|
// {0, 8, 0, 0, 8, 8, 0, 8, 8, 8, 8, 4, 8,12,12, 0, /* 2x !"#$%&'()*+,-./ */
|
|
// IE4 BETA1: allow + through unmolested. Should consider other options
|
|
// post beta1. 12feb97 tonyci
|
|
{0, 8, 0, 0, 8, 8, 0, 8, 8, 8, 8, 12, 8,12,12, 0, /* 2x !"#$%&'()*+,-./ */
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 8, 8, 0, 8, 0, 0, /* 3x 0123456789:;<=>? */
|
|
8, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x @ABCDEFGHIJKLMNO */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 8, /* 5X PQRSTUVWXYZ[\]^_ */
|
|
0, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x `abcdefghijklmno */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 8, 0}; /* 7X pqrstuvwxyz{|}~ DEL */
|
|
|
|
PRIVATE const WCHAR hex[] = {L"0123456789ABCDEF"};
|
|
|
|
PRIVATE inline BOOL IsSafe(WCHAR ch, WORD mask)
|
|
{
|
|
if(ch > 31 && ch < 128 && (isSafe[ch - 32] & mask))
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#define IsAlphaDigit(c) IsSafe(c, 1)
|
|
#define IsHex(c) IsSafe(c, 2)
|
|
#define IsValidSchemeCharA(c) IsSafe(c, 5)
|
|
#define IsSafePathChar(c) IsSafe(c, 9)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Line Break Character Table
|
|
|
|
const WCHAR MAC_awchNonBreakingAtLineEnd[] = {
|
|
0x0028, // LEFT PARENTHESIS
|
|
0x005B, // LEFT SQUARE BRACKET
|
|
0x007B, // LEFT CURLY BRACKET
|
|
0x00AB, // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
|
|
0x2018, // LEFT SINGLE QUOTATION MARK
|
|
0x201C, // LEFT DOUBLE QUOTATION MARK
|
|
0x2039, // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
|
|
0x2045, // LEFT SQUARE BRACKET WITH QUILL
|
|
0x207D, // SUPERSCRIPT LEFT PARENTHESIS
|
|
0x208D, // SUBSCRIPT LEFT PARENTHESIS
|
|
0x226A, // MUCH LESS THAN
|
|
0x3008, // LEFT ANGLE BRACKET
|
|
0x300A, // LEFT DOUBLE ANGLE BRACKET
|
|
0x300C, // LEFT CORNER BRACKET
|
|
0x300E, // LEFT WHITE CORNER BRACKET
|
|
0x3010, // LEFT BLACK LENTICULAR BRACKET
|
|
0x3014, // LEFT TORTOISE SHELL BRACKET
|
|
0x3016, // LEFT WHITE LENTICULAR BRACKET
|
|
0x3018, // LEFT WHITE TORTOISE SHELL BRACKET
|
|
0x301A, // LEFT WHITE SQUARE BRACKET
|
|
0x301D, // REVERSED DOUBLE PRIME QUOTATION MARK
|
|
0xFD3E, // ORNATE LEFT PARENTHESIS
|
|
0xFE35, // PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
|
|
0xFE37, // PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
|
|
0xFE39, // PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
|
|
0xFE3B, // PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
|
|
0xFE3D, // PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
|
|
0xFE3F, // PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
|
|
0xFE41, // PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
|
|
0xFE43, // PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
|
|
0xFE59, // SMALL LEFT PARENTHESIS
|
|
0xFE5B, // SMALL LEFT CURLY BRACKET
|
|
0xFE5D, // SMALL LEFT TORTOISE SHELL BRACKET
|
|
0xFF08, // FULLWIDTH LEFT PARENTHESIS
|
|
0xFF1C, // FULLWIDTH LESS-THAN SIGN
|
|
0xFF3B, // FULLWIDTH LEFT SQUARE BRACKET
|
|
0xFF5B, // FULLWIDTH LEFT CURLY BRACKET
|
|
0xFF62, // HALFWIDTH LEFT CORNER BRACKET
|
|
0xFFE9 // HALFWIDTH LEFTWARDS ARROW
|
|
};
|
|
|
|
const WCHAR MAC_awchNonBreakingAtLineStart[] = {
|
|
0x0029, // RIGHT PARENTHESIS
|
|
0x002D, // HYPHEN
|
|
0x005D, // RIGHT SQUARE BRACKET
|
|
0x007D, // RIGHT CURLY BRACKET
|
|
0x00AD, // OPTIONAL HYPHEN
|
|
0x00BB, // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
|
|
0x02C7, // CARON
|
|
0x02C9, // MODIFIER LETTER MACRON
|
|
0x055D, // ARMENIAN COMMA
|
|
0x060C, // ARABIC COMMA
|
|
0x2013, // EN DASH
|
|
0x2014, // EM DASH
|
|
0x2016, // DOUBLE VERTICAL LINE
|
|
0x201D, // RIGHT DOUBLE QUOTATION MARK
|
|
0x2022, // BULLET
|
|
0x2025, // TWO DOT LEADER
|
|
0x2026, // HORIZONTAL ELLIPSIS
|
|
0x2027, // HYPHENATION POINT
|
|
0x203A, // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
|
|
0x2046, // RIGHT SQUARE BRACKET WITH QUILL
|
|
0x207E, // SUPERSCRIPT RIGHT PARENTHESIS
|
|
0x208E, // SUBSCRIPT RIGHT PARENTHESIS
|
|
0x226B, // MUCH GREATER THAN
|
|
0x2574, // BOX DRAWINGS LIGHT LEFT
|
|
0x3001, // IDEOGRAPHIC COMMA
|
|
0x3002, // IDEOGRAPHIC FULL STOP
|
|
0x3003, // DITTO MARK
|
|
0x3005, // IDEOGRAPHIC ITERATION MARK
|
|
0x3009, // RIGHT ANGLE BRACKET
|
|
0x300B, // RIGHT DOUBLE ANGLE BRACKET
|
|
0x300D, // RIGHT CORNER BRACKET
|
|
0x300F, // RIGHT WHITE CORNER BRACKET
|
|
0x3011, // RIGHT BLACK LENTICULAR BRACKET
|
|
0x3015, // RIGHT TORTOISE SHELL BRACKET
|
|
0x3017, // RIGHT WHITE LENTICULAR BRACKET
|
|
0x3019, // RIGHT WHITE TORTOISE SHELL BRACKET
|
|
0x301B, // RIGHT WHITE SQUARE BRACKET
|
|
0x301E, // DOUBLE PRIME QUOTATION MARK
|
|
0x3041, // HIRAGANA LETTER SMALL A
|
|
0x3043, // HIRAGANA LETTER SMALL I
|
|
0x3045, // HIRAGANA LETTER SMALL U
|
|
0x3047, // HIRAGANA LETTER SMALL E
|
|
0x3049, // HIRAGANA LETTER SMALL O
|
|
0x3063, // HIRAGANA LETTER SMALL TU
|
|
0x3083, // HIRAGANA LETTER SMALL YA
|
|
0x3085, // HIRAGANA LETTER SMALL YU
|
|
0x3087, // HIRAGANA LETTER SMALL YO
|
|
0x308E, // HIRAGANA LETTER SMALL WA
|
|
0x309B, // KATAKANA-HIRAGANA VOICED SOUND MARK
|
|
0x309C, // KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
|
|
0x309D, // HIRAGANA ITERATION MARK
|
|
0x309E, // HIRAGANA VOICED ITERATION MARK
|
|
0x30A1, // KATAKANA LETTER SMALL A
|
|
0x30A3, // KATAKANA LETTER SMALL I
|
|
0x30A5, // KATAKANA LETTER SMALL U
|
|
0x30A7, // KATAKANA LETTER SMALL E
|
|
0x30A9, // KATAKANA LETTER SMALL O
|
|
0x30C3, // KATAKANA LETTER SMALL TU
|
|
0x30E3, // KATAKANA LETTER SMALL YA
|
|
0x30E5, // KATAKANA LETTER SMALL YU
|
|
0x30E7, // KATAKANA LETTER SMALL YO
|
|
0x30EE, // KATAKANA LETTER SMALL WA
|
|
0x30F5, // KATAKANA LETTER SMALL KA
|
|
0x30F6, // KATAKANA LETTER SMALL KE
|
|
0x30FC, // KATAKANA-HIRAGANA PROLONGED SOUND MARK
|
|
0x30FD, // KATAKANA ITERATION MARK
|
|
0x30FE, // KATAKANA VOICED ITERATION MARK
|
|
0xFD3F, // ORNATE RIGHT PARENTHESIS
|
|
0xFE30, // VERTICAL TWO DOT LEADER
|
|
0xFE31, // VERTICAL EM DASH
|
|
0xFE33, // VERTICAL LOW LINE
|
|
0xFE34, // VERTICAL WAVY LOW LINE
|
|
0xFE36, // PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
|
|
0xFE38, // PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
|
|
0xFE3A, // PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
|
|
0xFE3C, // PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
|
|
0xFE3E, // PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
|
|
0xFE40, // PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
|
|
0xFE42, // PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
|
|
0xFE44, // PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
|
|
0xFE4F, // WAVY LOW LINE
|
|
0xFE50, // SMALL COMMA
|
|
0xFE51, // SMALL IDEOGRAPHIC COMMA
|
|
0xFE5A, // SMALL RIGHT PARENTHESIS
|
|
0xFE5C, // SMALL RIGHT CURLY BRACKET
|
|
0xFE5E, // SMALL RIGHT TORTOISE SHELL BRACKET
|
|
0xFF09, // FULLWIDTH RIGHT PARENTHESIS
|
|
0xFF0C, // FULLWIDTH COMMA
|
|
0xFF0E, // FULLWIDTH FULL STOP
|
|
0xFF1E, // FULLWIDTH GREATER-THAN SIGN
|
|
0xFF3D, // FULLWIDTH RIGHT SQUARE BRACKET
|
|
0xFF40, // FULLWIDTH GRAVE ACCENT
|
|
0xFF5C, // FULLWIDTH VERTICAL LINE
|
|
0xFF5D, // FULLWIDTH RIGHT CURLY BRACKET
|
|
0xFF5E, // FULLWIDTH TILDE
|
|
0xFF61, // HALFWIDTH IDEOGRAPHIC FULL STOP
|
|
0xFF63, // HALFWIDTH RIGHT CORNER BRACKET
|
|
0xFF64, // HALFWIDTH IDEOGRAPHIC COMMA
|
|
0xFF67, // HALFWIDTH KATAKANA LETTER SMALL A
|
|
0xFF68, // HALFWIDTH KATAKANA LETTER SMALL I
|
|
0xFF69, // HALFWIDTH KATAKANA LETTER SMALL U
|
|
0xFF6A, // HALFWIDTH KATAKANA LETTER SMALL E
|
|
0xFF6B, // HALFWIDTH KATAKANA LETTER SMALL O
|
|
0xFF6C, // HALFWIDTH KATAKANA LETTER SMALL YA
|
|
0xFF6D, // HALFWIDTH KATAKANA LETTER SMALL YU
|
|
0xFF6E, // HALFWIDTH KATAKANA LETTER SMALL YO
|
|
0xFF6F, // HALFWIDTH KATAKANA LETTER SMALL TU
|
|
0xFF70, // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
|
|
0xFF9E, // HALFWIDTH KATAKANA VOICED SOUND MARK
|
|
0xFF9F, // HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
|
|
0xFFEB // HALFWIDTH RIGHTWARDS ARROW
|
|
};
|
|
|
|
const WCHAR MAC_awchRomanInterWordSpace[] = {
|
|
0x0009, // TAB
|
|
0x0020, // SPACE
|
|
0x2002, // EN SPACE
|
|
0x2003, // EM SPACE
|
|
0x2004, // THREE-PER-EM SPACE
|
|
0x2005, // FOUR-PER-EM SPACE
|
|
0x2006, // SIX-PER-EM SPACE
|
|
0x2007, // FIGURE SPACE
|
|
0x2008, // PUNCTUATION SPACE
|
|
0x2009, // THIN SPACE
|
|
0x200A, // HAIR SPACE
|
|
0x200B // ZERO WIDTH SPACE
|
|
};
|
|
|
|
BOOL MAC_ScanWChar(const WCHAR awch[], int nArraySize, WCHAR wch)
|
|
{
|
|
int iMin = 0;
|
|
int iMax = nArraySize - 1;
|
|
|
|
while (iMax - iMin >= 2)
|
|
{
|
|
int iTry = (iMax + iMin + 1) / 2;
|
|
if (wch < awch[iTry])
|
|
iMax = iTry;
|
|
else if (wch > awch[iTry])
|
|
iMin = iTry;
|
|
else
|
|
return TRUE;
|
|
}
|
|
|
|
return (wch == awch[iMin] || wch == awch[iMax]);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Mac_StrStrIA
|
|
// --------------------------------------------------------------------------------
|
|
STDAPI_(LPSTR) Mac_StrStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
|
|
{
|
|
LPSTR lpFirstI;
|
|
LPSTR lpSrchI;
|
|
LPSTR lpRet;
|
|
|
|
if ((NULL == lpFirst) || (NULL == lpSrch))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
lpFirstI = StrDupA(lpFirst);
|
|
lpSrchI = StrDupA(lpSrch);
|
|
|
|
lpRet = StrStr(lpFirstI, lpSrchI);
|
|
|
|
SafeMemFree(lpFirstI);
|
|
SafeMemFree(lpSrchI);
|
|
|
|
return lpRet;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MAC_StrFormatByteSize
|
|
// --------------------------------------------------------------------------------
|
|
LPSTR MAC_StrFormatByteSize(DWORD dw, LPSTR szBuf, UINT uiBufSize)
|
|
{
|
|
CHAR szUnit[15];
|
|
|
|
szUnit[0] = '\0';
|
|
if (dw > 1024)
|
|
{
|
|
LoadString(g_hLocRes, idsBytes, szUnit, ARRAYSIZE(szUnit));
|
|
_snprintf(szBuf, uiBufSize, szUnit, dw);
|
|
}
|
|
else
|
|
{
|
|
LoadString(g_hLocRes, idsKilo, szUnit, ARRAYSIZE(szUnit));
|
|
_snprintf(szBuf, uiBufSize, szUnit, (ULONG) (dw / 1024));
|
|
}
|
|
|
|
return szBuf;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MAC_PathFindExtension
|
|
// --------------------------------------------------------------------------------
|
|
STDAPI_(LPSTR) MAC_PathFindExtension(LPCSTR pszPath)
|
|
{
|
|
LPSTR pszWalk;
|
|
LPSTR pszFileName = (LPSTR) pszPath;
|
|
LPSTR pszLastDot = NULL;
|
|
|
|
for (pszWalk = (LPSTR) pszPath; *pszWalk != '\0'; pszWalk++)
|
|
{
|
|
// $REVIEW: Should we be looking for Macintosh directories
|
|
// or Windows directories???
|
|
if (':' == *pszWalk)
|
|
{
|
|
// Point to the character after the seperator
|
|
// because that might be the start of the file name
|
|
pszFileName = pszWalk + 1;
|
|
}
|
|
else if ('.' == *pszWalk)
|
|
{
|
|
pszLastDot = pszWalk;
|
|
}
|
|
}
|
|
|
|
if (pszLastDot < pszFileName)
|
|
{
|
|
pszLastDot = pszWalk;
|
|
}
|
|
|
|
return pszLastDot;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MAC_PathFindFileName
|
|
// --------------------------------------------------------------------------------
|
|
STDAPI_(LPSTR) MAC_PathFindFileName(LPCSTR pszPath)
|
|
{
|
|
LPSTR pszWalk;
|
|
LPSTR pszFileName = (LPSTR) pszPath;
|
|
|
|
for (pszWalk = (LPSTR) pszPath; *pszWalk != '\0'; pszWalk++)
|
|
{
|
|
// $REVIEW: Should we be looking for Macintosh directories
|
|
// or Windows directories???
|
|
if (':' == *pszWalk)
|
|
{
|
|
// Point to the character after the seperator
|
|
// because that might be the start of the file name
|
|
pszFileName = pszWalk + 1;
|
|
}
|
|
}
|
|
|
|
return pszFileName;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MAC_BreakLineW
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT MAC_BreakLineW(LCID locale, const WCHAR* pszSrc, long cchSrc,
|
|
long cMaxColumns, long* pcchLine, long* pcchSkip)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
long cColumns = 0;
|
|
long lCandPos;
|
|
long lBreakPos = -1;
|
|
long lSkipLen = 0;
|
|
struct {
|
|
unsigned fDone : 1;
|
|
unsigned fInSpaces : 1;
|
|
unsigned fFEChar : 1;
|
|
unsigned fInFEChar : 1;
|
|
unsigned fBreakByEndOfLine : 1;
|
|
unsigned fNonBreakNext : 1;
|
|
unsigned fHaveCandPos : 1;
|
|
unsigned fSlashR : 1;
|
|
} Flags = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
|
locale; // Not used yet...
|
|
|
|
// While we still have characters left
|
|
for (int iCh = 0; iCh < cchSrc; iCh++)
|
|
{
|
|
const WCHAR wch = pszSrc[iCh];
|
|
|
|
if (wch == wchCR && !Flags.fSlashR)
|
|
{
|
|
Flags.fSlashR = TRUE;
|
|
}
|
|
else if (wch == wchLF || Flags.fSlashR) // End of line
|
|
{
|
|
Flags.fDone = TRUE;
|
|
Flags.fBreakByEndOfLine = TRUE;
|
|
if (Flags.fInSpaces)
|
|
{
|
|
Flags.fHaveCandPos = FALSE;
|
|
lBreakPos = lCandPos;
|
|
lSkipLen++; // Skip spaces and line break character
|
|
}
|
|
else
|
|
{
|
|
lBreakPos = iCh; // Break at right before the end of line
|
|
if (Flags.fSlashR)
|
|
lBreakPos--;
|
|
|
|
lSkipLen = 1; // Skip line break character
|
|
}
|
|
if (wch == wchLF && Flags.fSlashR)
|
|
lSkipLen++;
|
|
break;
|
|
}
|
|
else if (MAC_ScanWChar(MAC_awchRomanInterWordSpace, ARRAYSIZE(MAC_awchRomanInterWordSpace), wch)) // Spaces
|
|
{
|
|
if (!Flags.fInSpaces && !Flags.fNonBreakNext)
|
|
{
|
|
Flags.fHaveCandPos = TRUE;
|
|
lCandPos = iCh; // Break at right before the spaces
|
|
lSkipLen = 0;
|
|
}
|
|
Flags.fInSpaces = TRUE;
|
|
lSkipLen++; // Skip continuous spaces after breaking
|
|
}
|
|
else // Other characters
|
|
{
|
|
// Don't use this code. We'll pick it up when MLANG is ported.
|
|
#ifdef NEVER
|
|
Flags.fFEChar = ((wCharType3 & (C3_KATAKANA | C3_HIRAGANA | C3_FULLWIDTH | C3_IDEOGRAPH)) != 0);
|
|
|
|
if ((Flags.fFEChar || Flags.fInFEChar) && !Flags.fNonBreakNext && !Flags.fInSpaces)
|
|
{
|
|
Flags.fHaveCandPos = TRUE;
|
|
lCandPos = lSrcPosTemp + iCh; // Break at right before or after the FE char
|
|
lSkipLen = 0;
|
|
}
|
|
Flags.fInFEChar = Flags.fFEChar;
|
|
#endif // NEVER
|
|
Flags.fInSpaces = FALSE;
|
|
|
|
if (Flags.fHaveCandPos)
|
|
{
|
|
Flags.fHaveCandPos = FALSE;
|
|
if (!MAC_ScanWChar(MAC_awchNonBreakingAtLineStart, ARRAYSIZE(MAC_awchNonBreakingAtLineStart), wch))
|
|
lBreakPos = lCandPos;
|
|
}
|
|
|
|
if (cColumns + 1 > cMaxColumns)
|
|
{
|
|
Flags.fDone = TRUE;
|
|
break;
|
|
}
|
|
|
|
Flags.fNonBreakNext = MAC_ScanWChar(MAC_awchNonBreakingAtLineEnd, ARRAYSIZE(MAC_awchNonBreakingAtLineEnd), wch);
|
|
}
|
|
|
|
cColumns++;
|
|
}
|
|
|
|
if (Flags.fHaveCandPos)
|
|
lBreakPos = lCandPos;
|
|
|
|
if (!Flags.fBreakByEndOfLine && lBreakPos < 0)
|
|
{
|
|
lBreakPos = min(cchSrc, cMaxColumns); // Default breaking
|
|
lSkipLen = 0;
|
|
}
|
|
|
|
if (!Flags.fDone)
|
|
{
|
|
if (Flags.fInSpaces)
|
|
{
|
|
lBreakPos = cchSrc - lSkipLen;
|
|
}
|
|
else
|
|
{
|
|
lBreakPos = cchSrc;
|
|
lSkipLen = 0;
|
|
}
|
|
if (Flags.fSlashR)
|
|
{
|
|
lBreakPos--;
|
|
lSkipLen++;
|
|
}
|
|
}
|
|
|
|
if (pcchLine)
|
|
*pcchLine = lBreakPos;
|
|
if (pcchSkip)
|
|
*pcchSkip = lSkipLen;
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// MAC_BreakLineA
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT MAC_BreakLineA(LCID locale, UINT uCodePage, const CHAR* pszSrc, long cchSrc,
|
|
long cMaxColumns, long* pcchLine, long* pcchSkip)
|
|
{
|
|
HRESULT hr;
|
|
LPWSTR wszBuff = NULL;
|
|
long cchLineTemp;
|
|
long cchSkipTemp;
|
|
int cwch;
|
|
|
|
// Check parameters
|
|
if ((NULL == pszSrc) || (cMaxColumns < 0))
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
if (0 == cchSrc)
|
|
{
|
|
hr = S_OK;
|
|
if (pcchLine)
|
|
{
|
|
*pcchLine = 0;
|
|
}
|
|
|
|
if (pcchSkip)
|
|
{
|
|
*pcchSkip = 0;
|
|
}
|
|
|
|
goto exit;
|
|
}
|
|
|
|
cwch = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, pszSrc, cchSrc, NULL, NULL);
|
|
if (!cwch)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
CHECKALLOC(wszBuff = (LPWSTR)g_pMalloc->Alloc(cwch * sizeof(WCHAR)));
|
|
|
|
cwch = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, pszSrc, cchSrc, wszBuff, cwch);
|
|
Assert(cwch);
|
|
|
|
CHECKHR(hr = MAC_BreakLineW(locale, wszBuff, cwch, cMaxColumns, &cchLineTemp, &cchSkipTemp));
|
|
|
|
if (pcchLine)
|
|
{
|
|
if (cchLineTemp != 0)
|
|
{
|
|
*pcchLine = WideCharToMultiByte(uCodePage, 0, wszBuff, cchLineTemp, NULL, 0, NULL, NULL);
|
|
} else
|
|
{
|
|
*pcchLine = 0;
|
|
}
|
|
}
|
|
|
|
if (pcchSkip)
|
|
{
|
|
*pcchSkip = WideCharToMultiByte(uCodePage, 0, wszBuff + cchLineTemp, cchSkipTemp, NULL, 0, NULL, NULL);
|
|
}
|
|
|
|
exit:
|
|
|
|
SafeMemFree(wszBuff);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------
|
|
// MAC_IsConvertINetStringAvailable
|
|
//---------------------------------------------------------------------------------
|
|
STDAPI MAC_IsConvertINetStringAvailable(DWORD dwSrcEncoding, DWORD dwDstEncoding)
|
|
{
|
|
HRESULT hrResult = S_OK;
|
|
|
|
if (!(IsValidCodePage(dwSrcEncoding) && IsValidCodePage(dwDstEncoding)))
|
|
{
|
|
hrResult = S_FALSE;
|
|
}
|
|
|
|
return hrResult;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------------
|
|
// MAC_ConvertINetString
|
|
//---------------------------------------------------------------------------------
|
|
STDAPI MAC_ConvertINetString(LPDWORD lpdwMode, DWORD dwSrcEncoding, DWORD dwDstEncoding,
|
|
LPCSTR lpSrcStr, LPINT lpnSrcSize, LPSTR lpDstStr, LPINT lpnDstSize)
|
|
{
|
|
HRESULT hrResult;
|
|
INT cch;
|
|
INT cwch;
|
|
INT cchSrcSize;
|
|
INT cchDstSize;
|
|
LPWSTR pwsz = NULL;
|
|
|
|
// Check parameters....
|
|
if (lpdwMode)
|
|
{
|
|
AssertSz(FALSE, "We don't support any variations");
|
|
hrResult = E_FAIL;
|
|
cchDstSize = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if ((!lpSrcStr) || (FALSE == IsValidCodePage(dwSrcEncoding)) || (FALSE == IsValidCodePage(dwDstEncoding)))
|
|
{
|
|
hrResult = E_FAIL;
|
|
cchDstSize = 0;
|
|
goto exit;
|
|
}
|
|
|
|
if(lpnSrcSize)
|
|
{
|
|
cchSrcSize = *lpnSrcSize;
|
|
}
|
|
else
|
|
{
|
|
cchSrcSize = -1;
|
|
}
|
|
|
|
if(!lpDstStr)
|
|
{
|
|
cchDstSize = 0;
|
|
}
|
|
else if (lpnDstSize)
|
|
{
|
|
cchDstSize = *lpnDstSize;
|
|
}
|
|
else
|
|
{
|
|
cchDstSize = 0;
|
|
}
|
|
|
|
if (-1 == cchSrcSize)
|
|
{
|
|
AssertSz(FALSE, "We don't support any variations");
|
|
hrResult = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Allocate the buffer
|
|
hrResult = HrAlloc((LPVOID *)&pwsz, cchSrcSize * sizeof(WCHAR));
|
|
if (FAILED(hrResult))
|
|
goto exit;
|
|
|
|
cwch = MultiByteToWideChar(dwSrcEncoding, MB_PRECOMPOSED, lpSrcStr,
|
|
cchSrcSize, pwsz, cchSrcSize * sizeof(WCHAR));
|
|
if (0 == cwch)
|
|
{
|
|
hrResult = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
cchDstSize = WideCharToMultiByte(dwDstEncoding, 0, pwsz, cwch, lpDstStr, cchDstSize, NULL, NULL);
|
|
if (0 == cchDstSize)
|
|
{
|
|
hrResult = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
if (lpnDstSize)
|
|
{
|
|
*lpnDstSize = cchDstSize;
|
|
}
|
|
|
|
SafeMemFree(pwsz);
|
|
|
|
return hrResult;
|
|
}
|
|
|
|
STDAPI MAC_CoInternetCombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
|
|
LPWSTR pszResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
|
|
{
|
|
UINT cchSizeNeeded = 0;
|
|
UINT cchBaseUrl;
|
|
HRESULT hr;
|
|
LPWSTR pwzTempUrl;
|
|
|
|
// Check the parameters
|
|
if ((!pwzBaseUrl) || dwCombineFlags || dwReserved)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Do we have enough room for the string?
|
|
cchBaseUrl = lstrlenW(pwzBaseUrl);
|
|
cchSizeNeeded = cchBaseUrl + lstrlenW(pwzRelativeUrl) + 1;
|
|
|
|
// Add one for the connecting '\' or subtract one if we have too many...
|
|
if ((L'/' != pwzBaseUrl[cchBaseUrl]) && (L'/' != pwzRelativeUrl[0]))
|
|
{
|
|
cchSizeNeeded++;
|
|
}
|
|
else if ((L'/' == pwzBaseUrl[cchBaseUrl]) && (L'/' == pwzRelativeUrl[0]))
|
|
{
|
|
cchSizeNeeded--;
|
|
}
|
|
|
|
if (cchSizeNeeded < cchResult)
|
|
{
|
|
hr = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
// Copy the base url
|
|
wcscpy(pszResult, pwzBaseUrl);
|
|
|
|
// Do we need a ending slash?
|
|
if (L'/' != pwzBaseUrl[cchBaseUrl])
|
|
{
|
|
pszResult[cchBaseUrl + 1] = L'/';
|
|
}
|
|
|
|
// concatenate relative url
|
|
wcscat(pszResult, ((L'/' == pwzRelativeUrl[0]) ? pwzRelativeUrl + 1: pwzRelativeUrl));
|
|
|
|
hr = S_OK;
|
|
|
|
exit:
|
|
// set count of result buffer
|
|
if (pcchResult)
|
|
{
|
|
*pcchResult = cchSizeNeeded;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Mac_SzGetLocalPackedIP
|
|
// --------------------------------------------------------------------------------
|
|
LPSTR Mac_SzGetLocalPackedIP(void)
|
|
{
|
|
return "127.0.0.1";
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Mac_SzGetLocalHostNameForID
|
|
// --------------------------------------------------------------------------------
|
|
LPSTR Mac_SzGetLocalHostNameForID(void)
|
|
{
|
|
return "localhost";
|
|
}
|
|
|
|
/*+++
|
|
|
|
SHUrlUnescape()
|
|
Unescapes a string in place. this is ok because
|
|
it should never grow
|
|
|
|
Parameters
|
|
IN -
|
|
psz string to unescape inplace
|
|
dwFlags the relevant URL_* flags,
|
|
|
|
Returns
|
|
HRESULT -
|
|
SUCCESS S_OK
|
|
ERROR DOESNT error right now
|
|
|
|
|
|
Helper Routines
|
|
HexToWord takes a hexdigit and returns WORD with the right number or -1
|
|
IsEscapedChar looks at a ptr for "%XX" where X is a hexdigit
|
|
TranslateEscapedChar translates "%XX" to an 8 bit char
|
|
---*/
|
|
|
|
PRIVATE WORD
|
|
Mac_HexToWord(WCHAR ch)
|
|
{
|
|
if(ch >= L'0' && ch <= L'9')
|
|
return (WORD) ch - L'0';
|
|
if(ch >= L'A' && ch <= L'F')
|
|
return (WORD) ch - L'A' + 10;
|
|
if(ch >= L'a' && ch <= L'f')
|
|
return (WORD) ch - L'a' + 10;
|
|
|
|
Assert(FALSE); //we have tried to use a non-hex number
|
|
return (WORD) -1;
|
|
}
|
|
|
|
PRIVATE BOOL inline
|
|
MAC_IsEscapedOctet(LPCWSTR pch)
|
|
{
|
|
return (pch[0] == HEX_ESCAPE && IsHex(pch[1]) && IsHex(pch[2])) ? TRUE : FALSE;
|
|
}
|
|
|
|
PRIVATE WCHAR
|
|
MAC_TranslateEscapedOctet(LPCWSTR pch)
|
|
{
|
|
WCHAR ch;
|
|
Assert(MAC_IsEscapedOctet(pch));
|
|
|
|
pch++;
|
|
ch = (WCHAR) Mac_HexToWord(*pch++) * 16; // hi nibble
|
|
ch += Mac_HexToWord(*pch); // lo nibble
|
|
|
|
return ch;
|
|
}
|
|
|
|
HRESULT MAC_SHUrlUnescape(LPWSTR psz, DWORD dwFlags)
|
|
{
|
|
WCHAR *pchSrc = psz;
|
|
WCHAR *pchDst = psz;
|
|
BOOL fTrailByte = FALSE;
|
|
|
|
while (*pchSrc)
|
|
{
|
|
if ((*pchSrc == POUND || *pchSrc == QUERY) && (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO))
|
|
{
|
|
lstrcpyW(pchDst, pchSrc);
|
|
pchDst += lstrlenW(pchDst);
|
|
break;
|
|
}
|
|
|
|
if (MAC_IsEscapedOctet(pchSrc))
|
|
{
|
|
WCHAR ch = MAC_TranslateEscapedOctet(pchSrc);
|
|
|
|
*pchDst++ = ch;
|
|
|
|
pchSrc += 3; // enuff for "%XX"
|
|
}
|
|
else
|
|
{
|
|
*pchDst++ = *pchSrc++;
|
|
}
|
|
}
|
|
|
|
TERMSTR(pchDst);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
PRIVATE HRESULT
|
|
MAC_CopyOutA(LPSTR pszIn, LPSTR pszOut, LPDWORD pcch)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cch;
|
|
Assert(pszIn);
|
|
Assert(pszOut);
|
|
Assert(pcch);
|
|
|
|
cch = lstrlen(pszIn);
|
|
if(*pcch > cch)
|
|
lstrcpyA(pszOut, pszIn);
|
|
else
|
|
hr = E_POINTER;
|
|
|
|
*pcch = cch + (FAILED(hr) ? 1 : 0);
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDAPI
|
|
MAC_UrlUnescapeA(LPSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPWSTR pwszIn = NULL;
|
|
LPSTR pszOutT = NULL;
|
|
|
|
if(pszIn)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
CHECKALLOC(pwszIn = PszToUnicode(CP_ACP, pszIn));
|
|
|
|
MAC_SHUrlUnescape(pwszIn, dwFlags);
|
|
|
|
CHECKALLOC(pszOutT = PszToANSI(CP_ACP, pwszIn));
|
|
|
|
if(dwFlags & URL_UNESCAPE_INPLACE)
|
|
{
|
|
lstrcpyA(pszIn, pszOutT);
|
|
}
|
|
else if(pszOut && pcchOut && *pcchOut)
|
|
{
|
|
hr = MAC_CopyOutA(pszOutT, pszOut, pcchOut);
|
|
}
|
|
else
|
|
hr = E_INVALIDARG;
|
|
|
|
exit:
|
|
// Cleanup
|
|
SafeMemFree(pwszIn);
|
|
SafeMemFree(pszOutT);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CoCreateInstance
|
|
// --------------------------------------------------------------------------------
|
|
STDAPI Athena_CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwContext,
|
|
REFIID iid, LPVOID * ppv)
|
|
{
|
|
HRESULT hr;
|
|
IClassFactory * pICFactory;
|
|
|
|
*ppv = NULL;
|
|
|
|
hr = Ares_DllGetClassObject(rclsid, IID_IClassFactory, (LPVOID *) &pICFactory);
|
|
if (CLASS_E_CLASSNOTAVAILABLE == hr)
|
|
{
|
|
hr = Athena_DllGetClassObject(rclsid, IID_IClassFactory, (LPVOID *) &pICFactory);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
hr = pICFactory->CreateInstance(pUnkOuter, iid, ppv);
|
|
|
|
pICFactory->Release();
|
|
|
|
Error:
|
|
return hr;
|
|
}
|
|
|
|
EXTERN_C INT CchFileTimeToLongDateTimeSz(FILETIME * pft, TCHAR * szDateTime,
|
|
UINT cchStr, BOOL fNoSeconds);
|
|
//
|
|
// This function just goes off and uses a function in Capone to do it's work.
|
|
STDAPI_(INT) MAC_CchFileTimeToDateTimeSz(FILETIME * pft, TCHAR * szDateTime, int cch, DWORD dwFlags)
|
|
{
|
|
Assert(dwFlags & DTM_LONGDATE);
|
|
return CchFileTimeToLongDateTimeSz(pft, szDateTime, (UINT) cch, dwFlags & DTM_NOSECONDS);
|
|
}
|
|
#endif // MAC
|
|
|