Leaked source code of windows server 2003
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.

557 lines
15 KiB

  1. /////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1998 Active Voice Corporation. All Rights Reserved.
  4. //
  5. // Active Agent(r) and Unified Communications(tm) are trademarks of Active Voice Corporation.
  6. //
  7. // Other brand and product names used herein are trademarks of their respective owners.
  8. //
  9. // The entire program and user interface including the structure, sequence, selection,
  10. // and arrangement of the dialog, the exclusively "yes" and "no" choices represented
  11. // by "1" and "2," and each dialog message are protected by copyrights registered in
  12. // the United States and by international treaties.
  13. //
  14. // Protected by one or more of the following United States patents: 5,070,526, 5,488,650,
  15. // 5,434,906, 5,581,604, 5,533,102, 5,568,540, 5,625,676, 5,651,054.
  16. //
  17. // Active Voice Corporation
  18. // Seattle, Washington
  19. // USA
  20. //
  21. /////////////////////////////////////////////////////////////////////////////////////////
  22. ////
  23. // intl.c - internationalization functions
  24. ////
  25. #include "winlocal.h"
  26. #include <stdlib.h>
  27. #include "intl.h"
  28. #include "mem.h"
  29. #include "str.h"
  30. #include "trace.h"
  31. ////
  32. // private definitions
  33. ////
  34. // intl control struct
  35. //
  36. typedef struct INTL
  37. {
  38. DWORD dwVersion;
  39. HINSTANCE hInst;
  40. HTASK hTask;
  41. TCHAR szShortDate[32];
  42. TCHAR szDateSep[32];
  43. TCHAR szTimeSep[32];
  44. TCHAR szAMPMSep[32];
  45. TCHAR szAM[32];
  46. TCHAR szPM[32];
  47. int iDate;
  48. int iTime;
  49. int iTLZero;
  50. BOOL fYearCentury;
  51. BOOL fMonthLeadingZero;
  52. BOOL fDayLeadingZero;
  53. BOOL fHourLeadingZero;
  54. BOOL fMinuteLeadingZero;
  55. BOOL fSecondLeadingZero;
  56. int iLZero;
  57. TCHAR szDecimal[32];
  58. } INTL, FAR *LPINTL;
  59. // helper functions
  60. //
  61. static LPINTL IntlGetPtr(HINTL hIntl);
  62. static HINTL IntlGetHandle(LPINTL lpIntl);
  63. ////
  64. // public functions
  65. ////
  66. // IntlInit - initialize intl engine
  67. // <dwVersion> (i) must be INTL_VERSION
  68. // <hInst> (i) instance handle of calling module
  69. // return handle (NULL if error)
  70. //
  71. HINTL DLLEXPORT WINAPI IntlInit(DWORD dwVersion, HINSTANCE hInst)
  72. {
  73. BOOL fSuccess = TRUE;
  74. LPINTL lpIntl = NULL;
  75. if (dwVersion != INTL_VERSION)
  76. fSuccess = TraceFALSE(NULL);
  77. else if (hInst == NULL)
  78. fSuccess = TraceFALSE(NULL);
  79. else if ((lpIntl = (LPINTL) MemAlloc(NULL, sizeof(INTL), 0)) == NULL)
  80. fSuccess = TraceFALSE(NULL);
  81. else
  82. {
  83. lpIntl->dwVersion = dwVersion;
  84. lpIntl->hInst = hInst;
  85. lpIntl->hTask = GetCurrentTask();
  86. GetProfileString(TEXT("intl"), TEXT("sShortDate"), TEXT("M/d/yy"), lpIntl->szShortDate, SIZEOFARRAY(lpIntl->szShortDate));
  87. GetProfileString(TEXT("intl"), TEXT("sDate"), TEXT("/"), lpIntl->szDateSep, SIZEOFARRAY(lpIntl->szDateSep));
  88. GetProfileString(TEXT("intl"), TEXT("sTime"), TEXT(":"), lpIntl->szTimeSep, SIZEOFARRAY(lpIntl->szTimeSep));
  89. StrCpy(lpIntl->szAMPMSep, TEXT(" "));
  90. GetProfileString(TEXT("intl"), TEXT("s1159"), TEXT("AM"), lpIntl->szAM, SIZEOFARRAY(lpIntl->szAM));
  91. GetProfileString(TEXT("intl"), TEXT("s2359"), TEXT("PM"), lpIntl->szPM, SIZEOFARRAY(lpIntl->szPM));
  92. lpIntl->iDate = GetProfileInt(TEXT("intl"), TEXT("iDate"), 0);
  93. lpIntl->iTime = GetProfileInt(TEXT("intl"), TEXT("iTime"), 0);
  94. lpIntl->iTLZero = GetProfileInt(TEXT("intl"), TEXT("iTLZero"), 0);
  95. lpIntl->fYearCentury = (BOOL) (StrStr(lpIntl->szShortDate, TEXT("yyyy")) != NULL);
  96. lpIntl->fMonthLeadingZero = (BOOL) (StrStr(lpIntl->szShortDate, TEXT("MM")) != NULL);
  97. lpIntl->fDayLeadingZero = (BOOL) (StrStr(lpIntl->szShortDate, TEXT("dd")) != NULL);
  98. lpIntl->fHourLeadingZero = (BOOL) (lpIntl->iTLZero != 0);
  99. lpIntl->fMinuteLeadingZero = TRUE;
  100. lpIntl->fSecondLeadingZero = TRUE;
  101. lpIntl->iLZero = GetProfileInt(TEXT("intl"), TEXT("iLZero"), 0);
  102. GetProfileString(TEXT("intl"), TEXT("sDecimal"), TEXT("."), lpIntl->szDecimal, SIZEOFARRAY(lpIntl->szDecimal));
  103. }
  104. if (!fSuccess)
  105. {
  106. IntlTerm(IntlGetHandle(lpIntl));
  107. lpIntl = NULL;
  108. }
  109. return fSuccess ? IntlGetHandle(lpIntl) : NULL;
  110. }
  111. // IntlTerm - shut down intl engine
  112. // <hIntl> (i) handle returned from IntlInit
  113. // return 0 if success
  114. //
  115. int DLLEXPORT WINAPI IntlTerm(HINTL hIntl)
  116. {
  117. BOOL fSuccess = TRUE;
  118. LPINTL lpIntl;
  119. if ((lpIntl = IntlGetPtr(hIntl)) == NULL)
  120. fSuccess = TraceFALSE(NULL);
  121. else if ((lpIntl = MemFree(NULL, lpIntl)) != NULL)
  122. fSuccess = TraceFALSE(NULL);
  123. return fSuccess ? 0 : -1;
  124. }
  125. // IntlDateGetText - construct date text based on <y>, <m>, <d>
  126. // <hIntl> (i) handle returned from IntlInit
  127. // <y> (i) year
  128. // <m> (i) month
  129. // <d> (i) day
  130. // <lpszText> (o) buffer to copy date text
  131. // <sizText> (i) size of buffer
  132. // <dwFlags> (i) option flags
  133. // INTL_NOYEAR do not include year in text output
  134. // return 0 if success
  135. //
  136. int DLLEXPORT WINAPI IntlDateGetText(HINTL hIntl, int y, int m, int d, LPTSTR lpszText, size_t sizText, DWORD dwFlags)
  137. {
  138. BOOL fSuccess = TRUE;
  139. LPINTL lpIntl;
  140. if ((lpIntl = IntlGetPtr(hIntl)) == NULL)
  141. fSuccess = TraceFALSE(NULL);
  142. else if (lpszText != NULL)
  143. {
  144. TCHAR szYear[16];
  145. TCHAR szMonth[16];
  146. TCHAR szDay[16];
  147. TCHAR szText[64];
  148. *szYear = '\0';
  149. if (!lpIntl->fYearCentury)
  150. y %= 100;
  151. if (y < 10)
  152. StrCat(szYear, TEXT("0"));
  153. StrItoA(y, StrChr(szYear, '\0'), 10);
  154. *szMonth = '\0';
  155. if (lpIntl->fMonthLeadingZero && m < 10)
  156. StrCat(szMonth, TEXT("0"));
  157. StrItoA(m, StrChr(szMonth, '\0'), 10);
  158. *szDay = '\0';
  159. if (lpIntl->fDayLeadingZero && d < 10)
  160. StrCat(szDay, TEXT("0"));
  161. StrItoA(d, StrChr(szDay, '\0'), 10);
  162. *szText = '\0';
  163. if (lpIntl->iDate == IDATE_MDY)
  164. {
  165. StrCat(szText, szMonth);
  166. StrCat(szText, lpIntl->szDateSep);
  167. StrCat(szText, szDay);
  168. if (!(dwFlags & INTL_NOYEAR))
  169. {
  170. StrCat(szText, lpIntl->szDateSep);
  171. StrCat(szText, szYear);
  172. }
  173. }
  174. else if (lpIntl->iDate == IDATE_DMY)
  175. {
  176. StrCat(szText, szDay);
  177. StrCat(szText, lpIntl->szDateSep);
  178. StrCat(szText, szMonth);
  179. if (!(dwFlags & INTL_NOYEAR))
  180. {
  181. StrCat(szText, lpIntl->szDateSep);
  182. StrCat(szText, szYear);
  183. }
  184. }
  185. else if (lpIntl->iDate == IDATE_YMD)
  186. {
  187. if (!(dwFlags & INTL_NOYEAR))
  188. {
  189. StrCat(szText, szYear);
  190. StrCat(szText, lpIntl->szDateSep);
  191. }
  192. StrCat(szText, szMonth);
  193. StrCat(szText, lpIntl->szDateSep);
  194. StrCat(szText, szDay);
  195. }
  196. StrNCpy(lpszText, szText, sizText);
  197. }
  198. return fSuccess ? 0 : -1;
  199. }
  200. // IntlTimeGetText - construct time text based on <h>, <m>, <s>
  201. // <hIntl> (i) handle returned from IntlInit
  202. // <h> (i) hour
  203. // <m> (i) minute
  204. // <s> (i) second
  205. // <lpszText> (o) buffer to copy time text
  206. // <sizText> (i) size of buffer
  207. // <dwFlags> (i) option flags
  208. // INTL_NOSECOND do not include second in text output
  209. // INTL_NOAMPM do not include am or pm in text output
  210. // INTL_NOAMPMSEPARATOR do not include space between time and am/pm
  211. // return 0 if success
  212. //
  213. int DLLEXPORT WINAPI IntlTimeGetText(HINTL hIntl, int h, int m, int s, LPTSTR lpszText, size_t sizText, DWORD dwFlags)
  214. {
  215. BOOL fSuccess = TRUE;
  216. LPINTL lpIntl;
  217. if ((lpIntl = IntlGetPtr(hIntl)) == NULL)
  218. fSuccess = TraceFALSE(NULL);
  219. else if (lpszText != NULL)
  220. {
  221. TCHAR szHour[16];
  222. TCHAR szMinute[16];
  223. TCHAR szSecond[16];
  224. BOOL fPM = FALSE;
  225. TCHAR szText[64];
  226. *szHour = '\0';
  227. if (lpIntl->iTime == ITIME_12)
  228. {
  229. if (h > 11)
  230. fPM = TRUE;
  231. if (h > 12)
  232. h -= 12;
  233. if (h == 0)
  234. h = 12;
  235. }
  236. if (lpIntl->fHourLeadingZero && h < 10)
  237. StrCat(szHour, TEXT("0"));
  238. StrItoA(h, StrChr(szHour, '\0'), 10);
  239. *szMinute = '\0';
  240. if (lpIntl->fMinuteLeadingZero && m < 10)
  241. StrCat(szMinute, TEXT("0"));
  242. StrItoA(m, StrChr(szMinute, '\0'), 10);
  243. *szSecond = '\0';
  244. if (lpIntl->fSecondLeadingZero && s < 10)
  245. StrCat(szSecond, TEXT("0"));
  246. StrItoA(s, StrChr(szSecond, '\0'), 10);
  247. *szText = '\0';
  248. StrCat(szText, szHour);
  249. StrCat(szText, lpIntl->szTimeSep);
  250. StrCat(szText, szMinute);
  251. if (!(dwFlags & INTL_NOSECOND))
  252. {
  253. StrCat(szText, lpIntl->szTimeSep);
  254. StrCat(szText, szSecond);
  255. }
  256. if (!(dwFlags & INTL_NOAMPM))
  257. {
  258. if (!(dwFlags & INTL_NOAMPMSEPARATOR))
  259. StrCat(szText, lpIntl->szAMPMSep);
  260. StrCat(szText, fPM ? lpIntl->szPM : lpIntl->szAM);
  261. }
  262. StrNCpy(lpszText, szText, sizText);
  263. }
  264. return fSuccess ? 0 : -1;
  265. }
  266. // IntlTimeSpanGetText - construct time span text based on <ms>
  267. // <hIntl> (i) handle returned from IntlInit
  268. // <ms> (i) milleseconds
  269. // <nDecimalPlaces> (i) 0, 1, 2, or 3 decimal places for fraction
  270. // <lpszText> (o) buffer to copy time span text
  271. // <sizText> (i) size of buffer
  272. // <dwFlags> (i) option flags
  273. // INTL_HOURS_LZ include hours, even if zero
  274. // INTL_MINUTES_LZ include minutes, even if zero
  275. // INTL_SECONDS_LZ include seconds, even if zero
  276. //
  277. // NOTE: below are some examples
  278. //
  279. // dwFlags ms=7299650 ms=1234 ms=0
  280. // --------------------------------------------------------
  281. // 0 "2:01:39.650" "1.234" "0"
  282. // INTL_HOURS_LZ "2:01:39.650" "0:00:01.234" "0:00:00.000"
  283. // INTL_MINUTES_LZ "2:01:39.650" "0:01.234" "0:00.000"
  284. // INTL_SECONDS_LZ "2:01:39.650" "1.234" "0.000"
  285. //
  286. // dwFlags ms=7299650 ms=1234 ms=0
  287. // --------------------------------------------------------
  288. // 3 "2:01:39.650" "1.234" ".000"
  289. // 2 "2:01:39.65" "1.23" ".00"
  290. // 1 "2:01:39.7" "1.2" ".0"
  291. // 0 "2:01:39" "1" "0"
  292. //
  293. // return 0 if success
  294. //
  295. int DLLEXPORT WINAPI IntlTimeSpanGetText(HINTL hIntl, DWORD ms,
  296. int nDecimalPlaces, LPTSTR lpszText, size_t sizText, DWORD dwFlags)
  297. {
  298. BOOL fSuccess = TRUE;
  299. LPINTL lpIntl;
  300. if ((lpIntl = IntlGetPtr(hIntl)) == NULL)
  301. fSuccess = TraceFALSE(NULL);
  302. else if (lpszText != NULL)
  303. {
  304. long h;
  305. long m;
  306. long s;
  307. long f;
  308. TCHAR szText[64];
  309. // break ms into h, m, s, f
  310. // NOTE: rounding must occur before we break ms
  311. //
  312. if (nDecimalPlaces == 1)
  313. f = (long) ms + 50;
  314. else if (nDecimalPlaces == 2)
  315. f = (long) ms + 5;
  316. else
  317. f = (long) ms;
  318. s = f / 1000;
  319. f = f % 1000;
  320. m = s / 60;
  321. s = s % 60;
  322. h = m / 60;
  323. m = m % 60;
  324. // construct text
  325. //
  326. *szText = '\0';
  327. if (h > 0 || (dwFlags & INTL_HOURS_LZ))
  328. {
  329. if (lpIntl->fHourLeadingZero && h < 10)
  330. StrCat(szText, TEXT("0"));
  331. StrLtoA(h, StrChr(szText, '\0'), 10);
  332. }
  333. if (*szText != '\0' || m > 0 || (dwFlags & INTL_MINUTES_LZ))
  334. {
  335. if (*szText != '\0')
  336. {
  337. StrCat(szText, lpIntl->szTimeSep);
  338. if (lpIntl->fMinuteLeadingZero && m < 10)
  339. StrCat(szText, TEXT("0"));
  340. }
  341. StrLtoA(m, StrChr(szText, '\0'), 10);
  342. }
  343. if (*szText != '\0' || s > 0 || (dwFlags & INTL_SECONDS_LZ) ||
  344. (ms == 0 && nDecimalPlaces == 0))
  345. {
  346. if (*szText != '\0')
  347. {
  348. StrCat(szText, lpIntl->szTimeSep);
  349. if (lpIntl->fSecondLeadingZero && s < 10)
  350. StrCat(szText, TEXT("0"));
  351. }
  352. StrLtoA(s, StrChr(szText, '\0'), 10);
  353. }
  354. switch (nDecimalPlaces)
  355. {
  356. case 3:
  357. if (*szText != '\0' || ms < 1000)
  358. {
  359. StrCat(szText, lpIntl->szDecimal);
  360. if (f < 100)
  361. StrCat(szText, TEXT("0"));
  362. if (f < 10)
  363. StrCat(szText, TEXT("0"));
  364. }
  365. StrLtoA(f, StrChr(szText, '\0'), 10);
  366. break;
  367. case 2:
  368. f = f / 10;
  369. if (*szText != '\0' || ms < 1000)
  370. {
  371. StrCat(szText, lpIntl->szDecimal);
  372. if (f < 10)
  373. StrCat(szText, TEXT("0"));
  374. }
  375. StrLtoA(f, StrChr(szText, '\0'), 10);
  376. break;
  377. case 1:
  378. f = f / 100;
  379. if (*szText != '\0' || ms < 1000)
  380. StrCat(szText, lpIntl->szDecimal);
  381. StrLtoA(f, StrChr(szText, '\0'), 10);
  382. break;
  383. default:
  384. break;
  385. }
  386. StrNCpy(lpszText, szText, sizText);
  387. }
  388. return fSuccess ? 0 : -1;
  389. }
  390. // IntlDateGetFormat - return current date format structure
  391. // <hIntl> (i) handle returned from IntlInit
  392. // <lpIntlDateFormat> (o) copy date format structure here
  393. // return 0 if success
  394. //
  395. int DLLEXPORT WINAPI IntlDateGetFormat(HINTL hIntl, LPINTLDATEFORMAT lpIntlDateFormat)
  396. {
  397. BOOL fSuccess = TRUE;
  398. LPINTL lpIntl;
  399. if ((lpIntl = IntlGetPtr(hIntl)) == NULL)
  400. fSuccess = TraceFALSE(NULL);
  401. else if (lpIntlDateFormat != NULL)
  402. {
  403. MemSet(lpIntlDateFormat, 0,
  404. sizeof(INTLDATEFORMAT));
  405. MemCpy(lpIntlDateFormat->szShortDate, lpIntl->szShortDate,
  406. sizeof(lpIntl->szShortDate));
  407. MemCpy(lpIntlDateFormat->szDateSep, lpIntl->szDateSep,
  408. sizeof(lpIntl->szDateSep));
  409. lpIntlDateFormat->iDate = lpIntl->iDate;
  410. lpIntlDateFormat->fYearCentury = lpIntl->fYearCentury;
  411. lpIntlDateFormat->fMonthLeadingZero = lpIntl->fMonthLeadingZero;
  412. lpIntlDateFormat->fDayLeadingZero = lpIntl->fDayLeadingZero;
  413. }
  414. return fSuccess ? 0 : -1;
  415. }
  416. // IntlTimeGetFormat - return current time format structure
  417. // <hIntl> (i) handle returned from IntlInit
  418. // <lpIntlTimeFormat> (o) copy time format structure here
  419. // return 0 if success
  420. //
  421. int DLLEXPORT WINAPI IntlTimeGetFormat(HINTL hIntl, LPINTLTIMEFORMAT lpIntlTimeFormat)
  422. {
  423. BOOL fSuccess = TRUE;
  424. LPINTL lpIntl;
  425. if ((lpIntl = IntlGetPtr(hIntl)) == NULL)
  426. fSuccess = TraceFALSE(NULL);
  427. else if (lpIntlTimeFormat != NULL)
  428. {
  429. MemSet(lpIntlTimeFormat, 0,
  430. sizeof(INTLDATEFORMAT));
  431. MemCpy(lpIntlTimeFormat->szTimeSep, lpIntl->szTimeSep,
  432. sizeof(lpIntl->szTimeSep));
  433. MemCpy(lpIntlTimeFormat->szAMPMSep, lpIntl->szAMPMSep,
  434. sizeof(lpIntl->szAMPMSep));
  435. MemCpy(lpIntlTimeFormat->szAM, lpIntl->szAM,
  436. sizeof(lpIntl->szAM));
  437. MemCpy(lpIntlTimeFormat->szPM, lpIntl->szPM,
  438. sizeof(lpIntl->szPM));
  439. lpIntlTimeFormat->iTime = lpIntl->iTime;
  440. lpIntlTimeFormat->fHourLeadingZero = lpIntl->fHourLeadingZero;
  441. lpIntlTimeFormat->fMinuteLeadingZero = lpIntl->fMinuteLeadingZero;
  442. lpIntlTimeFormat->fSecondLeadingZero = lpIntl->fSecondLeadingZero;
  443. }
  444. return fSuccess ? 0 : -1;
  445. }
  446. ////
  447. // helper functions
  448. ////
  449. // IntlGetPtr - verify that intl handle is valid,
  450. // <hIntl> (i) handle returned from IntlInit
  451. // return corresponding intl pointer (NULL if error)
  452. //
  453. static LPINTL IntlGetPtr(HINTL hIntl)
  454. {
  455. BOOL fSuccess = TRUE;
  456. LPINTL lpIntl;
  457. if ((lpIntl = (LPINTL) hIntl) == NULL)
  458. fSuccess = TraceFALSE(NULL);
  459. else if (IsBadWritePtr(lpIntl, sizeof(INTL)))
  460. fSuccess = TraceFALSE(NULL);
  461. #ifdef CHECKTASK
  462. // make sure current task owns the intl handle
  463. //
  464. else if (lpIntl->hTask != GetCurrentTask())
  465. fSuccess = TraceFALSE(NULL);
  466. #endif
  467. return fSuccess ? lpIntl : NULL;
  468. }
  469. // IntlGetHandle - verify that intl pointer is valid,
  470. // <lpIntl> (i) pointer to INTL struct
  471. // return corresponding intl handle (NULL if error)
  472. //
  473. static HINTL IntlGetHandle(LPINTL lpIntl)
  474. {
  475. BOOL fSuccess = TRUE;
  476. HINTL hIntl;
  477. if ((hIntl = (HINTL) lpIntl) == NULL)
  478. fSuccess = TraceFALSE(NULL);
  479. return fSuccess ? hIntl : NULL;
  480. }