Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

2876 lines
84 KiB

/** FILE: intl.c *********** Module Header ********************************
*
* Control panel applet for International configuration. This file holds
* everything to do with the "International" dialog box in the Control
* Panel.
*
* International Scheme --
* This module allows the modification of the International section of
* the WIN.INI file, it allows either to select one among the predefined
* countries or to build a new section. By magic stuff it reacts
* automatically to any number of countries declared in the resource
* file, no compilation is needed to add a new country.
*
*
* History:
* 12:30 on Tues 23 Apr 1991 -by- Steve Cathcart [stevecat]
* Took base code from Win 3.1 source
* 10:30 on Tues 04 Feb 1992 -by- Steve Cathcart [stevecat]
* Updated code to latest Win 3.1 sources
*
* Copyright (C) 1990-1992 Microsoft Corporation
*
*************************************************************************/
//==========================================================================
// Include files
//==========================================================================
// C Runtime
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
// Application specific
#include "main.h"
// Setup api
#include "prsinf.h"
//==========================================================================
// Local Definitions
//==========================================================================
// Linked-list structure used at init time
typedef struct _nlslcid
{
struct _nlslcid *pNext;
LCID lcid; // NLS LCID value from registry
int iCountry; // NLS Country Code for this LCID
BOOL bMulti; // Multiple Languages per Country?
} NLSLCID;
#if 1
#define STATIC
#else
#define STATIC static
#endif
#define KEYBOARDHARDWARECHANGABLE 1
/*
* Default settings for integer values of INTLSTRUCT.
*/
typedef struct _intl_istrings
{
TCHAR iCountry[6]; /* Country code (phone ID) */
TCHAR iDate[2]; /* Date mode (0:MDY, 1:DMY, 2:YMD) */
TCHAR iTime[2]; /* Time mode (0: 12 hour clock, 1: 24 ) */
TCHAR iTLZero[2]; /* Leading zeros for hour (0: no, 1: yes) */
TCHAR iCurFmt[2]; /* Currency mode(0: prefix, no separation
1: suffix, no separation
2: prefix, 1 char separation
3: suffix, 1 char separation) */
TCHAR iCurDec[2]; /* Currency Decimal Place */
TCHAR iNegCur[2]; /* Negative currency pattern:
($1.23), -$1.23, $-1.23, $1.23-, etc. */
TCHAR iLzero[2]; /* Leading zeros of decimal (0: no, 1: yes) */
TCHAR iDigits[2]; /* Significant decimal digits */
TCHAR iMeasure[2]; /* Metric 0; British 1 */
TCHAR lcid[10]; /* NT NLS Language/Locale Identifier */
TCHAR iTimeMarker[2]; /* Time marker position (0: suffix, 1: prefix) */
TCHAR iNegNumber[2]; /* Negative number pattern:
(1.1), -1.1, - 1.1, 1.1-, 1.1 - */
} INTL_ISTRINGS;
typedef INTL_ISTRINGS *LPINTL_ISTRINGS;
//==========================================================================
// External Declarations
//==========================================================================
//==========================================================================
// Local Data Declarations
//==========================================================================
LPTSTR pszCountry; /* pointer to this string used by ReadNext () */
LPTSTR pLocales; // Ptr to Locales option info from SETUP api call
LPTSTR pLayouts; // Ptr to Locales option info from SETUP api call
TCHAR szPct02D[] = TEXT("%02d");
TCHAR szPctD[] = TEXT("%d");
TCHAR szQuote[] = TEXT("\"");
TCHAR szColon[] = TEXT(":");
TCHAR szDotDLL[] = TEXT(".DLL");
TCHAR szInstalledLocales[] = TEXT("System\\CurrentControlSet\\Control\\NLS\\Language");
TCHAR szInstalledLayouts[] = TEXT("System\\CurrentControlSet\\Control\\Keyboard Layout");
TCHAR szRegCPIntl[] = TEXT("Control Panel\\International");
TCHAR szRegLayerDef[] = TEXT("Keyboard Layout");
TCHAR szRegLocale[] = TEXT("Locale");
TCHAR szRegDefault[] = TEXT("Default");
TCHAR szRegActive[] = TEXT("Active");
NLSLCID *pFirstNlsLcid = NULL; /* ptr to linked list for country listbox info */
#ifdef JAPAN
// On the safe side.. v-hirot
INTLSTRUCT Current = { TEXT(""),
81,
2,
1,
0,
0,
0,
1,
1,
0,
0,
TEXT(""),
TEXT(""),
TEXT("\\"),
TEXT(","),
TEXT("."),
TEXT("/"),
TEXT(":"),
TEXT(","),
TEXT("yyyy”N MŒŽ d“ú WW"),
TEXT("yy/MM/dd"),
TEXT("JPN"),
1,
1,
1,
2,
0x0411,
TEXT("hh:mm:ss tt"),
0,
1,
TEXT(","),
TEXT(".")
};
/* default used if no WIN.INI or no [intl] section inside WIN.INI */
INTLSTRUCT IntlDef = { TEXT("Other Country"),
81,
2,
1,
0,
0,
0,
1,
1,
0,
0,
TEXT(""),
TEXT(""),
TEXT("\\"),
TEXT(","),
TEXT("."),
TEXT("/"),
TEXT(":"),
TEXT(","),
TEXT("yyyy”N MŒŽ d“ú WW"),
TEXT("yy/MM/dd"),
TEXT("JPN"),
1,
1,
1,
2,
0x0411,
TEXT("hh:mm:ss tt"),
0,
1,
TEXT(","),
TEXT(".")
};
INTL_ISTRINGS DefIStr = { TEXT("81"),
TEXT("2"),
TEXT("1"),
TEXT("0"),
TEXT("0"),
TEXT("0"),
TEXT("1"),
TEXT("1"),
TEXT("0"),
TEXT("0"),
TEXT("0x0411"),
TEXT("0"),
TEXT("1")
};
#else
INTLSTRUCT Current = { TEXT(""),
1,
0,
0,
0,
0,
2,
0,
1,
2,
1,
TEXT("AM"),
TEXT("PM"),
TEXT("$"),
TEXT(","),
TEXT("."),
TEXT("/"),
TEXT(":"),
TEXT(","),
TEXT("dddd, MMMM dd, yyyy"),
TEXT("M/d/yy"),
TEXT("USA"),
1,
0,
1,
0,
0x0409,
TEXT("hh:mm:ss tt"),
0,
1,
TEXT(","),
TEXT(".")
};
/* default used if no WIN.INI or no [intl] section inside WIN.INI */
INTLSTRUCT IntlDef = { TEXT("Other Country"),
1,
0,
0,
0,
0,
2,
0,
1,
2,
1,
TEXT("AM"),
TEXT("PM"),
TEXT("$"),
TEXT(","),
TEXT("."),
TEXT("/"),
TEXT(":"),
TEXT(","),
TEXT("dddd, MMMM dd, yyyy"),
TEXT("M/d/yy"),
TEXT("USA"),
1,
0,
1,
0,
0x0409,
TEXT("hh:mm:ss tt"),
0,
1,
TEXT(","),
TEXT(".")
};
INTL_ISTRINGS DefIStr = { TEXT("1"),
TEXT("0"),
TEXT("0"),
TEXT("0"),
TEXT("0"),
TEXT("2"),
TEXT("0"),
TEXT("1"),
TEXT("2"),
TEXT("1"),
TEXT("0x0409"),
TEXT("0"),
TEXT("1")
};
#endif
int nCurCountry; /* current Country CB selection */
int nCurLang; /* current Language CB selection */
int nCurKbd; /* current Keyboard CB selection */
TCHAR *pszNegNumPat[NUM_NEGNUM_PAT] = { TEXT("(%s)"), // the positions of these can't change
TEXT("-%s"),
TEXT("- %s"),
TEXT("%s-"),
TEXT("%s -")
};
TCHAR *pszCurPat[NUM_CUR_PAT] = { TEXT("%s%s"),
TEXT("%s %s")
};
TCHAR *pszNegCurPat[NUM_NEG_PAT] = { TEXT("(%s%s)"), // the positions of these can't change
TEXT("-%s%s"),
TEXT("%s-%s"),
TEXT("%s%s-"),
TEXT("(%s%s)"),
TEXT("-%s%s"),
TEXT("%s-%s"),
TEXT("%s%s-"),
TEXT("-%s %s"),
TEXT("-%s %s"),
TEXT("%s %s-"),
TEXT("%s %s-"),
TEXT("%s -%s"),
TEXT("%s- %s"),
TEXT("(%s %s)"),
TEXT("(%s %s)")
};
TCHAR *pszSymPlacement[] = { TEXT("%s1"),
TEXT("1%s"),
TEXT("%s 1"),
TEXT("1 %s")
};
WORD wFontHeight;
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
// for new emperor's era
TCHAR NewEra[8];
WORD NewYear = 9999;
WORD NewMonth = 0;
WORD NewDay = 0;
#endif
//==========================================================================
// Local Function Prototypes
//==========================================================================
BOOL
InvokeSetup(
HWND hDlg,
LPTSTR pszInfFile,
LPTSTR pszOption);
BOOL
CheckOptionInstall(
LPTSTR pszRegKey,
LPTSTR pszOption);
//==========================================================================
// Functions
//==========================================================================
// *** private functions ***
/*
* This helps parse a date string. It returns the number of characters
* in the current token or'ed with a token identifier.
*/
STATIC WORD GetLDFToken(
LPTSTR pString,
LPTSTR pBuf)
{
TCHAR cTest;
WORD retval, wLength;
LPTSTR pBase = pString, pBufBase;
/* check the first letter of the token;
* by default this will be a separator
*/
switch (cTest = *pString)
{
case TEXT('d'):
retval = LDF_DAY;
break;
#ifdef JAPAN /* V-KeijiY June.29.1992 */
case TEXT('W'):
retval = LDF_JaDAY;
break;
#endif
case TEXT('M'):
retval = LDF_MONTH;
break;
case TEXT('y'):
retval = LDF_YEAR;
break;
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
case TEXT('G'):
case TEXT('n'):
retval = LDF_JaYEAR;
for (wLength = 0; (*pString == TEXT('G') || *pString == TEXT('n')) && wLength < 4;
wLength++, pBuf++, pString++)
*pBuf = *pString;
goto OutOfHere;
break;
#endif
case TEXT('\0'):
return (0);
break;
case TEXT('\''):
++pString;
/* Fall through */
default:
retval = LDF_SEP;
/* This is a separator; copy to the next unescaped "'" if we started
* with a "'", otherwise to the next unescaped token marker
*/
pBufBase = pBuf;
while (1)
{
switch (*pString)
{
case TEXT('d'):
case TEXT('M'):
case TEXT('y'):
if (cTest == TEXT('\''))
goto DoDefault;
case TEXT('\0'):
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG DATE
case TEXT('n'):
case TEXT('G'):
case TEXT('W'):
#endif
goto EndOfSep;
case TEXT('\''):
++pString;
if (cTest == TEXT('\'') && *pString != TEXT('\''))
#ifdef JAPAN
goto OutOfHere;
#else
goto EndOfSep;
#endif
/* Fall through */
default:
DoDefault:
*pBuf++ = *pString++;
}
}
EndOfSep:
if (*(pBuf = CharPrev (pBufBase, pBuf)) != TEXT(' '))
++pBuf;
goto OutOfHere;
}
/* This is not a separator; see how long the thing is (up to
* 4 characters)
*/
wLength = 0;
do
{
++wLength;
*pBuf++ = *pString++;
} while (*pString == cTest && wLength < 4) ;
OutOfHere:
*pBuf = TEXT('\0');
return (retval + (WORD) (pString - pBase));
}
/*
* This fills the INTL structure with date information.
*/
STATIC void TranslateShortDate(
PINTL pI)
{
LDF LongDF;
WORD wElement;
short i;
ParseLDF (pI->sShortDate, &LongDF);
pI->iDate = (int) ((LongDF.Order[0] & 0xF0) - LDF_MONTH) >> 4;
for (i = 0; i < 3; i++)
{
wElement = LongDF.Order[i];
switch (wElement & 0xF0)
{
case LDF_MONTH:
pI->iMonLzero = (short) ((wElement & 0x0F) - 1);
break;
case LDF_DAY:
pI->iDayLzero = (short) ((wElement & 0x0F) - 1);
break;
case LDF_YEAR:
pI->iCentury = (short) ((wElement & 0x0F) - 2);
break;
default:
break;
}
}
}
/*
* This routine sets the time sample into the appropriate
* static text item of the dialog.
*/
STATIC void SetTimeSamples(
HWND hDlg,
PINTL pI,
BOOL fUseDefault)
{
LPTSTR pszAMPM;
TCHAR szSample[30];
if (fUseDefault)
{
GetTimeFormat( pI->lcid,
LOCALE_NOUSEROVERRIDE,
NULL,
NULL,
szSample,
30 );
}
else
{
/*
* Must do this by hand since pszAMPM could be set to anything.
*/
GetTime ();
pszAMPM = (wDateTime[HOUR] < 12) ? pI->s1159 : pI->s2359;
if (!pI->iTime)
if (!(wDateTime[HOUR] %= 12))
wDateTime[HOUR] = 12;
if (pI->iTimeMarker == 1)
{
wsprintf ( szSample,
pI->iTLZero ? TEXT("%s %02d%s%02d%s%02d")
: TEXT("%s %d%s%02d%s%02d"),
pszAMPM,
wDateTime[HOUR],
pI->sTime,
wDateTime[MINUTE],
pI->sTime,
wDateTime[SECOND] );
}
else
{
wsprintf ( szSample,
pI->iTLZero ? TEXT("%02d%s%02d%s%02d %s")
: TEXT("%d%s%02d%s%02d %s"),
wDateTime[HOUR],
pI->sTime,
wDateTime[MINUTE],
pI->sTime,
wDateTime[SECOND],
pszAMPM );
}
}
SetDlgItemText (hDlg, INTL_TIMESAMPLE, szSample);
}
/*
* This routine sets the number sample into the appropriate
* static text item of the dialog.
*/
STATIC void SetNumSamples(
HWND hDlg,
PINTL pI,
BOOL fUseDefault)
{
TCHAR szPosSample[30];
TCHAR szNegSample[30];
TCHAR *psz;
TCHAR ch;
int i;
TCHAR szValue[] = TEXT("-1234.000000");
NUMBERFMT NumFmt;
/*
* Change the decimal digit values to the number of digits.
* The maximum value is MAX_DEC_DIGITS.
*/
psz = szValue + 6;
i = (pI->iDigits < MAX_DEC_DIGITS) ? pI->iDigits : MAX_DEC_DIGITS;
ch = (TCHAR) (TEXT('0') + i);
for ( ; i; i--)
{
*psz++ = ch;
}
*psz = TEXT('\0');
if (fUseDefault)
{
/*
* Get negative number sample.
*/
GetNumberFormat( pI->lcid,
LOCALE_NOUSEROVERRIDE,
szValue,
NULL,
szNegSample,
30 );
/*
* Get positive number sample.
*/
psz = szValue + 1;
GetNumberFormat( pI->lcid,
LOCALE_NOUSEROVERRIDE,
psz,
NULL,
szPosSample,
30 );
}
else
{
NumFmt.NumDigits = (pI->iDigits < MAX_DEC_DIGITS) ? pI->iDigits : MAX_DEC_DIGITS;
NumFmt.LeadingZero = pI->iLzero;
NumFmt.Grouping = 3;
NumFmt.lpDecimalSep = pI->sDecimal;
NumFmt.lpThousandSep = pI->sThousand;
NumFmt.NegativeOrder = pI->iNegNumber;
/*
* Get negative number sample.
*/
GetNumberFormat( pI->lcid,
0,
szValue,
&NumFmt,
szNegSample,
30 );
/*
* Get positive number sample.
*/
psz = szValue + 1;
GetNumberFormat( pI->lcid,
0,
psz,
&NumFmt,
szPosSample,
30 );
}
SetDlgItemText (hDlg, INTL_NUMSAMPLE, szPosSample);
SetDlgItemText (hDlg, INTL_NEGNUMSAMPLE, szNegSample);
}
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
WORD ConvertStringToInteger(
LPTSTR far *p)
{
TCHAR *pt = *p;
int result = 0;
if (*pt == TEXT(','))
pt++;
while (*pt == TEXT(' '))
pt++;
while (*pt >= TEXT('0') && *pt <= TEXT('9'))
result = result * 10 + (*pt++ - TEXT('0'));
*p = pt;
return (result);
}
DWORD ConvertEraToJapaneseEra(
WORD Year,
WORD Month,
WORD Day)
{
WORD eranameindex = 0;
WORD ryear = 1;
if (Year >= NewYear)
{
if (Year == NewYear && Month <= NewMonth && Day < NewDay)
goto Heisei;
eranameindex = 5;
ryear = Year - (NewYear - 1);
}
else if (Year >= 1989)
{
Heisei:
if (Year == 1989 && Month == 1 && Day < 8)
goto Syouwa;
eranameindex = 4;
ryear = Year - 1988;
}
else if (Year >= 1926)
{
Syouwa:
eranameindex = 3;
ryear = Year - 1925;
}
else if (Year >= 1912)
{
eranameindex = 2;
ryear = Year - 1911;
}
else if (Year >= 1868)
{
eranameindex = 1;
ryear = Year - 1867;
}
return ( MAKELONG(ryear, eranameindex) );
}
#endif
/*
* Format the date strings and put them in the dialog.
*/
STATIC void SetDateSamples(
HWND hDlg,
PINTL pI)
{
TCHAR szDate[80];
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
// Additional space is required in order to support Jpn Emperor's Era
TCHAR szDay[3], szMonth[16], szYear[8], szDayName[16], szDayNameTrail[16];
#else
TCHAR szDay[3], szMonth[16], szYear[5], szDayName[16];
#endif
TCHAR *first, *second, *third;
LDF LongDF;
short i, j;
WORD wKey, wOffset;
WORD wTemp, wString;
/* Get the three date strings: month, day, year
*/
GetDate ();
i = wDateTime[YEAR];
if (!(pI->iCentury))
i %= 100;
MyItoa (i, szYear, 10);
wsprintf (szMonth, pI->iMonLzero ? szPct02D : szPctD, wDateTime[MONTH]);
wsprintf (szDay, pI->iDayLzero ? szPct02D : szPctD, wDateTime[DAY]);
/* Determine the order of the strings,
* and print them to szDate
*/
if (pI->iDate == 2)
{
first = szYear;
second = szMonth;
third = szDay;
}
else
{
third = szYear;
if (pI->iDate == 1)
{
first = szDay;
second = szMonth;
}
else
{
first = szMonth;
second = szDay;
}
}
wsprintf (szDate, TEXT("%s%s%s%s%s"), first, pI->sDateSep,
second, pI->sDateSep, third);
SetDlgItemText (hDlg, INTL_DATESAMPLE, szDate);
/* Parse the long date string
* and get the day of week string
*/
ParseLDF (pI->sLongDate, &LongDF);
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
szDayNameTrail[0] = TEXT('\0');
if (LongDF.Leadin)
{
if ((LongDF.Leadin & 0xF0) == LDF_JaDAY)
LoadString(hModule,
JaDAYSOFWK + wDateTime[WEEKDAY] + ((LongDF.Leadin & 0x0F) - 4 ?
7 : 0 ),
szDayName, CharSizeOf(szDayName));
else
LoadString(hModule,
DAYSOFWK + wDateTime[WEEKDAY] + ((LongDF.Leadin & 0x0F) - 4 ?
7 : 0 ),
szDayName, CharSizeOf(szDayName));
if (LongDF.Trailin)
{
szDayNameTrail[0] = TEXT(' ');
szDayNameTrail[1] = TEXT('\0');
lstrcat(szDayNameTrail, szDayName);
szDayName[0] = TEXT('\0');
}
else
szDayNameTrail[0] = TEXT('\0');
}
#else
if (LongDF.Leadin)
{
wTemp = (WORD) ((LongDF.Leadin & 0x0F) - 4) ? 7 : 0;
wString = (WORD) (DAYSOFWK + wDateTime[WEEKDAY] + wTemp),
LoadString (hModule, wString, szDayName, CharSizeOf(szDayName));
}
#endif
else
szDayName[0] = TEXT('\0');
/* Get the month, day, year strings
*/
for (i = 2; i >= 0; i--)
{
wKey = LongDF.Order[i];
switch (wKey & 0xF0)
{
case LDF_DAY:
wsprintf (szDay, (wKey & 0x0f) == 2 ? szPct02D : szPctD, wDateTime[DAY]);
break;
case LDF_MONTH:
wOffset = 0;
switch (wKey & 0x0F)
{
case 3:
wOffset = 12;
case 4:
LoadString (hModule, (WORD) (MON_OF_YR - 1 + wDateTime[MONTH] + wOffset),
szMonth, CharSizeOf(szMonth));
break;
default:
wsprintf (szMonth, (wKey & 0x0f) == 2 ? szPct02D : szPctD,
wDateTime[MONTH]);
break;
}
break;
case LDF_YEAR:
j = wDateTime[YEAR];
if ((wKey & 0x0F) == 2)
j %= 100;
MyItoa (j, szYear, 10);
break;
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
case LDF_JaYEAR:
{
DWORD dd = ConvertEraToJapaneseEra (wDateTime[YEAR], wDateTime[MONTH],
wDateTime[DAY]);
if ((wKey & 0x0F) > 2)
{
// set era string
if (HIWORD(dd) >= 5) // supporse new emperor's era
lstrcpy(szYear, NewEra);
else
LoadString (hModule, JaEMPERORYEAR + HIWORD(dd), szYear,
CharSizeOf(szYear));
}
else
szYear[0] = TEXT('\0');
switch (wKey & 0x0F)
{
case 1:
case 3:
wsprintf (szYear + lstrlen(szYear), TEXT("%d"), LOWORD(dd));
break;
case 2:
case 4:
default:
wsprintf (szYear + lstrlen(szYear), TEXT("%02.02d"),
LOWORD(dd));
break;
}
break;
}
#endif
}
}
/* Determine the order of the date strings
* program management has decided that only these three
* formats will be allowed
*/
switch (wKey & 0xF0)
{
case LDF_DAY:
first = szDay;
second = szMonth;
third = szYear;
break;
case LDF_YEAR:
#ifdef JAPAN // LONG_DATE_FORMAT
case LDF_JaYEAR:
#endif
first = szYear;
second = szMonth;
third = szDay;
break;
case LDF_MONTH:
default:
first = szMonth;
second = szDay;
third = szYear;
break;
}
/* Put the string into the dialog
*/
#ifdef JAPAN /* V-KeijiY June.30.1992 */
wsprintf (szDate, TEXT("%s%s %s%s %s%s %s%s%s"), szDayName,
LongDF.LeadinSep, first, LongDF.Sep[0],
second, LongDF.Sep[1], third, LongDF.Sep[2],
szDayNameTrail);
#else
wsprintf (szDate, TEXT("%s%s %s%s %s%s %s"), szDayName,
LongDF.LeadinSep, first, LongDF.Sep[0],
second, LongDF.Sep[1], third);
#endif
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
// Japanese date format will overflow in the rectangle, truncate required.
{
LPTSTR lpPos;
RECT rcRect;
WORD wWidth;
HDC hDc;
SIZE TxtSize;
GetWindowRect(GetDlgItem(hDlg, INTL_DATESAMPLE2), (LPRECT) &rcRect);
// width of long date sample window
wWidth = rcRect.right - rcRect.left - 4;
lpPos = szDate + lstrlen(szDate);
if (hDc = GetDC(hDlg))
{
GetTextExtentPoint (hDc, szDate, lstrlen(szDate), &TxtSize);
if (TxtSize.cx > wWidth)
{
// doesn't fit in the window - truncate & try again
do {
lpPos = CharPrev(szDate,lpPos);
*lpPos = TEXT('\0');
lstrcat(szDate, TEXT("..."));
GetTextExtentPoint(hDc, szDate, lstrlen(szDate), &TxtSize);
} while ( TxtSize.cx > wWidth );
}
ReleaseDC (hDlg, hDc);
}
}
#endif
SetDlgItemText (hDlg, INTL_DATESAMPLE2, szDate);
}
/*
* This puts the currency samples into the dialog box.
*/
STATIC void SetCurSamples(
HWND hDlg,
PINTL pI,
BOOL fUseDefault)
{
TCHAR szPosSample[30];
TCHAR szNegSample[30];
TCHAR *psz;
TCHAR ch;
int i;
TCHAR szValue[] = TEXT("-1.000000000");
CURRENCYFMT CurFmt;
/*
* Change the decimal digit values to the number of digits.
* The maximum value is MAX_DEC_DIGITS.
*/
psz = szValue + 3;
i = (pI->iCurDec < MAX_DEC_DIGITS) ? pI->iCurDec : MAX_DEC_DIGITS;
ch = (TCHAR) (TEXT('0') + i);
for ( ; i; i--)
{
*psz++ = ch;
}
*psz = TEXT('\0');
if (fUseDefault)
{
/*
* Get negative currency sample.
*/
GetCurrencyFormat( pI->lcid,
LOCALE_NOUSEROVERRIDE,
szValue,
NULL,
szNegSample,
30 );
/*
* Get positive currency sample.
*/
psz = szValue + 1;
GetCurrencyFormat( pI->lcid,
LOCALE_NOUSEROVERRIDE,
psz,
NULL,
szPosSample,
30 );
}
else
{
CurFmt.NumDigits = (pI->iCurDec < MAX_DEC_DIGITS) ? pI->iCurDec : MAX_DEC_DIGITS;
CurFmt.LeadingZero = pI->iLzero;
CurFmt.Grouping = 3;
CurFmt.lpDecimalSep = pI->sMonDecimal;
CurFmt.lpThousandSep = pI->sMonThousand;
CurFmt.NegativeOrder = pI->iNegCur;
CurFmt.PositiveOrder = pI->iCurFmt;
CurFmt.lpCurrencySymbol = pI->sCurrency;
/*
* Get negative currency sample.
*/
GetCurrencyFormat( pI->lcid,
0,
szValue,
&CurFmt,
szNegSample,
30 );
/*
* Get positive currency sample.
*/
psz = szValue + 1;
GetCurrencyFormat( pI->lcid,
0,
psz,
&CurFmt,
szPosSample,
30 );
}
SetDlgItemText (hDlg, INTL_CURSAMPLE, szPosSample);
SetDlgItemText (hDlg, INTL_NEGSAMPLE, szNegSample);
}
/*
* This routine loads the International section of WIN.INI
* into the structure "Current". If items are missing U.S. values
* are used.
*/
STATIC void LoadIntlWin (void)
{
TCHAR szwork[128];
/*
* Get language and country information.
*/
GetLocaleValue (0,
LOCALE_SABBREVLANGNAME,
Current.sLanguage,
CharSizeOf(Current.sLanguage),
IntlDef.sLanguage);
GetLocaleValue (0,
LOCALE_SCOUNTRY,
Current.sCountry,
CharSizeOf(Current.sCountry),
IntlDef.sCountry);
Current.iCountry = GetLocaleValue (0,
LOCALE_ICOUNTRY,
szwork,
CharSizeOf(szwork),
DefIStr.iCountry);
/*
* Get list separator and measurement information.
*/
GetLocaleValue (0,
LOCALE_SLIST,
Current.sList,
CharSizeOf(Current.sList),
IntlDef.sList);
if ((Current.iMeasure = GetLocaleValue (0,
LOCALE_IMEASURE,
szwork,
CharSizeOf(szwork),
DefIStr.iMeasure)) > 1)
{
Current.iMeasure = 0;
}
/*
* Get number format information.
*/
GetLocaleValue (0,
LOCALE_STHOUSAND,
Current.sThousand,
CharSizeOf(Current.sThousand),
IntlDef.sThousand);
GetLocaleValue (0,
LOCALE_SDECIMAL,
Current.sDecimal,
CharSizeOf(Current.sDecimal),
IntlDef.sDecimal);
Current.iDigits = GetLocaleValue (0,
LOCALE_IDIGITS,
szwork,
CharSizeOf(szwork),
DefIStr.iDigits);
Current.iLzero = GetLocaleValue (0,
LOCALE_ILZERO,
szwork,
CharSizeOf(szwork),
DefIStr.iLzero);
Current.iNegNumber = GetLocaleValue (0,
LOCALE_INEGNUMBER,
szwork,
CharSizeOf(szwork),
DefIStr.iNegNumber);
/*
* Get currency format information.
*/
GetLocaleValue (0,
LOCALE_SCURRENCY,
Current.sCurrency,
CharSizeOf(Current.sCurrency),
IntlDef.sCurrency);
GetLocaleValue (0,
LOCALE_SMONTHOUSANDSEP,
Current.sMonThousand,
CharSizeOf(Current.sMonThousand),
IntlDef.sMonThousand);
GetLocaleValue (0,
LOCALE_SMONDECIMALSEP,
Current.sMonDecimal,
CharSizeOf(Current.sMonDecimal),
IntlDef.sMonDecimal);
Current.iCurDec = GetLocaleValue (0,
LOCALE_ICURRDIGITS,
szwork,
CharSizeOf(szwork),
DefIStr.iCurDec);
Current.iCurFmt = GetLocaleValue (0,
LOCALE_ICURRENCY,
szwork,
CharSizeOf(szwork),
DefIStr.iCurFmt);
Current.iNegCur = GetLocaleValue (0,
LOCALE_INEGCURR,
szwork,
CharSizeOf(szwork),
DefIStr.iNegCur);
/*
* Get time format information.
*/
GetLocaleValue (0,
LOCALE_STIMEFORMAT,
Current.sTimeFormat,
CharSizeOf(Current.sTimeFormat),
IntlDef.sTimeFormat);
GetLocaleValue (0,
LOCALE_STIME,
Current.sTime,
CharSizeOf(Current.sTime),
IntlDef.sTime);
Current.iTime = GetLocaleValue (0,
LOCALE_ITIME,
szwork,
CharSizeOf(szwork),
DefIStr.iTime);
Current.iTLZero = GetLocaleValue (0,
LOCALE_ITLZERO,
szwork,
CharSizeOf(szwork),
DefIStr.iTLZero);
Current.iTimeMarker = GetLocaleValue (0,
LOCALE_ITIMEMARKPOSN,
szwork,
CharSizeOf(szwork),
DefIStr.iTimeMarker);
GetLocaleValue (0,
LOCALE_S1159,
Current.s1159,
CharSizeOf(Current.s1159),
IntlDef.s1159);
GetLocaleValue (0,
LOCALE_S2359,
Current.s2359,
CharSizeOf(Current.s2359),
IntlDef.s2359);
/*
* Get date format information.
*/
GetLocaleValue (0,
LOCALE_SSHORTDATE,
Current.sShortDate,
CharSizeOf(Current.sShortDate),
IntlDef.sShortDate);
GetLocaleValue (0,
LOCALE_SDATE,
Current.sDateSep,
CharSizeOf(Current.sDateSep),
IntlDef.sDateSep);
Current.iDate = GetLocaleValue (0,
LOCALE_IDATE,
szwork,
CharSizeOf(szwork),
DefIStr.iDate);
GetLocaleValue (0,
LOCALE_SLONGDATE,
Current.sLongDate,
CharSizeOf(Current.sLongDate),
IntlDef.sLongDate);
TranslateShortDate (&Current);
#ifdef JAPAN // LONG_DATE_FORMAT
{
TCHAR szBuf[40];
LPTSTR lp, lpt;
if (GetProfileString (szIntl, TEXT("NewEra"), TEXT(""), szBuf, CharSizeOf(szBuf)))
{
lp = szBuf;
lpt = NewEra;
while (*lp != TEXT(','))
*lpt++ = *lp++;
*lpt = TEXT('\0');
NewYear = ConvertStringToInteger(&lp);
NewMonth = ConvertStringToInteger(&lp);
NewDay = ConvertStringToInteger(&lp);
if (NewYear < 1991)
NewYear = 0; // wrong conversion data
}
}
#endif
}
/*
* This does a total reset of all the samples in the dialog.
*/
STATIC void FillIntlDlg(
HWND hDlg,
PINTL pIntl,
BOOL fUseDefault)
{
SetDlgItemText (hDlg, INTL_LISTSEP, pIntl->sList);
SendDlgItemMessage (hDlg, INTL_MEASUREMENT, CB_SETCURSEL, pIntl->iMeasure, 0L);
SetDateSamples (hDlg, pIntl);
SetTimeSamples (hDlg, pIntl, fUseDefault);
SetNumSamples (hDlg, pIntl, fUseDefault);
SetCurSamples (hDlg, pIntl, fUseDefault);
}
/*
* Callback function for EnumSystemLocales.
*/
BOOL CALLBACK EnumSysLocaleFunc(
LPTSTR pLocale)
{
NLSLCID *pTemp; /* temp pointer to linked list */
TCHAR pData[128]; /*
/*
* Make the new nlslcid node and add it to the linked list.
*/
if (pFirstNlsLcid)
{
pTemp = (NLSLCID *) AllocMem (sizeof(NLSLCID));
pTemp->pNext = pFirstNlsLcid;
pFirstNlsLcid = pTemp;
}
else // First time thru
{
pFirstNlsLcid = (NLSLCID *) AllocMem (sizeof(NLSLCID));
pFirstNlsLcid->pNext = NULL;
}
/*
* Initialize bMulti flag to false.
*/
pFirstNlsLcid->bMulti = FALSE;
/*
* Save LCID value and get "Country Code" value for the LCID.
*/
pFirstNlsLcid->lcid = _tcstoul (pLocale, NULL, 16);
pFirstNlsLcid->iCountry =
GetLocaleValue (pFirstNlsLcid->lcid,
LOCALE_ICOUNTRY | LOCALE_NOUSEROVERRIDE,
pData,
CharSizeOf(pData),
NULL);
/*
* Return success.
*/
return (TRUE);
}
/*
* This initializes all of the international dialog controls.
*/
STATIC BOOL InitIntlDlg(
HWND hDlg)
{
int nLen, nDefault;
int count; /* iterative */
HANDLE hLBName, hkey;
TCHAR szLBEntry[128];
int nCountry; /* number of countries available in setup.inf */
LPTSTR pszTemp;
LPSTR pszAnsi; /* ptr to ANSI Locales option info from SETUP api call */
TCHAR szLocale[40];
TCHAR szLayout[40];
DWORD dwSize, dwType;
int rc;
NLSLCID *pNlsLcid;
LPTSTR pszFileName, pszOption, pszOptionText;
LPTSTR pszCurrent, pszDefault;
int nPlace;
pLocales = NULL;
pLayouts = NULL;
if ((pszTemp = BackslashTerm (szSharedDir)) - szSharedDir > 3)
*(pszTemp - 1) = TEXT('\0');
SetCurrentDirectory(szSharedDir);
LoadString (hModule, PRN, szSetupDir, CharSizeOf(szSetupDir));
LoadString (hModule, PRN, szDirOfSrc, CharSizeOf(szDirOfSrc));
/* load Window International section into structure "Current"
*/
LoadIntlWin ();
hLBName = GetDlgItem (hDlg, INTL_COUNTRY);
/////////////////////////////////////////////////////////////////
// Enumerate all supported locales for the Country listbox.
/////////////////////////////////////////////////////////////////
nCountry = 0;
/*
* First: Make a linked list of all LCIDs in Registry.
*
* This uses the EnumSysLocaleFunc callback function to
* build the linked list.
*/
pFirstNlsLcid = (NLSLCID *) NULL;
EnumSystemLocales (EnumSysLocaleFunc, LCID_SUPPORTED);
/*
* Now traverse the list, and determine duplicate country codes
*
* Outer loop ensures that we check every LCID entry from registry
* If statement determines if a check is even necessary
* (i.e. if the field is already TRUE, we already have an
* answer for this LCID, so just move on to the next one).
* Inner loop tests all remaining LCIDs against current LCID for a
* matching Country code and sets bMulti to TRUE.
*/
pNlsLcid = pFirstNlsLcid;
while (pNlsLcid)
{
if (!pNlsLcid->bMulti)
{
NLSLCID *pTemp;
pTemp = pNlsLcid->pNext;
while (pTemp)
{
if (pNlsLcid->iCountry == pTemp->iCountry)
{
pNlsLcid->bMulti = TRUE;
pTemp->bMulti = TRUE;
}
pTemp = pTemp->pNext;
}
}
pNlsLcid = pNlsLcid->pNext;
}
/*
* Traverse the list again, putting values in ListBox based on
* the findings above.
*/
pNlsLcid = pFirstNlsLcid;
while (pNlsLcid)
{
TCHAR szLocName[256];
TCHAR szLang[128];
if (pNlsLcid->bMulti)
{
rc = GetLocaleValue (pNlsLcid->lcid,
LOCALE_SCOUNTRY | LOCALE_NOUSEROVERRIDE,
szLBEntry,
CharSizeOf(szLBEntry),
NULL);
// In case of error - do not put this entry in Combobox
if (rc == -1)
goto SkipBadEntry;
rc = GetLocaleValue (pNlsLcid->lcid,
LOCALE_SLANGUAGE | LOCALE_NOUSEROVERRIDE,
szLang,
CharSizeOf(szLang),
NULL);
if (rc == -1)
goto SkipBadEntry;
wsprintf (szLocName, TEXT("%s (%s)"), szLBEntry, szLang);
}
else
{
rc = GetLocaleValue (pNlsLcid->lcid,
LOCALE_SCOUNTRY | LOCALE_NOUSEROVERRIDE,
szLocName,
CharSizeOf(szLocName),
NULL);
if (rc == -1)
goto SkipBadEntry;
}
count = SendMessage (hLBName, CB_ADDSTRING, 0, (LPARAM) szLocName);
nCountry++;
SendMessage (hLBName, CB_SETITEMDATA, count, (LPARAM) pNlsLcid->lcid);
SkipBadEntry:
pNlsLcid = pNlsLcid->pNext;
}
/*
* Finally traverse the list, freeing list memory.
*/
pNlsLcid = pFirstNlsLcid;
while (pNlsLcid)
{
pFirstNlsLcid = pNlsLcid;
pNlsLcid = pNlsLcid->pNext;
FreeMem ((LPVOID) pFirstNlsLcid, sizeof(NLSLCID));
}
/*
* If there are no entries in the listbox, then error.
*/
if (!nCountry)
goto Error1;
/*
* Find the currently selected country by searching for
* Current.sCountry in the listbox.
*/
count = -1;
nLen = lstrlen (Current.sCountry);
while (1)
{
if ((nCurCountry = SendMessage (hLBName, CB_FINDSTRING, count,
(LPARAM) Current.sCountry)) <= count)
{
nCurCountry = nCountry - 1;
break;
}
if (SendMessage (hLBName, CB_GETLBTEXTLEN, nCurCountry, 0L) == nLen)
{
/*
* We have an exact match on country name alone, no further
* checks are necessary, just use it.
*/
break;
}
else
{
LCID lcid;
/*
* Since we can have "country" entries like
* "Canada (Canadian English)"
* "Canada (Canadian French)"
* "Switzerland (Swiss French)"
* "Switzerland (Swiss German)"
* "Switzerland (Swiss Italian)"
*
* the above CB_FINDSTRING will match only the first entry
* initially. We need to do a further check against
* LOCALE_SABREVLANGNAME to find the exact match.
*/
lcid = (LCID)SendMessage (hLBName, CB_GETITEMDATA, nCurCountry, 0L);
GetLocaleValue (lcid,
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
szLBEntry,
CharSizeOf(szLBEntry),
NULL);
if (!lstrcmpi (szLBEntry, Current.sLanguage))
break;
/*
* else this entry didn't match, so go check next closest
* Combobox entry.
*/
}
count = nCurCountry;
}
Current.lcid = (LCID)SendMessage (hLBName, CB_GETITEMDATA, nCurCountry, 0L);
SendMessage (hLBName, CB_SETCURSEL, nCurCountry, 0L);
//////////////////////////////////////////////////////////////////////////
// Get user's default selection for Locale/Language and Keyboard
// Layout from Registry and select it in ComboBox.
//////////////////////////////////////////////////////////////////////////
/*
* Assume that no Locale and Layout config choice exists.
*/
szLocale[0] = TEXT('\0');
szLayout[0] = TEXT('\0');
/*
* Get the system default Locale.
*/
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, szInstalledLocales,
0L, KEY_READ, (PHKEY) &hkey))
{
dwSize = sizeof(szLocale);
rc = RegQueryValueEx (hkey, szRegDefault, NULL, &dwType,
(LPBYTE) szLocale, &dwSize);
RegCloseKey (hkey);
if (rc != 0)
{
goto DefaultLocaleFail;
}
}
else
{
DefaultLocaleFail:
/*
* Error condition - System DEFAULT locale not found.
*
* Put up a message box error stating that the USER does
* not have any USER or SYSTEM default locale info
* configured in the registry and just continue for now.
*/
MyMessageBox (hDlg, INTL+9, INITS+1, MB_OK | MB_ICONINFORMATION);
}
// Try to get the USER's Keyboard Layout from the registry
if (!RegOpenKeyEx (HKEY_CURRENT_USER, szRegLayerDef, 0L, KEY_READ, (PHKEY) &hkey))
{
dwSize = sizeof(szLayout);
rc = RegQueryValueEx (hkey, szRegActive, NULL, &dwType,
(LPBYTE) szLayout, &dwSize);
RegCloseKey (hkey);
// Error condition - USER Layout not found,
// Try to find a system default Layout
if (rc != 0)
goto FindDefaultLayout;
}
else
{
// Error reading registry for USER
// Try to find a system default Layout
FindDefaultLayout:
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, szInstalledLayouts,
0L, KEY_READ, (PHKEY) &hkey))
{
dwSize = sizeof(szLayout);
rc = RegQueryValueEx (hkey, szRegDefault, NULL, &dwType,
(LPBYTE) szLayout, &dwSize);
RegCloseKey (hkey);
if (rc != 0)
goto DefaultLayoutFail;
}
else
{
DefaultLayoutFail:
// Error condition - System DEFAULT locale not found
// Put up a message box error stating that the USER does
// not have any USER or SYSTEM default Keyboard Layout info
// configured in the registry and just continue for now.
MyMessageBox (hDlg, INTL+10, INITS+1, MB_OK | MB_ICONINFORMATION);
}
}
//////////////////////////////////////////////////////////////////////////
// Get option lists from .INF files, select USER defaults
//////////////////////////////////////////////////////////////////////////
// Get the "LANGUAGE" options
hLBName = GetDlgItem (hDlg, INTL_LANGUAGE);
LoadString (hModule, KBD + 1, szLBEntry, CharSizeOf(szLBEntry));
nDefault = -1;
nCurLang = -1;
pszCurrent = NULL;
pszDefault = NULL;
pszAnsi = GetAllOptionsText ("LANGUAGE", 0);
pLocales = pszTemp = (LPTSTR) pszAnsi;
// Check for api errors and NoOptions
if ((pszAnsi == NULL) || ((*pszAnsi == '\0') && (*(pszAnsi+1) == '\0')))
goto Error1;
#ifdef UNICODE
if (pszAnsi)
{
// Get size of buffer pointed to by pszAnsi
for (nLen = 0; ;pszAnsi++)
{
nLen++;
if (*pszAnsi == '\0' && *(pszAnsi+1) == '\0')
break;
}
// Take into account double-null termination of buffer
nLen += 2;
pszAnsi = (LPSTR) pszTemp;
pLocales = pszTemp = (LPTSTR) LocalAlloc (LPTR, nLen*2);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, pszAnsi, nLen, pLocales, nLen);
LocalFree ((HLOCAL) pszAnsi);
}
#endif
// Continue until we reach end of buffer, marked by Double '\0'
while (*pszTemp != TEXT('\0'))
{
// Get a ptr to each of item in the triplet strings returned
pszOption = pszTemp;
pszOptionText = pszOption + lstrlen (pszOption) + 1;
pszFileName = pszOptionText + lstrlen (pszOptionText) + 1;
nPlace = SendMessage (hLBName, CB_ADDSTRING, (DWORD)-1, (LPARAM)pszOptionText);
// Save ptr to Filename and Option strings for later use with SETUP
SendMessage (hLBName, CB_SETITEMDATA, nPlace, (LPARAM)pszOption);
// Find OPTION that matches User's selection
//
// Since this is a sorted Combo-box, we must save a ptr to the
// OptionText for both current and default selections. Later we
// will perform a search to get the actual cbox index of the
// matching selections.
// Special Note: The pszOption values point to 8-char strings
// like "00000409" BUT szLocale is a 4-char Language
// number string value like "0409"; hence, we will
// do the comparison starting at pszOption+4.
// Use this when we go to UniCode (pszOption + 4*sizeof(TCHAR)).
if (!lstrcmpi (pszOption + 4, szLocale))
pszCurrent = pszOptionText;
// Find selection matching our "Default", for possible use below
if (!lstrcmpi (pszOption, szLBEntry))
pszDefault = pszOptionText;
// Point to next triplet
pszTemp = pszFileName + lstrlen (pszFileName) + 1;
}
// Find the currently selected Language by searching for it in the listbox
if (pszCurrent)
{
count = -1;
nLen = lstrlen (pszCurrent);
while (1)
{
if ((nCurLang = SendMessage (hLBName, CB_FINDSTRING, count,
(LPARAM)pszCurrent)) <= count)
{
// If we can't find a match set to invalid value
nCurLang = -1;
break;
}
if (SendMessage (hLBName, CB_GETLBTEXTLEN, nCurLang, 0L) == nLen)
break;
count = nCurLang;
}
}
// Find the default Language by searching for it in the listbox
if (pszDefault)
{
count = -1;
nLen = lstrlen (pszDefault);
while (1)
{
if ((nDefault = SendMessage (hLBName, CB_FINDSTRING, count,
(LPARAM) pszDefault)) <= count)
{
// If we can't find a match set to invalid value
nDefault = -1;
break;
}
if (SendMessage (hLBName, CB_GETLBTEXTLEN, nDefault, 0L) == nLen)
break;
count = nDefault;
}
}
if (nCurLang == -1)
{
// LangDLLFailure:
// Set ultimate default selection if nothing found
nCurLang = (nDefault == -1) ? 0 : nDefault;
}
SendMessage (hLBName, CB_SETCURSEL, nCurLang, 0L);
//////////////////////////////////////////////////////////////////////////
// Get option lists from .INF files, select USER defaults for Layout
//////////////////////////////////////////////////////////////////////////
#if KEYBOARDHARDWARECHANGABLE
/* Get the keyboard section
*/
hLBName = GetDlgItem (hDlg, INTL_KEYBOARD);
LoadString (hModule, KBD + 2, szLBEntry, CharSizeOf(szLBEntry));
nDefault = -1;
nCurKbd = -1;
pszCurrent = NULL;
pszDefault = NULL;
// pszAnsi = GetAllOptionsText ("LAYOUT", GetUserDefaultLangID());
// pszAnsi = GetAllOptionsText ("LAYOUT", LANG_ENGLISH);
pszAnsi = GetAllOptionsText ("LAYOUT", 0);
pLayouts = pszTemp = (LPTSTR) pszAnsi;
// Check for api errors and NoOptions
if ((pszAnsi == NULL) || ((*pszAnsi == '\0') && (*(pszAnsi+1) == '\0')))
goto Error1;
#ifdef UNICODE
if (pszAnsi)
{
// Get size of buffer pointed to by pszAnsi
for (nLen = 0; ;pszAnsi++)
{
nLen++;
if (*pszAnsi == '\0' && *(pszAnsi+1) == '\0')
break;
}
nLen += 2;
pszAnsi = (LPSTR) pszTemp;
pLayouts = pszTemp = (LPTSTR) LocalAlloc (LPTR, nLen*2);
MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, pszAnsi, nLen, pLayouts, nLen);
LocalFree ((HLOCAL) pszAnsi);
}
#endif
// Continue until we reach end of buffer, marked by Double '\0'
while (*pszTemp != TEXT('\0'))
{
// Get a ptr to each of item in the triplet strings returned
pszOption = pszTemp;
pszOptionText = pszOption + lstrlen (pszOption) + 1;
pszFileName = pszOptionText + lstrlen (pszOptionText) + 1;
nPlace = SendMessage (hLBName, CB_ADDSTRING, (DWORD) -1, (LPARAM)pszOptionText);
// Save ptr to Filename and Option strings for later use with SETUP
SendMessage (hLBName, CB_SETITEMDATA, nPlace, (LPARAM)pszOption);
// Find OPTION that matches User's selection
//
// Since this is a sorted Combo-box, we must save a ptr to the
// OptionText for both current and default selections. Later we
// will perform a search to get the actual cbox index of the
// matching selections.
if (!lstrcmpi (pszOption, szLayout))
pszCurrent = pszOptionText;
// Find selection matching our "Default", for possible use below
if (!lstrcmpi (pszOption, szLBEntry))
pszDefault = pszOptionText;
// Point to next triplet
pszTemp = pszFileName + lstrlen (pszFileName) + 1;
}
// Find the currently selected Layout by searching for it in the listbox
if (pszCurrent)
{
count = -1;
nLen = lstrlen (pszCurrent);
while (1)
{
if ((nCurKbd = SendMessage (hLBName, CB_FINDSTRING, count,
(LPARAM)pszCurrent)) <= count)
{
// If we can't find a match set to invalid value
nCurKbd = -1;
break;
}
if (SendMessage (hLBName, CB_GETLBTEXTLEN, nCurKbd, 0L) == nLen)
break;
count = nCurKbd;
}
}
// Find the default Layout by searching for it in the listbox
if (pszDefault)
{
count = -1;
nLen = lstrlen (pszDefault);
while (1)
{
if ((nDefault = SendMessage (hLBName, CB_FINDSTRING, count,
(LPARAM)pszDefault)) <= count)
{
// If we can't find a match set to invalid value
nDefault = -1;
break;
}
if (SendMessage (hLBName, CB_GETLBTEXTLEN, nDefault, 0L) == nLen)
break;
count = nDefault;
}
}
if (nCurKbd == -1)
{
// CannotFindKbdDll:
// Set ultimate default selection if nothing found
nCurKbd = (nDefault == -1) ? 0 : nDefault;
}
SendMessage (hLBName, CB_SETCURSEL, nCurKbd, 0L);
#endif // KEYBOARDHARDWARECHANGABLE
/* Set up measurement systems (English and Metric)
*/
for (count = 0; count < MEASUREMENTSYSTEMS; count++)
{
LoadString (hModule, (WORD) (count + MEASUREMENTSYS), szLBEntry, CharSizeOf(szLBEntry));
SendDlgItemMessage (hDlg, INTL_MEASUREMENT, CB_ADDSTRING, 0L,
(LPARAM)szLBEntry);
}
/* now fill the dialog box */
FillIntlDlg (hDlg, &Current, FALSE);
SendDlgItemMessage (hDlg, INTL_LISTSEP, EM_LIMITTEXT, 1, 0L);
return (TRUE); /* made it past error exits */
Error1:
// Free memory from SETUP api calls
if (pLocales != NULL)
LocalFree ((HLOCAL) pLocales);
if (pLayouts != NULL)
LocalFree ((HLOCAL) pLayouts);
MyMessageBox (hDlg, INTL + 8, INITS + 1, MB_OK | MB_ICONINFORMATION);
return (FALSE);
}
/*
* Use GetLocaleInfo NLS api to get the value for the given lctype.
* If no user override is to be used (want system default), then
* the caller must pass in the LOCALE_NOUSEROVERRIDE flag as part
* of the lctype. It returns the Integer value of the returned
* string (if appropriate).
*/
int GetLocaleValue(
LCID lcid,
LCTYPE lcType,
TCHAR *pszStr,
int size,
LPTSTR pszDefault )
{
/*
* Initialize the output buffer.
*/
*pszStr = (TCHAR) 0;
/*
* Get the locale information.
*/
if (!GetLocaleInfo ( lcid,
lcType,
pszStr,
size ))
{
/*
* Couldn't get info from GetLocaleInfo.
*/
if (pszDefault)
{
/*
* Return the default info.
*/
lstrcpy (pszStr, pszDefault);
}
else
{
/*
* Return error.
*/
return (-1);
}
}
/*
* Convert the string to an integer and return the result.
* This will only be used by the caller of this routine when
* appropriate.
*/
return ( MyAtoi (pszStr) );
}
/*
* This routine reads the pszCountry string, which contains
* the current country string read from the inf file,
* and builds an INTLSTRUCT pointed by pIntl.
*/
STATIC void DecodeCountryString(
PINTL pIntl)
{
TCHAR szwork[128];
LCID lcid = pIntl->lcid;
/*
* Get language and country information.
*/
GetLocaleValue (lcid,
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
pIntl->sLanguage,
CharSizeOf(pIntl->sLanguage),
IntlDef.sLanguage);
GetLocaleValue (lcid,
LOCALE_SCOUNTRY | LOCALE_NOUSEROVERRIDE,
pIntl->sCountry,
CharSizeOf(pIntl->sCountry),
DefIStr.lcid);
pIntl->iCountry = GetLocaleValue (lcid,
LOCALE_ICOUNTRY | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iCountry);
/*
* Get list separator and measurement information.
*/
GetLocaleValue (lcid,
LOCALE_SLIST | LOCALE_NOUSEROVERRIDE,
pIntl->sList,
CharSizeOf(pIntl->sList),
IntlDef.sList);
pIntl->iMeasure = GetLocaleValue (lcid,
LOCALE_IMEASURE | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iMeasure);
/*
* Get number format information.
*/
GetLocaleValue (lcid,
LOCALE_STHOUSAND | LOCALE_NOUSEROVERRIDE,
pIntl->sThousand,
CharSizeOf(pIntl->sThousand),
IntlDef.sThousand);
GetLocaleValue (lcid,
LOCALE_SDECIMAL | LOCALE_NOUSEROVERRIDE,
pIntl->sDecimal,
CharSizeOf(pIntl->sDecimal),
IntlDef.sDecimal);
pIntl->iDigits = GetLocaleValue (lcid,
LOCALE_IDIGITS | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iDigits);
pIntl->iLzero = GetLocaleValue (lcid,
LOCALE_ILZERO | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iLzero);
pIntl->iNegNumber = GetLocaleValue (lcid,
LOCALE_INEGNUMBER | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iNegNumber);
/*
* Get currency format information.
*/
GetLocaleValue (lcid,
LOCALE_SCURRENCY | LOCALE_NOUSEROVERRIDE,
pIntl->sCurrency,
CharSizeOf(pIntl->sCurrency),
IntlDef.sCurrency);
GetLocaleValue (lcid,
LOCALE_SMONTHOUSANDSEP | LOCALE_NOUSEROVERRIDE,
pIntl->sMonThousand,
CharSizeOf(pIntl->sMonThousand),
IntlDef.sMonThousand);
GetLocaleValue (lcid,
LOCALE_SMONDECIMALSEP | LOCALE_NOUSEROVERRIDE,
pIntl->sMonDecimal,
CharSizeOf(pIntl->sMonDecimal),
IntlDef.sMonDecimal);
pIntl->iCurDec = GetLocaleValue (lcid,
LOCALE_ICURRDIGITS | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iCurDec);
pIntl->iCurFmt = GetLocaleValue (lcid,
LOCALE_ICURRENCY | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iCurFmt);
pIntl->iNegCur = GetLocaleValue (lcid,
LOCALE_INEGCURR | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iNegCur);
/*
* Get time format information.
*/
GetLocaleValue (lcid,
LOCALE_STIMEFORMAT | LOCALE_NOUSEROVERRIDE,
pIntl->sTimeFormat,
CharSizeOf(pIntl->sTimeFormat),
IntlDef.sTimeFormat);
GetLocaleValue (lcid,
LOCALE_STIME | LOCALE_NOUSEROVERRIDE,
pIntl->sTime,
CharSizeOf(pIntl->sTime),
IntlDef.sTime);
pIntl->iTime = GetLocaleValue (lcid,
LOCALE_ITIME | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iTime);
pIntl->iTLZero = GetLocaleValue (lcid,
LOCALE_ITLZERO | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iTLZero);
pIntl->iTimeMarker = GetLocaleValue (lcid,
LOCALE_ITIMEMARKPOSN | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iTimeMarker);
GetLocaleValue (lcid,
LOCALE_S1159 | LOCALE_NOUSEROVERRIDE,
pIntl->s1159,
CharSizeOf(pIntl->s1159),
IntlDef.s1159);
GetLocaleValue (lcid,
LOCALE_S2359 | LOCALE_NOUSEROVERRIDE,
pIntl->s2359,
CharSizeOf(pIntl->s2359),
IntlDef.s2359);
/*
* Get date format information.
*/
GetLocaleValue (lcid,
LOCALE_SSHORTDATE | LOCALE_NOUSEROVERRIDE,
pIntl->sShortDate,
CharSizeOf(pIntl->sShortDate),
IntlDef.sShortDate);
GetLocaleValue (lcid,
LOCALE_SDATE | LOCALE_NOUSEROVERRIDE,
pIntl->sDateSep,
CharSizeOf(pIntl->sDateSep),
IntlDef.sDateSep);
pIntl->iDate = GetLocaleValue (lcid,
LOCALE_IDATE | LOCALE_NOUSEROVERRIDE,
szwork,
CharSizeOf(szwork),
DefIStr.iDate);
GetLocaleValue (lcid,
LOCALE_SLONGDATE | LOCALE_NOUSEROVERRIDE,
pIntl->sLongDate,
CharSizeOf(pIntl->sLongDate),
IntlDef.sLongDate);
}
/*
* This gets the new country information and updates the dialog.
*/
STATIC void ChangeCountry(
HWND hDlg)
{
int nNation;
LCID lcid;
/* First check if this is the current country, and if we have enough room
* in the buffer for the string (all reasonable strings will be OK)
* Notice that LB_ERR >= any WORD
*/
if ((nNation = SendDlgItemMessage (hDlg, INTL_COUNTRY, CB_GETCURSEL, 0, 0L))
== nCurCountry)
return;
lcid = (LCID) SendDlgItemMessage (hDlg, INTL_COUNTRY, CB_GETITEMDATA,
nCurCountry = nNation, 0L);
if (lcid == Current.lcid)
return;
else
Current.lcid = lcid;
DecodeCountryString (&Current);
TranslateShortDate (&Current);
FillIntlDlg (hDlg, &Current, TRUE);
}
/*
* This changes the system and ini files to reflect the new choice
* for language or keyboard driver.
*/
STATIC BOOL ChangeDriver(
HWND hDlg,
short nID)
{
short nOriginal, nCurrent;
HWND hCB;
LPTSTR pszInfFile, pszOption, pszOptionText;
HKEY hkey;
/*
* Determine what we are talking about, and get the two windows.
*/
nOriginal = (nID == INTL_LANGUAGE) ? nCurLang : nCurKbd;
hCB = GetDlgItem(hDlg, nID);
/*
* Get the current data string.
*/
if ((nCurrent = (short)SendMessage(hCB, CB_GETCURSEL, 0, 0L)) == nOriginal)
return (TRUE);
//
// Check for invalid selection or error return from User api
//
if ((nCurrent == 0xFFFF) || (nCurrent == (short)CB_ERR) ||
(nCurrent == (short)CB_ERRSPACE))
return (TRUE);
pszOption = (LPTSTR) SendMessage (hCB, CB_GETITEMDATA, nCurrent, 0L);
pszOptionText = pszOption + lstrlen (pszOption) + 1;
pszInfFile = pszOptionText + lstrlen (pszOptionText) + 1;
if (nID == INTL_LANGUAGE)
{
/*
* Verify that we can install this option - by checking for
* write permission to registry key.
*/
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, szInstalledLocales,
0L, KEY_WRITE, &hkey))
{
/*
* We can write to the HKEY_LOCAL_MACHINE key, close
* and call setup.
*/
RegCloseKey (hkey);
}
else
goto CannotInstallOption;
}
else
{
// See if this LAYOUT option is already installed on system before
// calling off to SETUP to install it
if (CheckOptionInstall (szInstalledLayouts, pszOption))
{
// LAYOUT installed. Set it for current user
if (LoadKeyboardLayout (pszOption,
KLF_ACTIVATE | KLF_UNLOADPREVIOUS) != 0)
{
return (TRUE);
}
else
{
// Load failure, Failsafe is to try to install it again
goto InstallKeybd;
}
}
else
{
InstallKeybd:
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, szInstalledLayouts,
0L, KEY_WRITE, &hkey))
{
// We can write to the HKEY_LOCAL_MACHINE key, close
// and call setup
RegCloseKey (hkey);
}
else
goto CannotInstallOption;
}
}
if (!InvokeSetup (hDlg, pszInfFile, pszOption))
goto FailureExit;
//
// REMOVE THIS FOR PRODUCT11 [julieb 6/23/93]
//
// Set the Locale value in the user's control panel international
// section of the registry so that GetThreadLocale will return the
// correct result. This should be removed when locales are on
// a per user basis.
//
if (nID == INTL_LANGUAGE)
{
if (!RegOpenKeyEx (HKEY_CURRENT_USER, szRegCPIntl, 0L, KEY_WRITE, &hkey))
{
RegSetValueEx (hkey, szRegLocale, 0L, REG_SZ,
(LPBYTE)pszOption, ByteCountOf(lstrlen(pszOption) + 1));
RegCloseKey (hkey);
}
}
return (TRUE);
CannotInstallOption:
// Put up a message box error stating that the USER does
// not have correct privilege to install a new option on
// the system - contact System Administrator
MyMessageBox (hDlg, INTL+11, INITS+1, MB_OK | MB_ICONINFORMATION);
// fall thru...
FailureExit:
// If SETUP fails or if User does not have enough permission to
// change this option, reset original selection in ComboBox
SendMessage(hCB, CB_SETCURSEL, nOriginal, 0L);
return (FALSE);
}
/*
* InvokeSetup
*
* Call the SETUP.EXE program to install an option listed in an .INF file.
* The SETUP program will make the correct registry entries for this option
* under both HKEY_LOCAL_MACHINE and HKEY_CURRENT_USER. It will set the
* new default value for the USER (i.e. a new locale or keyboard layout).
*
*
* FIX FIX FIX [stevecat] Need to make a better choice for SRCDIR and
* STF_LANGUAGE based on some user preference.
*/
BOOL InvokeSetup(
HWND hDlg,
LPTSTR pszInfFile,
LPTSTR pszOption)
{
TCHAR szCmdSetup[1024];
TCHAR *pszSetup = TEXT("setup -f -i %s /t STF_LANGUAGE = ENG /t OPTION = %s \
/s A:\\ /t ADDCOPY = YES /t DOCOPY = YES \
/c ExternalInstallOption /t DOCONFIG = YES");
MSG Msg;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInformation;
BOOL b;
DWORD dwExitCode;
// Create comamnd line to invoke SETUP program
wsprintf (szCmdSetup, pszSetup, pszInfFile, pszOption);
// WinExec (szCmdSetup, SW_SHOW);
// Create setup process
memset (&StartupInfo, 0, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
StartupInfo.wShowWindow = SW_SHOW;
b = CreateProcess ( NULL,
szCmdSetup, // CommandLine
NULL,
NULL,
FALSE,
0,
NULL,
pszSysDir, // szCurrentDirectory
&StartupInfo,
&ProcessInformation
);
// If process creation successful, wait for it to
// complete before continuing
if ( b )
{
EnableWindow (hDlg, FALSE);
while (MsgWaitForMultipleObjects (
1,
&ProcessInformation.hProcess,
FALSE,
(DWORD) -1,
QS_ALLEVENTS | QS_SENDMESSAGE) != 0)
{
// This message loop is a duplicate of main
// message loop with the exception of using
// PeekMessage instead of waiting inside of
// GetMessage. Process wait will actually
// be done in MsgWaitForMultipleObjects api.
//
while (PeekMessage (&Msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&Msg);
DispatchMessage (&Msg);
}
}
if (b = GetExitCodeProcess (ProcessInformation.hProcess, &dwExitCode))
b = (dwExitCode == 0);
// b = (dwExitCode == SETUP_ERROR_SUCCESS);
// Close handles and re-enable window
CloseHandle (ProcessInformation.hProcess);
CloseHandle (ProcessInformation.hThread);
EnableWindow (hDlg, TRUE);
// Bring Intl window to foreground, always
SetForegroundWindow (hDlg);
}
return (b);
}
BOOL CheckOptionInstall(
LPTSTR pszRegKey,
LPTSTR pszOption)
{
HKEY hkeyOptions;
TCHAR szValueName[256];
TCHAR szValue[256];
DWORD dwIndex, dwBufz, dwBufv;
BOOL b = FALSE;
if (!RegOpenKeyEx (HKEY_LOCAL_MACHINE, pszRegKey, 0L, KEY_READ, &hkeyOptions))
{
dwBufz = CharSizeOf(szValueName);
dwBufv = sizeof(szValue);
dwIndex = 0;
while (!RegEnumValue (hkeyOptions, dwIndex++, szValueName, &dwBufz,
NULL, NULL, (LPBYTE) szValue, &dwBufv))
{
if (!lstrcmpi (pszOption, szValueName))
{
// Found a matching option - now verify that a string
// value exists for this "pszOption" valuename
// This is done by simply looking for any data.
if (dwBufv > 1)
{
b = TRUE;
break;
}
}
dwBufz = CharSizeOf(szValueName);
dwBufv = sizeof(szValue);
}
RegCloseKey (hkeyOptions);
}
return (b);
}
/*
* This routine updates the international section of WIN.INI. If
* there are any problems with WriteProfileString (), an error
* message is given to the user.
*/
STATIC BOOL WriteIntlWin(
HWND hDlg)
{
int item; /* iterative */
TCHAR szCountry[128]; /* needed for strings storage */
TCHAR sziCountry[6];
TCHAR sziCurFmt[2];
TCHAR sziCurDec[3];
TCHAR sziNegCur[3];
TCHAR sziLzero[2];
TCHAR sziDigits[2];
TCHAR sziMeasure[2];
TCHAR sziTimeMarker[2];
TCHAR sziNegNumber[2];
/*
* Get country code.
*/
item = (short)SendDlgItemMessage (hDlg, INTL_COUNTRY, CB_GETCURSEL, 0, 0L);
if (item != CB_ERR)
{
SendDlgItemMessage (hDlg, INTL_COUNTRY, CB_GETLBTEXT, item,
(LPARAM) szCountry);
}
else
lstrcpy (szCountry, IntlDef.sCountry);
/*
* Change the language and keyboard drivers.
*/
if (!ChangeDriver (hDlg, INTL_LANGUAGE) || !ChangeDriver (hDlg, INTL_KEYBOARD))
return (FALSE);
/*
* Show the hour glass.
*/
HourGlass (TRUE);
/*
* Convert the integers to strings so that they can be written
* to the registry.
*/
MyItoa (Current.iCountry, sziCountry, 10);
MyItoa (Current.iCurFmt, sziCurFmt, 10);
MyItoa (Current.iCurDec, sziCurDec, 10);
MyItoa (Current.iNegCur, sziNegCur, 10);
MyItoa (Current.iLzero, sziLzero, 10);
MyItoa (Current.iDigits, sziDigits, 10);
item = (short)SendDlgItemMessage (hDlg, INTL_MEASUREMENT, CB_GETCURSEL, 0, 0L);
MyItoa (item, sziMeasure, 10);
MyItoa (Current.iTimeMarker, sziTimeMarker, 10);
MyItoa (Current.iNegNumber, sziNegNumber, 10);
/*
* Set language and country information.
*/
WriteProfileString (szIntl, TEXT("sLanguage"), Current.sLanguage);
WriteProfileString (szIntl, TEXT("sCountry"), Current.sCountry);
WriteProfileString (szIntl, TEXT("iCountry"), sziCountry);
/*
* Set list separator and measurement information.
*/
GetDlgItemText (hDlg, INTL_LISTSEP, Current.sList, CharSizeOf(Current.sList));
SetLocaleInfo (0, LOCALE_SLIST, Current.sList);
SetLocaleInfo (0, LOCALE_IMEASURE, sziMeasure);
/*
* Set number format information.
*/
SetLocaleInfo (0, LOCALE_STHOUSAND, Current.sThousand);
SetLocaleInfo (0, LOCALE_SDECIMAL, Current.sDecimal);
SetLocaleInfo (0, LOCALE_IDIGITS, sziDigits);
SetLocaleInfo (0, LOCALE_ILZERO, sziLzero);
SetLocaleInfo (0, LOCALE_INEGNUMBER, sziNegNumber);
/*
* Set currency format information.
*/
SetLocaleInfo (0, LOCALE_SCURRENCY, Current.sCurrency);
SetLocaleInfo (0, LOCALE_SMONTHOUSANDSEP, Current.sMonThousand);
SetLocaleInfo (0, LOCALE_SMONDECIMALSEP, Current.sMonDecimal);
SetLocaleInfo (0, LOCALE_ICURRDIGITS, sziCurDec);
SetLocaleInfo (0, LOCALE_ICURRENCY, sziCurFmt);
SetLocaleInfo (0, LOCALE_INEGCURR, sziNegCur);
/*
* Set time format information.
*
* Setting the STIMEFORMAT value also sets the values for
* STIME, ITIME, and ITLZERO.
*/
SetLocaleInfo (0, LOCALE_STIMEFORMAT, Current.sTimeFormat);
WriteProfileString(szIntl, TEXT("iTimePrefix"), sziTimeMarker);
SetLocaleInfo (0, LOCALE_S1159, Current.s1159);
SetLocaleInfo (0, LOCALE_S2359, Current.s2359);
/*
* Set date format information.
*
* Setting the SSHORTDATE value also sets the values for
* SDATE and IDATE.
*/
SetLocaleInfo (0, LOCALE_SSHORTDATE, Current.sShortDate);
SetLocaleInfo (0, LOCALE_SLONGDATE, Current.sLongDate);
/*
* Stop showing the hour glass.
*/
HourGlass (FALSE);
/*
* Broadcast the winini change message.
*/
SendWinIniChange (szIntl);
/*
* Return success.
*/
return (TRUE);
}
/*
* Handle any button pushing or listbox changes in the intl dialog.
*/
STATIC void IntlDlgCommand(
HWND hDlg,
int id,
HWND hWndCtl,
int codeCtl)
{
BOOL bOK;
switch (id)
{
case IDOK:
HourGlass (TRUE);
bOK = WriteIntlWin (hDlg); /* update WIN.INI */
HourGlass (FALSE);
if (!bOK)
break;
/* fall through */
case IDCANCEL:
wFontHeight = 0; /* Clear out global variable */
// Free memory from SETUP api calls
if (pLocales != NULL)
LocalFree ((HLOCAL) pLocales);
if (pLayouts != NULL)
LocalFree ((HLOCAL) pLayouts);
EndDialog (hDlg, 0L); /* end this party (was OK) */
break;
case INTL_COUNTRY:
if (codeCtl == CBN_SELCHANGE)
ChangeCountry (hDlg);
break;
case INTL_DATECHANGE:
case INTL_DATECHANGE2:
case INTL_DATEACCEL:
DoDialogBoxParam (DLG_INTLDATE, hDlg, (DLGPROC) DateIntlDlg,
IDH_DLG_INTLDATE, 0L);
SetDateSamples (hDlg, &Current);
break;
case INTL_TIMECHANGE:
case INTL_TIMECHANGE2:
case INTL_TIMEACCEL:
DoDialogBoxParam (DLG_INTLTIME, hDlg, (DLGPROC) TimeIntlDlg,
IDH_DLG_INTLTIME, 0L);
SetTimeSamples (hDlg, &Current, FALSE);
break;
case INTL_NUMCHANGE:
case INTL_NUMCHANGE2:
case INTL_NUMACCEL:
DoDialogBoxParam (DLG_INTLNUM, hDlg, (DLGPROC) NumIntlDlg,
IDH_DLG_INTLNUM, 0L);
SetNumSamples (hDlg, &Current, FALSE);
break;
case INTL_CURCHANGE:
case INTL_CURCHANGE2:
case INTL_CURACCEL:
DoDialogBoxParam (DLG_INTLCUR, hDlg, (DLGPROC) CurIntlDlg,
IDH_DLG_INTLCUR, 0L);
SetCurSamples (hDlg, &Current, FALSE);
break;
case INTL_LANGUAGE:
#if KEYBOARDHARDWARECHANGABLE
case INTL_KEYBOARD:
#endif
default:
break;
}
UNREFERENCED_PARAMETER(hWndCtl);
}
/*****************************************************/
/******************** public functions ***************/
/*****************************************************/
/*
* This routine parses the date format string into the pLDF structure.
*/
void ParseLDF(
LPTSTR pszLDate,
PLDF pLDF)
{
short i;
WORD wLen;
TCHAR szBuf[128];
int nLen;
/* Check for a leading day and separator
* (like "Mon, 26 June")
*/
wLen = GetLDFToken (pszLDate, szBuf);
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
if (((wLen & 0xF0) == LDF_DAY && (wLen & 0x0F) > 2) ||
((wLen & 0xF0) == LDF_JaDAY && (wLen & 0x0F) && (wLen & 0x0F) < 3))
#else
if (((wLen & 0xF0) == LDF_DAY) && ((wLen & 0x0F) > 2))
#endif
{
pLDF->Leadin = wLen;
wLen = GetLDFToken (pszLDate += (wLen & 0x0F), szBuf);
}
else
pLDF->Leadin = 0;
if ((wLen & 0xF0) >= LDF_SEP)
{
nLen = CharSizeOf(pLDF->LeadinSep) - 1;
_tcsncpy (pLDF->LeadinSep, szBuf, nLen);
// Properly NULL terminate string
pLDF->LeadinSep[nLen] = TEXT('\0');
wLen = GetLDFToken (pszLDate += (wLen - LDF_SEP), szBuf);
}
else
pLDF->LeadinSep[0] = TEXT('\0');
/* Get the order of the date parts, the lengths,
* and the separators
*/
for (i = 0; i < 3 && wLen; i++)
{
switch (wLen & 0xF0)
{
case LDF_DAY:
case LDF_MONTH:
case LDF_YEAR:
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
case LDF_JaYEAR:
#endif
pLDF->Order[i] = wLen;
break;
default:
pLDF->Order[i] = (WORD) (((MONTH + i) << 4) & 1);
break;
}
/* Get the separator if another field to go;
* set to null string if no separator
*/
#ifndef JAPAN
if (i < 2)
#endif
{
wLen = GetLDFToken (pszLDate += (wLen & 0x0F), szBuf);
if ((wLen & 0xF0) >= LDF_SEP)
{
nLen = CharSizeOf(pLDF->Sep[0]) - 1;
_tcsncpy (pLDF->Sep[i], szBuf, nLen);
// Properly NULL terminate string
pLDF->Sep[i][nLen] = TEXT('\0');
wLen = GetLDFToken (pszLDate += (wLen - LDF_SEP), szBuf);
}
else
pLDF->Sep[i][0] = TEXT('\0');
}
}
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// LONG_DATE_FORMAT
// see trailing 'day of the week' for Japanese
pLDF->Trailin = 0;
if (!pLDF->Leadin)
{
wLen = GetLDFToken (pszLDate, szBuf);
if (((wLen & 0xF0) == LDF_DAY && (wLen & 0x0F) > 2) ||
((wLen & 0xF0) == LDF_JaDAY && (wLen & 0x0F) && (wLen & 0x0F) < 3))
{
pLDF->Leadin = wLen;
pLDF->Trailin = 1;
}
}
if (wLen = pLDF->Leadin)
{
if ((wLen & 0x0F) <= 2)
pLDF->Leadin += 2; // offset japanese day format
}
#endif
}
/*
* This is the dialog procedure for the international dialog.
*/
BOOL APIENTRY IntlDlg(
HWND hDlg,
UINT message,
DWORD wParam,
LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
#ifdef JAPAN /* V-KeijiY June.30.1992 */
// Set initial font height is required since dialog box doesn't
// contains font information.
if (!wFontHeight)
{
TEXTMETRIC TM;
HDC hDC = GetDC(hDlg);
GetTextMetrics(hDC, &TM);
ReleaseDC(hDlg, hDC);
wFontHeight = (WORD) TM.tmHeight;
}
#endif
{
BOOL bSuccess;
HourGlass (TRUE);
bSuccess = InitIntlDlg (hDlg);
HourGlass (FALSE);
if (!bSuccess)
EndDialog (hDlg, OUT_OF_MEM);
break;
}
case WM_COMMAND:
if (LOWORD (wParam) == IDD_HELP)
goto DoHelp;
else
IntlDlgCommand (hDlg, LOWORD(wParam), (HWND) lParam, (LONG) HIWORD(wParam));
break;
default:
if (message == wHelpMessage)
{
DoHelp:
CPHelp (hDlg);
}
else
return (FALSE);
}
return (TRUE);
}