Source code of Windows XP (NT5)
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.

745 lines
21 KiB

  1. /*++
  2. Copyright (c) 1994-2000, Microsoft Corporation All rights reserved.
  3. Module Name:
  4. timedlg.c
  5. Abstract:
  6. This module implements the time property sheet for the Regional
  7. Options applet.
  8. Revision History:
  9. --*/
  10. //
  11. // Include Files.
  12. //
  13. #include "intl.h"
  14. #include <windowsx.h>
  15. #include <tchar.h>
  16. #include "intlhlp.h"
  17. #include "maxvals.h"
  18. //
  19. // Global Variables.
  20. //
  21. static TCHAR sz_s1159[MAX_S1159 + 1];
  22. static TCHAR sz_s2359[MAX_S2359 + 1];
  23. static TCHAR sz_sTime[MAX_STIME + 1];
  24. static TCHAR sz_sTimeFormat[MAX_FORMAT + 1];
  25. TCHAR szNLS_TimeStyle[SIZE_128];
  26. //
  27. // Context Help Ids.
  28. //
  29. static int aTimeHelpIds[] =
  30. {
  31. IDC_GROUPBOX1, IDH_COMM_GROUPBOX,
  32. IDC_SAMPLELBL1, IDH_INTL_TIME_SAMPLE,
  33. IDC_SAMPLE1, IDH_INTL_TIME_SAMPLE,
  34. IDC_SAMPLE1A, IDH_INTL_TIME_SAMPLE_ARABIC,
  35. IDC_TIME_STYLE, IDH_INTL_TIME_FORMAT,
  36. IDC_SEPARATOR, IDH_INTL_TIME_SEPARATOR,
  37. IDC_AM_SYMBOL, IDH_INTL_TIME_AMSYMBOL,
  38. IDC_PM_SYMBOL, IDH_INTL_TIME_PMSYMBOL,
  39. IDC_GROUPBOX2, IDH_INTL_TIME_FORMAT_NOTATION,
  40. IDC_SAMPLE2, IDH_INTL_TIME_FORMAT_NOTATION,
  41. 0, 0
  42. };
  43. ////////////////////////////////////////////////////////////////////////////
  44. //
  45. // Time_DisplaySample
  46. //
  47. // Update the Time sample. Format the time based on the user's
  48. // current locale settings.
  49. //
  50. ////////////////////////////////////////////////////////////////////////////
  51. void Time_DisplaySample(
  52. HWND hDlg)
  53. {
  54. TCHAR szBuf[MAX_SAMPLE_SIZE];
  55. //
  56. // Show or hide the Arabic info based on the current user locale id.
  57. //
  58. ShowWindow(GetDlgItem(hDlg, IDC_SAMPLE1A), bShowArabic ? SW_SHOW : SW_HIDE);
  59. //
  60. // Get the string representing the time format for the current system
  61. // time and display it. If the sample in the buffer is valid, display
  62. // it. Otherwise, display a message box indicating that there is a
  63. // problem retrieving the locale information.
  64. //
  65. if (GetTimeFormat(UserLocaleID, 0, NULL, NULL, szBuf, MAX_SAMPLE_SIZE))
  66. {
  67. SetDlgItemText(hDlg, IDC_SAMPLE1, szBuf);
  68. if (bShowArabic)
  69. {
  70. SetDlgItemText(hDlg, IDC_SAMPLE1A, szBuf);
  71. SetDlgItemRTL(hDlg, IDC_SAMPLE1A);
  72. }
  73. }
  74. else
  75. {
  76. MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION);
  77. }
  78. }
  79. ////////////////////////////////////////////////////////////////////////////
  80. //
  81. // Time_SaveValues
  82. //
  83. // Save values in the case that we need to restore them.
  84. //
  85. ////////////////////////////////////////////////////////////////////////////
  86. void Time_SaveValues()
  87. {
  88. //
  89. // Save registry values.
  90. //
  91. if (!GetLocaleInfo( UserLocaleID,
  92. LOCALE_S1159,
  93. sz_s1159,
  94. MAX_S1159 + 1 ))
  95. {
  96. _tcscpy(sz_s1159, TEXT("AM"));
  97. }
  98. if (!GetLocaleInfo( UserLocaleID,
  99. LOCALE_S2359,
  100. sz_s2359,
  101. MAX_S2359 + 1 ))
  102. {
  103. _tcscpy(sz_s2359, TEXT("PM"));
  104. }
  105. if (!GetLocaleInfo( UserLocaleID,
  106. LOCALE_STIME,
  107. sz_sTime,
  108. MAX_STIME + 1 ))
  109. {
  110. _tcscpy(sz_sTime, TEXT(":"));
  111. }
  112. if (!GetLocaleInfo( UserLocaleID,
  113. LOCALE_STIMEFORMAT,
  114. sz_sTimeFormat,
  115. MAX_FORMAT + 1 ))
  116. {
  117. _tcscpy(sz_sTimeFormat, TEXT("h:mm:ss tt"));
  118. }
  119. }
  120. ////////////////////////////////////////////////////////////////////////////
  121. //
  122. // Time_RestoreValues
  123. //
  124. ////////////////////////////////////////////////////////////////////////////
  125. void Time_RestoreValues()
  126. {
  127. if (g_dwCustChange & Process_Time)
  128. {
  129. SetLocaleInfo(UserLocaleID, LOCALE_S1159, sz_s1159);
  130. SetLocaleInfo(UserLocaleID, LOCALE_S2359, sz_s2359);
  131. SetLocaleInfo(UserLocaleID, LOCALE_STIME, sz_sTime);
  132. SetLocaleInfo(UserLocaleID, LOCALE_STIMEFORMAT, sz_sTimeFormat);
  133. }
  134. }
  135. ////////////////////////////////////////////////////////////////////////////
  136. //
  137. // Time_ClearValues
  138. //
  139. // Reset each of the list boxes in the time property sheet page.
  140. //
  141. ////////////////////////////////////////////////////////////////////////////
  142. void Time_ClearValues(
  143. HWND hDlg)
  144. {
  145. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_AM_SYMBOL));
  146. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_PM_SYMBOL));
  147. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_SEPARATOR));
  148. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_TIME_STYLE));
  149. }
  150. ////////////////////////////////////////////////////////////////////////////
  151. //
  152. // Time_SetValues
  153. //
  154. // Initialize all of the controls in the time property sheet page.
  155. //
  156. ////////////////////////////////////////////////////////////////////////////
  157. void Time_SetValues(
  158. HWND hDlg)
  159. {
  160. TCHAR szBuf[SIZE_128];
  161. DWORD dwIndex;
  162. HWND hCtrl = GetDlgItem(hDlg, IDC_TIME_STYLE);
  163. //
  164. // Initialize the dropdown box for the current locale setting for:
  165. // AM Symbol, PM Symbol, and Time Separator.
  166. //
  167. DropDown_Use_Locale_Values(hDlg, LOCALE_S1159, IDC_AM_SYMBOL);
  168. DropDown_Use_Locale_Values(hDlg, LOCALE_S2359, IDC_PM_SYMBOL);
  169. DropDown_Use_Locale_Values(hDlg, LOCALE_STIME, IDC_SEPARATOR);
  170. //
  171. // Initialize and Lock function. If it succeeds, call enum function to
  172. // enumerate all possible values for the list box via a call to EnumProc.
  173. // EnumProc will call Set_List_Values for each of the string values it
  174. // receives. When the enumeration of values is complete, call
  175. // Set_List_Values to clear the dialog item specific data and to clear
  176. // the lock on the function. Perform this set of operations for all of
  177. // the Time Styles.
  178. //
  179. if (Set_List_Values(hDlg, IDC_TIME_STYLE, 0))
  180. {
  181. EnumTimeFormats(EnumProc, UserLocaleID, 0);
  182. Set_List_Values(0, IDC_TIME_STYLE, 0);
  183. dwIndex = 0;
  184. if (GetLocaleInfo(UserLocaleID, LOCALE_STIMEFORMAT, szBuf, SIZE_128))
  185. {
  186. dwIndex = ComboBox_FindString(hCtrl, -1, szBuf);
  187. }
  188. else
  189. {
  190. MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION);
  191. }
  192. Localize_Combobox_Styles(hDlg, IDC_TIME_STYLE, LOCALE_STIMEFORMAT);
  193. ComboBox_SetCurSel(hCtrl, dwIndex);
  194. }
  195. //
  196. // Display the current sample that represents all of the locale settings.
  197. //
  198. Time_DisplaySample(hDlg);
  199. }
  200. ////////////////////////////////////////////////////////////////////////////
  201. //
  202. // Time_ApplySettings
  203. //
  204. // For every control that has changed (that affects the Locale settings),
  205. // call Set_Locale_Values to update the user locale information. Notify
  206. // the parent of changes and reset the change flag stored in the property
  207. // sheet page structure appropriately. Redisplay the time sample if
  208. // bRedisplay is TRUE.
  209. //
  210. ////////////////////////////////////////////////////////////////////////////
  211. BOOL Time_ApplySettings(
  212. HWND hDlg,
  213. BOOL bRedisplay)
  214. {
  215. TCHAR szBuf[SIZE_128];
  216. DWORD dwIndex;
  217. HWND hCtrl;
  218. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  219. LPARAM Changes = lpPropSheet->lParam;
  220. if (Changes & TC_1159)
  221. {
  222. if (!Set_Locale_Values( hDlg,
  223. LOCALE_S1159,
  224. IDC_AM_SYMBOL,
  225. TEXT("s1159"),
  226. FALSE,
  227. 0,
  228. 0,
  229. NULL ))
  230. {
  231. return (FALSE);
  232. }
  233. }
  234. if (Changes & TC_2359)
  235. {
  236. if (!Set_Locale_Values( hDlg,
  237. LOCALE_S2359,
  238. IDC_PM_SYMBOL,
  239. TEXT("s2359"),
  240. FALSE,
  241. 0,
  242. 0,
  243. NULL ))
  244. {
  245. return (FALSE);
  246. }
  247. }
  248. if (Changes & TC_TimeFmt)
  249. {
  250. //
  251. // szNLS_TimeStyle is set in Time_ValidatePPS.
  252. //
  253. if (!Set_Locale_Values( hDlg,
  254. LOCALE_STIMEFORMAT,
  255. IDC_TIME_STYLE,
  256. 0,
  257. FALSE,
  258. 0,
  259. 0,
  260. szNLS_TimeStyle ))
  261. {
  262. return (FALSE);
  263. }
  264. #ifndef WINNT
  265. //
  266. // The time marker gets:
  267. // set to Null for 24 hour format and
  268. // doesn't change for 12 hour format.
  269. //
  270. GetProfileString(szIntl, TEXT("iTime"), TEXT("0"), pTestBuf, 10);
  271. if (*pTestBuf == TC_FullTime)
  272. {
  273. SetLocaleInfo(UserLocaleID, LOCALE_S1159, TEXT(""));
  274. SetLocaleInfo(UserLocaleID, LOCALE_S2359, TEXT(""));
  275. }
  276. else
  277. {
  278. //
  279. // Set time marker in the registry.
  280. //
  281. if (!Set_Locale_Values( 0,
  282. LOCALE_S1159,
  283. 0,
  284. TEXT("s1159"),
  285. TRUE,
  286. 0,
  287. 0,
  288. NULL ))
  289. {
  290. return (FALSE);
  291. }
  292. if (!Set_Locale_Values( 0,
  293. LOCALE_S2359,
  294. 0,
  295. TEXT("s2359"),
  296. TRUE,
  297. 0,
  298. 0,
  299. NULL ))
  300. {
  301. return (FALSE);
  302. }
  303. }
  304. #endif
  305. //
  306. // If the time separator has areadly been changed, then don't update
  307. // it now as it will be updated down below.
  308. //
  309. if (!(Changes & TC_STime))
  310. {
  311. //
  312. // Since the time style changed, reset time separator list box.
  313. //
  314. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_SEPARATOR));
  315. DropDown_Use_Locale_Values(hDlg, LOCALE_STIME, IDC_SEPARATOR);
  316. if (!Set_Locale_Values( hDlg,
  317. LOCALE_STIME,
  318. IDC_SEPARATOR,
  319. TEXT("sTime"),
  320. FALSE,
  321. 0,
  322. 0,
  323. NULL ))
  324. {
  325. return (FALSE);
  326. }
  327. }
  328. //
  329. // Also need to reset the AM and PM list boxes.
  330. //
  331. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_AM_SYMBOL));
  332. ComboBox_ResetContent(GetDlgItem(hDlg, IDC_PM_SYMBOL));
  333. DropDown_Use_Locale_Values(hDlg, LOCALE_S1159, IDC_AM_SYMBOL);
  334. DropDown_Use_Locale_Values(hDlg, LOCALE_S2359, IDC_PM_SYMBOL);
  335. }
  336. if (Changes & TC_STime)
  337. {
  338. if (!Set_Locale_Values( hDlg,
  339. LOCALE_STIME,
  340. IDC_SEPARATOR,
  341. TEXT("sTime"),
  342. FALSE,
  343. 0,
  344. 0,
  345. NULL ))
  346. {
  347. return (FALSE);
  348. }
  349. //
  350. // Since the time separator changed, update the time style
  351. // list box.
  352. //
  353. hCtrl = GetDlgItem(hDlg, IDC_TIME_STYLE);
  354. ComboBox_ResetContent(hCtrl);
  355. if (Set_List_Values(hDlg, IDC_TIME_STYLE, 0))
  356. {
  357. EnumTimeFormats(EnumProc, UserLocaleID, 0);
  358. Set_List_Values(0, IDC_TIME_STYLE, 0);
  359. dwIndex = 0;
  360. if (GetLocaleInfo(UserLocaleID, LOCALE_STIMEFORMAT, szBuf, SIZE_128))
  361. {
  362. dwIndex = ComboBox_FindString(hCtrl, -1, szBuf);
  363. }
  364. else
  365. {
  366. MessageBox(hDlg, szLocaleGetError, NULL, MB_OK | MB_ICONINFORMATION);
  367. }
  368. Localize_Combobox_Styles( hDlg,
  369. IDC_TIME_STYLE,
  370. LOCALE_STIMEFORMAT );
  371. ComboBox_SetCurSel(hCtrl, dwIndex);
  372. }
  373. }
  374. PropSheet_UnChanged(GetParent(hDlg), hDlg);
  375. lpPropSheet->lParam = TC_EverChg;
  376. //
  377. // Display the current sample that represents all of the locale settings.
  378. //
  379. if (bRedisplay)
  380. {
  381. Time_DisplaySample(hDlg);
  382. }
  383. //
  384. // Changes made in the second level.
  385. //
  386. if (Changes)
  387. {
  388. g_dwCustChange |= Process_Time;
  389. }
  390. //
  391. // Return success.
  392. //
  393. return (TRUE);
  394. }
  395. ////////////////////////////////////////////////////////////////////////////
  396. //
  397. // Time_ValidatePPS
  398. //
  399. // Validate each of the combo boxes whose values are constrained.
  400. // If any of the input fails, notify the user and then return FALSE
  401. // to indicate validation failure.
  402. //
  403. ////////////////////////////////////////////////////////////////////////////
  404. BOOL Time_ValidatePPS(
  405. HWND hDlg,
  406. LPARAM Changes)
  407. {
  408. //
  409. // If nothing has changed, return TRUE immediately.
  410. //
  411. if (Changes <= TC_EverChg)
  412. {
  413. return (TRUE);
  414. }
  415. //
  416. // If the AM symbol has changed, ensure that there are no digits
  417. // contained in the new symbol.
  418. //
  419. if (Changes & TC_1159 &&
  420. Item_Has_Digits(hDlg, IDC_AM_SYMBOL, TRUE))
  421. {
  422. No_Numerals_Error(hDlg, IDC_AM_SYMBOL, IDS_LOCALE_AM_SYM);
  423. return (FALSE);
  424. }
  425. //
  426. // If the PM symbol has changed, ensure that there are no digits
  427. // contained in the new symbol.
  428. //
  429. if (Changes & TC_2359 &&
  430. Item_Has_Digits(hDlg, IDC_PM_SYMBOL, TRUE))
  431. {
  432. No_Numerals_Error(hDlg, IDC_PM_SYMBOL, IDS_LOCALE_PM_SYM);
  433. return (FALSE);
  434. }
  435. //
  436. // If the time separator has changed, ensure that there are no digits
  437. // and no invalid characters contained in the new separator.
  438. //
  439. if (Changes & TC_STime &&
  440. Item_Has_Digits_Or_Invalid_Chars( hDlg,
  441. IDC_SEPARATOR,
  442. FALSE,
  443. szInvalidSTime ))
  444. {
  445. No_Numerals_Error(hDlg, IDC_SEPARATOR, IDS_LOCALE_TIME_SEP);
  446. return (FALSE);
  447. }
  448. //
  449. // If the time style has changed, ensure that there are only characters
  450. // in this set " Hhmst,-./:;\" or localized equivalent, the separator
  451. // string, and text enclosed in single quotes.
  452. //
  453. if (Changes & TC_TimeFmt)
  454. {
  455. if (NLSize_Style( hDlg,
  456. IDC_TIME_STYLE,
  457. szNLS_TimeStyle,
  458. LOCALE_STIMEFORMAT ) ||
  459. Item_Check_Invalid_Chars( hDlg,
  460. szNLS_TimeStyle,
  461. szTimeChars,
  462. IDC_SEPARATOR,
  463. FALSE,
  464. szTCaseSwap,
  465. IDC_TIME_STYLE ))
  466. {
  467. Invalid_Chars_Error(hDlg, IDC_TIME_STYLE, IDS_LOCALE_TIME);
  468. return (FALSE);
  469. }
  470. }
  471. //
  472. // Return success.
  473. //
  474. return (TRUE);
  475. }
  476. ////////////////////////////////////////////////////////////////////////////
  477. //
  478. // Time_InitPropSheet
  479. //
  480. // The extra long value for the property sheet page is used as a set of
  481. // state or change flags for each of the list boxes in the property sheet.
  482. // Initialize this value to 0. Call Time_SetValues with the property
  483. // sheet handle to initialize all of the property sheet controls. Limit
  484. // the length of the text in some of the ComboBoxes.
  485. //
  486. ////////////////////////////////////////////////////////////////////////////
  487. void Time_InitPropSheet(
  488. HWND hDlg,
  489. LPARAM lParam)
  490. {
  491. //
  492. // The lParam holds a pointer to the property sheet page. Save it
  493. // for later reference.
  494. //
  495. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  496. Time_SetValues(hDlg);
  497. szNLS_TimeStyle[0] = 0;
  498. ComboBox_LimitText(GetDlgItem(hDlg, IDC_AM_SYMBOL), MAX_S1159);
  499. ComboBox_LimitText(GetDlgItem(hDlg, IDC_PM_SYMBOL), MAX_S2359);
  500. ComboBox_LimitText(GetDlgItem(hDlg, IDC_SEPARATOR), MAX_STIME);
  501. ComboBox_LimitText(GetDlgItem(hDlg, IDC_TIME_STYLE), MAX_FORMAT);
  502. }
  503. ////////////////////////////////////////////////////////////////////////////
  504. //
  505. // TimeDlgProc
  506. //
  507. ////////////////////////////////////////////////////////////////////////////
  508. INT_PTR CALLBACK TimeDlgProc(
  509. HWND hDlg,
  510. UINT message,
  511. WPARAM wParam,
  512. LPARAM lParam)
  513. {
  514. NMHDR *lpnm;
  515. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  516. switch (message)
  517. {
  518. case ( WM_NOTIFY ) :
  519. {
  520. lpnm = (NMHDR *)lParam;
  521. switch (lpnm->code)
  522. {
  523. case ( PSN_SETACTIVE ) :
  524. {
  525. //
  526. // If there has been a change in the regional Locale
  527. // setting, clear all of the current info in the
  528. // property sheet, get the new values, and update the
  529. // appropriate registry values.
  530. //
  531. if (Verified_Regional_Chg & Process_Time)
  532. {
  533. Verified_Regional_Chg &= ~Process_Time;
  534. Time_ClearValues(hDlg);
  535. Time_SetValues(hDlg);
  536. lpPropSheet->lParam = 0;
  537. }
  538. break;
  539. }
  540. case ( PSN_KILLACTIVE ) :
  541. {
  542. //
  543. // Validate the entries on the property page.
  544. //
  545. SetWindowLongPtr( hDlg,
  546. DWLP_MSGRESULT,
  547. !Time_ValidatePPS( hDlg,
  548. lpPropSheet->lParam ) );
  549. break;
  550. }
  551. case ( PSN_APPLY ) :
  552. {
  553. //
  554. // Apply the settings.
  555. //
  556. if (Time_ApplySettings(hDlg, TRUE))
  557. {
  558. SetWindowLongPtr(hDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
  559. //
  560. // Zero out the TC_EverChg bit.
  561. //
  562. lpPropSheet->lParam = 0;
  563. }
  564. else
  565. {
  566. SetWindowLongPtr( hDlg,
  567. DWLP_MSGRESULT,
  568. PSNRET_INVALID_NOCHANGEPAGE );
  569. }
  570. break;
  571. }
  572. default :
  573. {
  574. return (FALSE);
  575. }
  576. }
  577. break;
  578. }
  579. case ( WM_INITDIALOG ) :
  580. {
  581. Time_InitPropSheet(hDlg, lParam);
  582. Time_SaveValues();
  583. break;
  584. }
  585. case ( WM_DESTROY ) :
  586. {
  587. break;
  588. }
  589. case ( WM_HELP ) :
  590. {
  591. WinHelp( (HWND)((LPHELPINFO)lParam)->hItemHandle,
  592. szHelpFile,
  593. HELP_WM_HELP,
  594. (DWORD_PTR)(LPTSTR)aTimeHelpIds );
  595. break;
  596. }
  597. case ( WM_CONTEXTMENU ) : // right mouse click
  598. {
  599. WinHelp( (HWND)wParam,
  600. szHelpFile,
  601. HELP_CONTEXTMENU,
  602. (DWORD_PTR)(LPTSTR)aTimeHelpIds );
  603. break;
  604. }
  605. case ( WM_COMMAND ) :
  606. {
  607. switch (LOWORD(wParam))
  608. {
  609. case ( IDC_AM_SYMBOL ) :
  610. {
  611. if (HIWORD(wParam) == CBN_SELCHANGE ||
  612. HIWORD(wParam) == CBN_EDITCHANGE)
  613. {
  614. lpPropSheet->lParam |= TC_1159;
  615. }
  616. break;
  617. }
  618. case ( IDC_PM_SYMBOL ) :
  619. {
  620. if (HIWORD(wParam) == CBN_SELCHANGE ||
  621. HIWORD(wParam) == CBN_EDITCHANGE)
  622. {
  623. lpPropSheet->lParam |= TC_2359;
  624. }
  625. break;
  626. }
  627. case ( IDC_SEPARATOR ) :
  628. {
  629. if (HIWORD(wParam) == CBN_SELCHANGE ||
  630. HIWORD(wParam) == CBN_EDITCHANGE)
  631. {
  632. lpPropSheet->lParam |= TC_STime;
  633. }
  634. break;
  635. }
  636. case ( IDC_TIME_STYLE ) :
  637. {
  638. if (HIWORD(wParam) == CBN_SELCHANGE ||
  639. HIWORD(wParam) == CBN_EDITCHANGE)
  640. {
  641. lpPropSheet->lParam |= TC_TimeFmt;
  642. }
  643. break;
  644. }
  645. }
  646. //
  647. // Turn on ApplyNow button.
  648. //
  649. if (lpPropSheet->lParam > TC_EverChg)
  650. {
  651. PropSheet_Changed(GetParent(hDlg), hDlg);
  652. }
  653. break;
  654. }
  655. default :
  656. {
  657. return (FALSE);
  658. }
  659. }
  660. //
  661. // Return success.
  662. //
  663. return (TRUE);
  664. }