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.

362 lines
14 KiB

  1. /**************************************************************************/
  2. /*** SCICALC Scientific Calculator for Windows 3.00.12 ***/
  3. /*** By Kraig Brockschmidt, Microsoft Co-op, Contractor, 1988-1989 ***/
  4. /*** (c)1989 Microsoft Corporation. All Rights Reserved. ***/
  5. /*** ***/
  6. /*** scimenu.c ***/
  7. /*** ***/
  8. /*** Functions contained: ***/
  9. /*** MenuFunctions--handles menu options. ***/
  10. /*** ***/
  11. /*** Functions called: ***/
  12. /*** DisplayNum ***/
  13. /*** ***/
  14. /*** Last modification Thu 06-Dec-1989 ***/
  15. /*** (-by- Amit Chatterjee [amitc]) ***/
  16. /*** ***/
  17. /*** Modified the 'PASTE' menu to check for unary minus, e, e+ & e- ***/
  18. /*** in DEC mode. ***/
  19. /*** ***/
  20. /*** Also modified the COPY code to not copy the last '.' in the display***/
  21. /*** if a decimal point has not been hit. ***/
  22. /*** ***/
  23. /**************************************************************************/
  24. #include "scicalc.h"
  25. #include "unifunc.h"
  26. #include "input.h"
  27. #include "strsafe.h"
  28. #include <shellapi.h>
  29. #include <ctype.h>
  30. #define CHARSCAN 66
  31. extern HWND hEdit, hStatBox;
  32. extern TCHAR szAppName[10], szDec[5], gszSep[5], *rgpsz[CSTRINGS];
  33. extern LPTSTR gpszNum;
  34. extern int gcchNum;
  35. extern BOOL bError;
  36. extern INT nLayout;
  37. extern HMENU g_hDecMenu;
  38. extern HMENU g_hHexMenu;
  39. extern CALCINPUTOBJ gcio;
  40. extern BOOL gbRecord;
  41. extern BOOL gbUseSep;
  42. /* Menu handling routine for COPY, PASTE, ABOUT, and HELP. */
  43. VOID NEAR PASCAL MemErrorMessage(VOID)
  44. {
  45. MessageBeep(0);
  46. MessageBox(g_hwndDlg,rgpsz[IDS_STATMEM],NULL,MB_OK|MB_ICONHAND);
  47. }
  48. VOID APIENTRY MenuFunctions(DWORD nFunc)
  49. {
  50. INT nx;
  51. static const int rgbMap[CHARSCAN * 2]=
  52. {
  53. TEXT('0'),IDC_0, TEXT('1'),IDC_1,
  54. TEXT('2'),IDC_2, TEXT('3'),IDC_3,
  55. TEXT('4'),IDC_4, TEXT('5'),IDC_5,
  56. TEXT('6'),IDC_6, TEXT('7'),IDC_7,
  57. TEXT('8'),IDC_8, TEXT('9'),IDC_9,
  58. TEXT('A'),IDC_A, TEXT('B'),IDC_B,
  59. TEXT('C'),IDC_C, TEXT('D'),IDC_D,
  60. TEXT('E'),IDC_E, TEXT('F'),IDC_F,
  61. TEXT('!'),IDC_FAC, TEXT('S'),IDC_SIN,
  62. TEXT('O'),IDC_COS, TEXT('T'),IDC_TAN,
  63. TEXT('R'),IDC_REC, TEXT('Y'),IDC_PWR,
  64. TEXT('#'),IDC_CUB, TEXT('@'),IDC_SQR,
  65. TEXT('M'),IDM_DEG, TEXT('N'),IDC_LN,
  66. TEXT('L'),IDC_LOG, TEXT('V'),IDC_FE,
  67. TEXT('X'),IDC_EXP, TEXT('I'),IDC_INV,
  68. TEXT('H'),IDC_HYP, TEXT('P'),IDC_PI,
  69. TEXT('/'),IDC_DIV, TEXT('*'),IDC_MUL,
  70. TEXT('%'),IDC_MOD, TEXT('-'),IDC_SUB,
  71. TEXT('='),IDC_EQU, TEXT('+'),IDC_ADD,
  72. TEXT('&'),IDC_AND, TEXT('|'),IDC_OR,
  73. TEXT('^'),IDC_XOR, TEXT('~'),IDC_COM,
  74. TEXT(';'),IDC_CHOP, TEXT('<'),IDC_LSHF,
  75. TEXT('('),IDC_OPENP,TEXT(')'),IDC_CLOSEP,
  76. TEXT('\\'), IDC_DATA,
  77. TEXT('Q'), IDC_CLEAR,
  78. TEXT('Q')+128, IDC_CLEAR, // ":Q"=="Q"=>CLEAR
  79. TEXT('S')+128, IDC_STAT, // ":S"=>CTRL-S
  80. TEXT('M')+128, IDC_STORE, // ":M"=>CTRL-M
  81. TEXT('P')+128, IDC_MPLUS, // ":P"=>CTRL-P
  82. TEXT('C')+128, IDC_MCLEAR, // ":C"=>CTRL-C
  83. TEXT('R')+128, IDC_RECALL, // ":R"=>CTRL-R
  84. TEXT('A')+128, IDC_AVE, // ":A"=>CTRL-A
  85. TEXT('T')+128, IDC_B_SUM, // ":T"=>CTRL-T
  86. TEXT('D')+128, IDC_DEV, // ":D"=>CTRL-D
  87. TEXT('2')+128, IDC_DWORD, // ":2"=>F2 IDC_DWORD
  88. TEXT('3')+128, IDC_RAD, // ":3"=>F3 IDC_WORD
  89. TEXT('4')+128, IDC_GRAD, // ":4"=>F4 IDC_BYTE
  90. TEXT('5')+128, IDC_HEX, // ":5"=>F5
  91. TEXT('6')+128, IDC_DEC, // ":6"=>F6
  92. TEXT('7')+128, IDC_OCT, // ":7"=>F7
  93. TEXT('8')+128, IDC_BIN, // ":8"=>F8
  94. TEXT('9')+128, IDC_SIGN, // ":9"=>F9
  95. TEXT('9')+3+128, IDC_QWORD // ":9"+2=>F12 (64 bit)
  96. };
  97. switch (nFunc)
  98. {
  99. case IDM_COPY:
  100. {
  101. TCHAR szJunk[256];
  102. // Copy the string into a work buffer. It may be modified.
  103. if (gbRecord)
  104. CIO_vConvertToString(&gpszNum, &gcchNum, &gcio, nRadix);
  105. StringCchCopy(szJunk, ARRAYSIZE(szJunk), gpszNum);
  106. // Strip a trailing decimal point if it wasn't explicitly entered.
  107. if (!gbRecord || !CIO_bDecimalPt(&gcio))
  108. {
  109. nx = lstrlen(szJunk);
  110. if (szJunk[nx - 1] == szDec[0])
  111. szJunk[nx - 1] = 0;
  112. }
  113. /* Copy text to the clipboard through the hidden edit control.*/
  114. SetWindowText(hEdit, szJunk);
  115. SendMessage(hEdit, EM_SETSEL, 0, -1); // select all text
  116. SendMessage(hEdit, WM_CUT, 0, 0L);
  117. break;
  118. }
  119. case IDM_PASTE:
  120. {
  121. HANDLE hClipData;
  122. char * lpClipData;
  123. char * lpEndOfBuffer; // used to ensure we don't GPF even if the clipboard data isn't NULL terminated
  124. WORD b, bLast;
  125. INT nControl;
  126. BOOL bNeedIDC_SIGN = FALSE;
  127. /* Get a handle on the clipboard data and paste by sending the*/
  128. /* contents one character at a time like it was typed. */
  129. if (!OpenClipboard(g_hwndDlg))
  130. {
  131. MessageBox(g_hwndDlg, rgpsz[IDS_NOPASTE], rgpsz[IDS_CALC],
  132. MB_OK | MB_ICONEXCLAMATION);
  133. break;
  134. }
  135. hClipData=GetClipboardData(CF_TEXT);
  136. if (hClipData)
  137. {
  138. lpClipData=(char *)GlobalLock(hClipData);
  139. if (lpClipData)
  140. {
  141. lpEndOfBuffer = lpClipData + GlobalSize(hClipData);
  142. bLast=0;
  143. /* Continue this as long as no error occurs. If one */
  144. /* does then it's useless to continue pasting. */
  145. while (!bError && lpClipData < lpEndOfBuffer)
  146. {
  147. // we know that lpClipData points to a NULL terminated ansi
  148. // string because this is the format we requested the data in.
  149. // As a result we call CharNextA.
  150. b = *lpClipData;
  151. lpClipData = CharNextA( lpClipData );
  152. /* Skip spaces and LF and CR. */
  153. if (b==32 || b==10 || b==13 || b==gszSep[0])
  154. continue;
  155. /* We're done if we get to a NULL character */
  156. if ( b==0 )
  157. break;
  158. if (b == szDec[0])
  159. {
  160. bLast = b;
  161. b = IDC_PNT;
  162. goto MappingDone;
  163. }
  164. /*-----------------------------------------------------------------------------;
  165. ; Now we will check for certain special cases. These are: ;
  166. ; ;
  167. ; (1) Unary Minus. If bLast is still 0 and b is '-' we will force b to ;
  168. ; be the code for 'SIGN'. ;
  169. ; (2) If b is 'x' we will make it the code for EXP ;
  170. ; (3) if bLast is 'x' and b is '+' we will ignore b, as '+' is the dflt. ;
  171. ; (4) if bLast is 'x' and b is '-' we will force b to be SIGN. ;
  172. ; ;
  173. ; In case (3) we will go back to the top of the loop else we will jmp off ;
  174. ; to the sendmessage point, bypassing the table lookup. ;
  175. ;-----------------------------------------------------------------------------*/
  176. /* check for unary minuses */
  177. if (!bLast && b == TEXT('-'))
  178. {
  179. /* Doesn't work.
  180. bLast = b ;
  181. b = IDC_SIGN ;
  182. goto MappingDone ;
  183. */
  184. bNeedIDC_SIGN = TRUE ;
  185. continue ;
  186. }
  187. /* check for 'x' */
  188. if ((b == TEXT('x') || b == TEXT('e')) && nRadix == 10)
  189. {
  190. bLast = TEXT('x') ;
  191. b = IDC_EXP ;
  192. goto MappingDone ;
  193. }
  194. /* if the last character was a 'x' & this is '+' - ignore */
  195. if (bLast==TEXT('x') && b ==TEXT('+') && nRadix == 10)
  196. continue ;
  197. /* if the last character was a 'x' & this is '-' - change
  198. it to be the code for SIGN */
  199. if (bLast==TEXT('x') && b==TEXT('-') && nRadix == 10)
  200. {
  201. bLast = b ;
  202. b = IDC_SIGN ;
  203. goto MappingDone ;
  204. }
  205. /* -by- AmitC */
  206. /*--------------------------------------------------------------------------*/
  207. /* Check for control character. */
  208. if (bLast==TEXT(':'))
  209. nControl=128;
  210. else
  211. nControl=0;
  212. bLast=b;
  213. if (b==TEXT(':'))
  214. continue;
  215. b=toupper(b)+nControl;
  216. nx=0;
  217. while (b!=rgbMap[nx*2] && nx < CHARSCAN)
  218. nx++;
  219. if (nx==CHARSCAN)
  220. break;
  221. b=(WORD)rgbMap[(nx*2)+1];
  222. if (nRadix != 10)
  223. {
  224. switch(b)
  225. {
  226. case IDC_DEG:
  227. case IDC_RAD:
  228. case IDC_GRAD:
  229. b=IDC_DWORD+(b-IDC_DEG);
  230. break;
  231. }
  232. }
  233. // REVIEW NOTE:
  234. // Conversion of IDC_MOD to IDC_PERCENT done in WM_COMMAND
  235. // processing so that keyboard accelerator and paste are
  236. // handled in the same place. The old conversion was broken
  237. // anyway and actually happened in
  238. MappingDone:
  239. /* Send the message to the window. */
  240. SendMessage(g_hwndDlg, WM_COMMAND, GET_WM_COMMAND_MPS(b, 0, 1));
  241. /* Note that we may need to apply the "+/-" key (IDC_SIGN)
  242. now. (If it had been applied earlier, it would have
  243. been ignored.) Note further that it can't be applied if we
  244. have seen only the "-0" of something like "-0.1". */
  245. if(bNeedIDC_SIGN && (IDC_0 != b))
  246. {
  247. SendMessage(g_hwndDlg, WM_COMMAND, GET_WM_COMMAND_MPS(IDC_SIGN, 0, 1));
  248. bNeedIDC_SIGN = FALSE;
  249. }
  250. }
  251. GlobalUnlock(hClipData);
  252. }
  253. }
  254. CloseClipboard();
  255. break;
  256. }
  257. case IDM_ABOUT:
  258. /* Start the About Box. */
  259. if(ShellAbout(g_hwndDlg, rgpsz[IDS_CALC], NULL, LoadIcon(hInst, (LPTSTR)TEXT("SC"))) == -1)
  260. MemErrorMessage();
  261. break;
  262. case IDM_SC:
  263. case IDM_SSC:
  264. {
  265. INT nTemp;
  266. TCHAR szWinIni[2];
  267. nTemp = (INT) nFunc - IDM_SC;
  268. if (nCalc != nTemp)
  269. {
  270. szWinIni[0] = TEXT('0') + nTemp;
  271. szWinIni[1]=0;
  272. WriteProfileString(szAppName, TEXT("layout"), szWinIni);
  273. if (hStatBox && !nCalc)
  274. SetStat(FALSE);
  275. nCalc = nTemp;
  276. InitSciCalc(TRUE);
  277. }
  278. break;
  279. }
  280. case IDM_USE_SEPARATOR:
  281. {
  282. gbUseSep = !gbUseSep;
  283. CheckMenuItem(g_hDecMenu, IDM_USE_SEPARATOR,
  284. MF_BYCOMMAND|(gbUseSep ? MF_CHECKED : MF_UNCHECKED));
  285. if (g_hHexMenu)
  286. {
  287. CheckMenuItem(g_hHexMenu, IDM_USE_SEPARATOR,
  288. MF_BYCOMMAND | \
  289. (gbUseSep ? MF_CHECKED:MF_UNCHECKED));
  290. }
  291. WriteProfileString(szAppName,TEXT("UseSep"),
  292. (gbUseSep ? TEXT("1") : TEXT("0")));
  293. break;
  294. }
  295. case IDM_HELPTOPICS:
  296. HtmlHelp(GetDesktopWindow(), rgpsz[IDS_CHMHELPFILE], HH_DISPLAY_TOPIC, 0L);
  297. break;
  298. }
  299. return;
  300. }