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.

736 lines
22 KiB

  1. /****************************Module*Header***********************************\
  2. * Module Name: SCICOMM.C
  3. *
  4. * Module Descripton:
  5. *
  6. * Warnings:
  7. *
  8. * Created:
  9. *
  10. * Author:
  11. \****************************************************************************/
  12. #include "scicalc.h"
  13. #include "calchelp.h"
  14. #include "unifunc.h"
  15. #include "input.h"
  16. extern HWND hStatBox;
  17. extern HNUMOBJ ghnoNum, ghnoLastNum, ghnoMem;
  18. extern HNUMOBJ ghnoParNum[25], ghnoPrecNum[25];
  19. extern eNUMOBJ_FMT nFE;
  20. extern INT nTempCom, nParNum, nPrecNum, gcIntDigits,
  21. nOpCode, nOp[25], nPrecOp[25];
  22. extern BOOL bError;
  23. extern TCHAR szBlank[6];
  24. extern TCHAR *rgpsz[CSTRINGS];
  25. int nLastCom; // Last command entered.
  26. CALCINPUTOBJ gcio; // Global calc input object for decimal strings
  27. BOOL gbRecord; // Global mode: recording or displaying
  28. /* Puts up the wait cursor if the calc will take a long time */
  29. HCURSOR ghcurOld = NULL;
  30. BOOL SetWaitCursor( BOOL fOn ) {
  31. if (fOn && ghcurOld == NULL) {
  32. ghcurOld = SetCursor( LoadCursor(NULL, IDC_WAIT) );
  33. } else if (!fOn && ghcurOld != NULL) {
  34. SetCursor( ghcurOld );
  35. ghcurOld = NULL;
  36. }
  37. return (fOn && ghcurOld != NULL);
  38. }
  39. /* Process all keyclicks whether by mouse or accelerator. */
  40. VOID NEAR RealProcessCommands(WPARAM wParam);
  41. VOID NEAR ProcessCommands(WPARAM wParam)
  42. {
  43. if (wParam != IDM_ABOUT)
  44. {
  45. TimeCalc(TRUE);
  46. }
  47. try
  48. {
  49. RealProcessCommands( wParam );
  50. }
  51. catch( ... )
  52. {
  53. // note: it should be impossible for a throw to reach this level, this is put here as an
  54. // emergency backup only. Throws are normally caught at the boundry between calc and ratpak.
  55. ASSERT( 0 );
  56. MessageBox( g_hwndDlg, TEXT("An unknown error has occured."), TEXT("Error"), MB_OK );
  57. }
  58. if (wParam != IDM_ABOUT)
  59. {
  60. TimeCalc(FALSE);
  61. }
  62. }
  63. VOID NEAR RealProcessCommands(WPARAM wParam)
  64. {
  65. static BOOL bNoPrevEqu=TRUE, /* Flag for previous equals. */
  66. bChangeOp=FALSE; /* Flag for changing operation. */
  67. INT nx, ni;
  68. TCHAR szJunk[50], szTemp[50];
  69. static BYTE rgbPrec[24]={ 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
  70. IDC_ADD,2, IDC_SUB,2, RSHF,3, IDC_LSHF,3,
  71. IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4};
  72. // Make sure we're only getting commands we understand.
  73. ASSERT( xwParam(IDC_FIRSTCONTROL, IDC_LASTCONTROL) || // Is it a button?
  74. xwParam(IDM_FIRSTMENU, IDM_LASTMENU) ); // or a menu command?
  75. // Save the last command. Some commands are not saved in this manor, these
  76. // commands are:
  77. // Inv, Hyp, Deg, Rad, Grad, Stat, FE, MClear, Back, and Exp. The excluded
  78. // commands are not
  79. // really mathematical operations, rather they are GUI mode settings.
  80. if ( !xwParam(IDC_INV, IDC_HYP) && !xwParam(IDM_HEX, IDM_BIN) &&
  81. !xwParam(IDM_QWORD, IDM_BYTE) && !xwParam(IDM_DEG, IDM_GRAD) &&
  82. wParam!=IDC_STAT && wParam!=IDC_FE &&
  83. wParam!=IDC_MCLEAR && wParam!=IDC_BACK && wParam!=IDC_EXP)
  84. {
  85. nLastCom=nTempCom;
  86. nTempCom=(INT)wParam;
  87. }
  88. // If error and not a clear key or help key, BEEP.
  89. if (bError && (wParam !=IDC_CLEAR) && (wParam !=IDC_CENTR) &&
  90. (wParam != IDM_HELPTOPICS))
  91. {
  92. MessageBeep(0);
  93. return;
  94. }
  95. // Toggle Record/Display mode if appropriate.
  96. if (gbRecord)
  97. {
  98. if (xwParam(IDC_AND, IDC_MPLUS) ||
  99. xwParam(IDC_AVE, IDC_CLOSEP) ||
  100. xwParam(IDC_INV, IDC_HYP) ||
  101. xwParam(IDM_HEX, IDM_BIN) ||
  102. xwParam(IDM_QWORD, IDM_BYTE) ||
  103. xwParam(IDM_DEG, IDM_GRAD) ||
  104. wParam == IDM_PASTE)
  105. {
  106. gbRecord = FALSE;
  107. SetWaitCursor(TRUE);
  108. CIO_vConvertToNumObj(&ghnoNum, &gcio);
  109. DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
  110. SetWaitCursor(FALSE);
  111. }
  112. }
  113. else
  114. {
  115. if ( xwParam(IDC_0, IDC_F) || wParam == IDC_PNT)
  116. {
  117. gbRecord = TRUE;
  118. CIO_vClear(&gcio);
  119. }
  120. }
  121. // Interpret digit keys.
  122. if (xwParam(IDC_0, IDC_F))
  123. {
  124. int iValue = (int)(wParam-IDC_0);
  125. // this is redundant, illegal keys are disabled
  126. if (iValue >= nRadix)
  127. {
  128. //ASSERT( 0 );
  129. MessageBeep(0);
  130. return;
  131. }
  132. if (!CIO_bAddDigit(&gcio, iValue))
  133. {
  134. MessageBeep(0);
  135. return;
  136. }
  137. DisplayNum();
  138. return;
  139. }
  140. // STATISTICAL FUNCTIONS:
  141. if (xwParam(IDC_AVE,IDC_DATA))
  142. {
  143. /* Do statistics functions on data in fpStatNum array. */
  144. if (hStatBox)
  145. {
  146. DisplayNum(); // Make sure gpszNum has the correct string
  147. try
  148. {
  149. StatFunctions (wParam);
  150. }
  151. catch ( ... )
  152. {
  153. ASSERT( 0 ); // the only thing stat box should be able to throw is out of memory
  154. // which in previous versions of calc caused a program crash
  155. }
  156. if (!bError)
  157. DisplayNum ();
  158. }
  159. else
  160. /* Beep if the stat box is not active. */
  161. MessageBeep(0);
  162. /* Reset the inverse flag since some functions use it. */
  163. SetBox (IDC_INV, bInv=FALSE);
  164. return;
  165. }
  166. // BINARY OPERATORS:
  167. if (xwParam(IDC_AND,IDC_PWR))
  168. {
  169. if (bInv && wParam==IDC_LSHF)
  170. {
  171. SetBox (IDC_INV, bInv=FALSE);
  172. wParam=RSHF;
  173. }
  174. /* Change the operation if last input was operation. */
  175. if (nLastCom >=IDC_AND && nLastCom <=IDC_PWR)
  176. {
  177. nOpCode=(INT)wParam;
  178. return;
  179. }
  180. /* bChangeOp is true if there was an operation done and the */
  181. /* current ghnoNum is the result of that operation. This is so */
  182. /* entering 3+4+5= gives 7 after the first + and 12 after the */
  183. /* the =. The rest of this stuff attempts to do precedence in*/
  184. /* Scientific mode. */
  185. if (bChangeOp)
  186. {
  187. DoPrecedenceCheckAgain:
  188. nx=0;
  189. while (wParam!=rgbPrec[nx*2] && nx <12)
  190. nx++;
  191. ni=0;
  192. while (nOpCode!=rgbPrec[ni*2] && ni <12)
  193. ni++;
  194. if (nx==12) nx=0;
  195. if (ni==12) ni=0;
  196. if (rgbPrec[nx*2+1] > rgbPrec[ni*2+1] && nCalc==0)
  197. {
  198. if (nPrecNum <25)
  199. {
  200. NumObjAssign( &ghnoPrecNum[nPrecNum], ghnoLastNum );
  201. nPrecOp[nPrecNum]=nOpCode;
  202. }
  203. else
  204. {
  205. nPrecNum=24;
  206. MessageBeep(0);
  207. }
  208. nPrecNum++;
  209. }
  210. else
  211. {
  212. /* do the last operation and then if the precedence array is not
  213. * empty or the top is not the '(' demarcator then pop the top
  214. * of the array and recheck precedence against the new operator
  215. */
  216. SetWaitCursor(TRUE);
  217. DoOperation(nOpCode, &ghnoNum, ghnoLastNum);
  218. SetWaitCursor(FALSE);
  219. if ((nPrecNum !=0) && (nPrecOp[nPrecNum-1]))
  220. {
  221. nPrecNum--;
  222. nOpCode=nPrecOp[nPrecNum] ;
  223. if (NumObjOK( ghnoPrecNum[nPrecNum] ))
  224. NumObjAssign(&ghnoLastNum , ghnoPrecNum[nPrecNum]);
  225. else
  226. NumObjAssign(&ghnoLastNum, HNO_ZERO);
  227. goto DoPrecedenceCheckAgain ;
  228. }
  229. if (!bError)
  230. DisplayNum ();
  231. }
  232. }
  233. NumObjAssign(&ghnoLastNum, ghnoNum);
  234. NumObjAssign(&ghnoNum, HNO_ZERO);
  235. nOpCode=(INT)wParam;
  236. bNoPrevEqu=bChangeOp=TRUE;
  237. return;
  238. }
  239. // UNARY OPERATORS:
  240. if (xwParam(IDC_CHOP,IDC_PERCENT))
  241. {
  242. /* Functions are unary operations. */
  243. /* If the last thing done was an operator, ghnoNum was cleared. */
  244. /* In that case we better use the number before the operator */
  245. /* was entered, otherwise, things like 5+ 1/x give Divide By */
  246. /* zero. This way 5+=gives 10 like most calculators do. */
  247. if (nLastCom >= IDC_AND && nLastCom <= IDC_PWR)
  248. NumObjAssign( &ghnoNum, ghnoLastNum );
  249. SetWaitCursor(TRUE);
  250. SciCalcFunctions ( &ghnoNum, (DWORD)wParam);
  251. SetWaitCursor(FALSE);
  252. if (bError)
  253. return;
  254. /* Display the result, reset flags, and reset indicators. */
  255. DisplayNum ();
  256. /* reset the bInv and bHyp flags and indicators if they are set
  257. and have been used */
  258. if (bInv &&
  259. (wParam == IDC_CHOP || wParam == IDC_SIN || wParam == IDC_COS ||
  260. wParam == IDC_TAN || wParam == IDC_SQR || wParam == IDC_CUB ||
  261. wParam == IDC_LOG || wParam == IDC_LN || wParam == IDC_DMS))
  262. {
  263. bInv=FALSE;
  264. SetBox (IDC_INV, FALSE);
  265. }
  266. if (bHyp &&
  267. (wParam == IDC_SIN || wParam == IDC_COS || wParam == IDC_TAN))
  268. {
  269. bHyp = FALSE;
  270. SetBox (IDC_HYP, FALSE);
  271. }
  272. bNoPrevEqu=TRUE;
  273. return;
  274. }
  275. // BASE CHANGES:
  276. if (xwParam(IDM_HEX, IDM_BIN))
  277. {
  278. // Change radix and update display.
  279. if (nCalc==1)
  280. {
  281. wParam=IDM_DEC;
  282. }
  283. SetRadix((DWORD)wParam);
  284. return;
  285. }
  286. SetWaitCursor(TRUE);
  287. /* Now branch off to do other commands and functions. */
  288. switch(wParam)
  289. {
  290. case IDM_COPY:
  291. case IDM_PASTE:
  292. case IDM_ABOUT:
  293. case IDM_SC:
  294. case IDM_SSC:
  295. case IDM_USE_SEPARATOR:
  296. case IDM_HELPTOPICS:
  297. // Jump to menu command handler in scimenu.c.
  298. MenuFunctions((DWORD)wParam);
  299. DisplayNum();
  300. break;
  301. case IDC_CLEAR: /* Total clear. */
  302. NumObjAssign( &ghnoLastNum, HNO_ZERO );
  303. nPrecNum=nTempCom=nLastCom=nOpCode=nParNum=bChangeOp=FALSE;
  304. nFE = FMT_FLOAT; // back to the default number format
  305. bNoPrevEqu=TRUE;
  306. /* clear the paranthesis status box indicator, this will not be
  307. cleared for CENTR */
  308. SetDlgItemText(g_hwndDlg, IDC_PARTEXT, szBlank);
  309. /* fall through */
  310. case IDC_CENTR: /* Clear only temporary values. */
  311. NumObjAssign( &ghnoNum, HNO_ZERO );
  312. if (!nCalc)
  313. {
  314. // Clear the INV, HYP indicators & leave (=xx indicator active
  315. SetBox (IDC_INV, bInv=FALSE);
  316. SetBox (IDC_HYP, bHyp=FALSE);
  317. }
  318. bError=FALSE;
  319. CIO_vClear(&gcio);
  320. gbRecord = TRUE;
  321. DisplayNum ();
  322. break;
  323. case IDC_STAT: /* Shift focus to Statistix Box if it's active. */
  324. if (hStatBox)
  325. SetFocus(hStatBox);
  326. else
  327. SetStat (TRUE);
  328. break;
  329. case IDC_BACK:
  330. // Divide number by the current radix and truncate.
  331. // Only allow backspace if we're recording.
  332. if (gbRecord)
  333. {
  334. if (!CIO_bBackspace(&gcio))
  335. MessageBeep(0);
  336. DisplayNum();
  337. }
  338. else
  339. MessageBeep(0);
  340. break;
  341. /* EQU enables the user to press it multiple times after and */
  342. /* operation to enable repeats of the last operation. I don't */
  343. /* know if I can explain what the [censored] I did here... */
  344. case IDC_EQU:
  345. do {
  346. // NOTE: the number pointed to by hnoHold won't get freed until process termination.
  347. static HNUMOBJ hnoHold;
  348. /* Last thing keyed in was an operator. Lets do the op on*/
  349. /* a duplicate of the last entry. */
  350. if ((nLastCom >= IDC_AND) && (nLastCom <= IDC_PWR))
  351. NumObjAssign( &ghnoNum, ghnoLastNum );
  352. if (nOpCode) /* Is there a valid operation around? */
  353. {
  354. /* If this is the first EQU in a string, set hnoHold=ghnoNum */
  355. /* Otherwise let ghnoNum=hnoTemp. This keeps ghnoNum constant */
  356. /* through all EQUs in a row. */
  357. if (bNoPrevEqu)
  358. NumObjAssign(&hnoHold, ghnoNum);
  359. else
  360. NumObjAssign(&ghnoNum, hnoHold);
  361. /* Do the current or last operation. */
  362. DoOperation (nOpCode, &ghnoNum, ghnoLastNum);
  363. NumObjAssign(&ghnoLastNum, ghnoNum );
  364. /* Check for errors. If this wasn't done, DisplayNum */
  365. /* would immediately overwrite any error message. */
  366. if (!bError)
  367. DisplayNum ();
  368. /* No longer the first EQU. */
  369. bNoPrevEqu=FALSE;
  370. }
  371. else if (!bError)
  372. DisplayNum();
  373. if (nPrecNum==0 || nCalc==1)
  374. break;
  375. nOpCode=nPrecOp[--nPrecNum];
  376. if (NumObjOK( ghnoPrecNum[nPrecNum] ))
  377. NumObjAssign(&ghnoLastNum , ghnoPrecNum[nPrecNum]);
  378. else
  379. NumObjAssign(&ghnoLastNum, HNO_ZERO);
  380. bNoPrevEqu=TRUE;
  381. } while (nPrecNum >= 0);
  382. bChangeOp=FALSE;
  383. break;
  384. case IDC_OPENP:
  385. case IDC_CLOSEP:
  386. nx=0;
  387. if (wParam==IDC_OPENP)
  388. nx=1;
  389. // -IF- the Paren holding array is full and we try to add a paren
  390. // -OR- the paren holding array is empty and we try to remove a
  391. // paren
  392. // -OR- the the precidence holding array is full
  393. if ((nParNum >= 25 && nx) || (!nParNum && !nx)
  394. || ( (nPrecNum >= 25 && nPrecOp[nPrecNum-1]!=0) ) )
  395. {
  396. MessageBeep(0);
  397. break;
  398. }
  399. if (nx)
  400. {
  401. /* Open level of parentheses, save number and operation. */
  402. NumObjAssign( &ghnoParNum[nParNum], ghnoLastNum);
  403. nOp[nParNum++]=nOpCode;
  404. /* save a special marker on the precedence array */
  405. nPrecOp[nPrecNum++]=0 ;
  406. NumObjAssign( &ghnoLastNum, HNO_ZERO );
  407. nTempCom=0;
  408. nOpCode=IDC_ADD;
  409. }
  410. else
  411. {
  412. /* Get the operation and number and return result. */
  413. DoOperation (nOpCode, &ghnoNum, ghnoLastNum);
  414. /* now process the precedence stack till we get to an
  415. opcode which is zero. */
  416. while (nOpCode = nPrecOp[--nPrecNum])
  417. {
  418. if (NumObjOK( ghnoPrecNum[nPrecNum] ))
  419. NumObjAssign(&ghnoLastNum , ghnoPrecNum[nPrecNum]);
  420. else
  421. NumObjAssign(&ghnoLastNum, HNO_ZERO);
  422. DoOperation (nOpCode, &ghnoNum, ghnoLastNum);
  423. }
  424. /* now get back the operation and opcode at the begining
  425. of this paranthesis pair */
  426. nParNum -= 1;
  427. NumObjAssign( &ghnoLastNum, ghnoParNum[nParNum] );
  428. nOpCode=nOp[nParNum];
  429. /* if nOpCode is a valid operator then set bChangeOp to
  430. be true else set it false */
  431. if (nOpCode)
  432. bChangeOp=TRUE;
  433. else
  434. bChangeOp=FALSE ;
  435. }
  436. /* Set the "(=xx" indicator. */
  437. lstrcpy(szJunk, TEXT("(="));
  438. lstrcat(szJunk, UToDecT(nParNum, szTemp));
  439. SetDlgItemText(g_hwndDlg, IDC_PARTEXT,
  440. (nParNum) ? (szJunk) : (szBlank));
  441. if (bError)
  442. break;
  443. if (nx)
  444. {
  445. /* Build a display string of nParNum "("'s. */
  446. for (nx=0; nx < nParNum; nx++)
  447. szJunk[nx]=TEXT('(');
  448. szJunk[nx]=0; /* Null-terminate. */
  449. SetDisplayText(g_hwndDlg, szJunk);
  450. bChangeOp=FALSE;
  451. }
  452. else
  453. DisplayNum ();
  454. break;
  455. case IDM_QWORD:
  456. case IDM_DWORD:
  457. case IDM_WORD:
  458. case IDM_BYTE:
  459. case IDM_DEG:
  460. case IDM_RAD:
  461. case IDM_GRAD:
  462. if (!F_INTMATH())
  463. {
  464. // in decimal mode, these buttons simply set a flag which is
  465. // passed to the ratpak to handle angle conversions
  466. if (xwParam(IDM_DEG, IDM_GRAD))
  467. {
  468. nDecMode = (ANGLE_TYPE)(wParam - IDM_DEG);
  469. CheckMenuRadioItem(GetSubMenu(GetMenu(g_hwndDlg), 1),
  470. IDM_DEG, IDM_GRAD, IDM_DEG+nDecMode,
  471. MF_BYCOMMAND);
  472. CheckRadioButton(g_hwndDlg, IDC_DEG, IDC_GRAD,
  473. IDC_DEG+nDecMode);
  474. }
  475. }
  476. else
  477. {
  478. if (xwParam(IDM_DEG, IDM_GRAD))
  479. {
  480. // if in hex mode, but we got a decimal key press this
  481. // likely is the accelorator. map this to the correct key
  482. wParam=IDM_DWORD+(wParam-IDM_DEG);
  483. }
  484. if ( gbRecord )
  485. {
  486. CIO_vConvertToNumObj(&ghnoNum, &gcio);
  487. gbRecord = FALSE;
  488. }
  489. // Compat. mode BaseX: Qword, Dword, Word, Byte
  490. nHexMode = (int)(wParam - IDM_QWORD);
  491. switch (nHexMode)
  492. {
  493. case 0: dwWordBitWidth = 64; break;
  494. case 1: dwWordBitWidth = 32; break;
  495. case 2: dwWordBitWidth = 16; break;
  496. case 3: dwWordBitWidth = 8; break;
  497. default:
  498. ASSERT( 0 ); // Invalid Word Size
  499. break;
  500. }
  501. // different wordsize means the new wordsize determines
  502. // the precision
  503. BaseOrPrecisionChanged();
  504. CheckMenuRadioItem(GetSubMenu(GetMenu(g_hwndDlg), 1),
  505. IDM_QWORD, IDM_BYTE, IDM_QWORD+nHexMode,
  506. MF_BYCOMMAND);
  507. CheckRadioButton(g_hwndDlg, IDC_QWORD, IDC_BYTE,
  508. IDC_QWORD+nHexMode);
  509. }
  510. // REARCHITECT: the call to display number is what actually does the
  511. // chop. it would make more sense to do the chop here when the
  512. // wordsize changes. the chop must be done when a different
  513. // wordsize is selected AND when the base is changed to non-decimal
  514. DisplayNum();
  515. break;
  516. case IDC_SIGN:
  517. // Change the sign.
  518. if (gbRecord)
  519. CIO_vToggleSign(&gcio);
  520. else {
  521. NumObjNegate( &ghnoNum );
  522. }
  523. DisplayNum();
  524. break;
  525. case IDC_RECALL:
  526. /* Recall immediate memory value. */
  527. NumObjAssign( &ghnoNum, ghnoMem );
  528. DisplayNum ();
  529. break;
  530. case IDC_MPLUS:
  531. /* MPLUS adds ghnoNum to immediate memory and kills the "mem" */
  532. /* indicator if the result is zero. */
  533. addrat( &ghnoMem, ghnoNum);
  534. SetDlgItemText(g_hwndDlg,IDC_MEMTEXT,
  535. !NumObjIsZero(ghnoMem) ? (TEXT(" M")):(szBlank));
  536. break;
  537. case IDC_STORE:
  538. case IDC_MCLEAR:
  539. if (wParam==IDC_STORE)
  540. {
  541. NumObjAssign( &ghnoMem, ghnoNum );
  542. }
  543. else
  544. {
  545. NumObjAssign( &ghnoMem, HNO_ZERO );
  546. }
  547. SetDlgItemText(g_hwndDlg,IDC_MEMTEXT,
  548. !NumObjIsZero(ghnoMem) ? (TEXT(" M")):(szBlank));
  549. break;
  550. case IDC_PI:
  551. if (!F_INTMATH())
  552. {
  553. /* Return PI if bInv==FALSE, or 2PI if bInv==TRUE. */
  554. if (bInv)
  555. NumObjAssign( &ghnoNum, HNO_2PI );
  556. else
  557. NumObjAssign( &ghnoNum, HNO_PI );
  558. DisplayNum();
  559. SetBox(IDC_INV, bInv=FALSE);
  560. }
  561. else
  562. MessageBeep(0);
  563. break;
  564. case IDC_FE:
  565. // Toggle exponential notation display.
  566. nFE = NUMOBJ_FMT(!(int)nFE);
  567. DisplayNum();
  568. break;
  569. case IDC_EXP:
  570. if (gbRecord && !F_INTMATH())
  571. if (CIO_bExponent(&gcio))
  572. {
  573. DisplayNum();
  574. break;
  575. }
  576. MessageBeep(0);
  577. break;
  578. case IDC_PNT:
  579. if (gbRecord && !F_INTMATH()) {
  580. if (CIO_bAddDecimalPt(&gcio)) {
  581. DisplayNum();
  582. break;
  583. }
  584. }
  585. MessageBeep(0);
  586. break;
  587. case IDC_INV:
  588. SetBox((int)wParam, bInv=!bInv);
  589. break;
  590. case IDC_HYP:
  591. SetBox((int)wParam, bHyp=!bHyp);
  592. break;
  593. }
  594. SetWaitCursor(FALSE);
  595. }
  596. // change the display area from a static text to an editbox, which has the focus can make
  597. // Magnifer (Accessibility tool) work
  598. BOOL SetDisplayText(HWND hDlg, LPCTSTR szText)
  599. {
  600. HWND hDispEdit = GetDlgItem(hDlg, IDC_DISPLAY);
  601. int nLen = lstrlen(szText);
  602. SetWindowText(hDispEdit, szText);
  603. SetFocus(hDispEdit);
  604. // make sure the number just typed is shown at the center of Magnifier
  605. SendMessage(hDispEdit, EM_SETSEL, nLen, nLen);
  606. return TRUE;
  607. }