/**************************************************************************/ /*** SCICALC Scientific Calculator for Windows 3.00.12 ***/ /*** By Kraig Brockschmidt, Microsoft Co-op, Contractor, 1988-1989 ***/ /*** (c)1989 Microsoft Corporation. All Rights Reserved. ***/ /*** ***/ /*** scimenu.c ***/ /*** ***/ /*** Functions contained: ***/ /*** MenuFunctions--handles menu options. ***/ /*** ***/ /*** Functions called: ***/ /*** DisplayNum ***/ /*** ***/ /*** Last modification Thu 06-Dec-1989 ***/ /*** (-by- Amit Chatterjee [amitc]) ***/ /*** ***/ /*** Modified the 'PASTE' menu to check for unary minus, e, e+ & e- ***/ /*** in DEC mode. ***/ /*** ***/ /*** Also modified the COPY code to not copy the last '.' in the display***/ /*** if a decimal point has not been hit. ***/ /*** ***/ /**************************************************************************/ #include "scicalc.h" #include "unifunc.h" #include "input.h" #include #include #define CHARSCAN 66 extern HWND hEdit, hStatBox; extern TCHAR szAppName[10], szDec[5], gszSep[5], *rgpsz[CSTRINGS]; extern LPTSTR gpszNum; extern BOOL bError; extern INT nLayout; extern HMENU g_hDecMenu; extern HMENU g_hHexMenu; extern CALCINPUTOBJ gcio; extern BOOL gbRecord; extern BOOL gbUseSep; /* Menu handling routine for COPY, PASTE, ABOUT, and HELP. */ VOID NEAR PASCAL MemErrorMessage(VOID) { MessageBeep(0); MessageBox(g_hwndDlg,rgpsz[IDS_STATMEM],NULL,MB_OK|MB_ICONHAND); } VOID APIENTRY MenuFunctions(DWORD nFunc) { INT nx; static const int rgbMap[CHARSCAN * 2]= { TEXT('0'),IDC_0, TEXT('1'),IDC_1, TEXT('2'),IDC_2, TEXT('3'),IDC_3, TEXT('4'),IDC_4, TEXT('5'),IDC_5, TEXT('6'),IDC_6, TEXT('7'),IDC_7, TEXT('8'),IDC_8, TEXT('9'),IDC_9, TEXT('A'),IDC_A, TEXT('B'),IDC_B, TEXT('C'),IDC_C, TEXT('D'),IDC_D, TEXT('E'),IDC_E, TEXT('F'),IDC_F, TEXT('!'),IDC_FAC, TEXT('S'),IDC_SIN, TEXT('O'),IDC_COS, TEXT('T'),IDC_TAN, TEXT('R'),IDC_REC, TEXT('Y'),IDC_PWR, TEXT('#'),IDC_CUB, TEXT('@'),IDC_SQR, TEXT('M'),IDM_DEG, TEXT('N'),IDC_LN, TEXT('L'),IDC_LOG, TEXT('V'),IDC_FE, TEXT('X'),IDC_EXP, TEXT('I'),IDC_INV, TEXT('H'),IDC_HYP, TEXT('P'),IDC_PI, TEXT('/'),IDC_DIV, TEXT('*'),IDC_MUL, TEXT('%'),IDC_MOD, TEXT('-'),IDC_SUB, TEXT('='),IDC_EQU, TEXT('+'),IDC_ADD, TEXT('&'),IDC_AND, TEXT('|'),IDC_OR, TEXT('^'),IDC_XOR, TEXT('~'),IDC_COM, TEXT(';'),IDC_CHOP, TEXT('<'),IDC_LSHF, TEXT('('),IDC_OPENP,TEXT(')'),IDC_CLOSEP, TEXT('\\'), IDC_DATA, TEXT('Q'), IDC_CLEAR, TEXT('Q')+128, IDC_CLEAR, // ":Q"=="Q"=>CLEAR TEXT('S')+128, IDC_STAT, // ":S"=>CTRL-S TEXT('M')+128, IDC_STORE, // ":M"=>CTRL-M TEXT('P')+128, IDC_MPLUS, // ":P"=>CTRL-P TEXT('C')+128, IDC_MCLEAR, // ":C"=>CTRL-C TEXT('R')+128, IDC_RECALL, // ":R"=>CTRL-R TEXT('A')+128, IDC_AVE, // ":A"=>CTRL-A TEXT('T')+128, IDC_B_SUM, // ":T"=>CTRL-T TEXT('D')+128, IDC_DEV, // ":D"=>CTRL-D TEXT('2')+128, IDC_DWORD, // ":2"=>F2 IDC_DWORD TEXT('3')+128, IDC_RAD, // ":3"=>F3 IDC_WORD TEXT('4')+128, IDC_GRAD, // ":4"=>F4 IDC_BYTE TEXT('5')+128, IDC_HEX, // ":5"=>F5 TEXT('6')+128, IDC_DEC, // ":6"=>F6 TEXT('7')+128, IDC_OCT, // ":7"=>F7 TEXT('8')+128, IDC_BIN, // ":8"=>F8 TEXT('9')+128, IDC_SIGN, // ":9"=>F9 TEXT('9')+3+128, IDC_QWORD // ":9"+2=>F12 (64 bit) }; switch (nFunc) { case IDM_COPY: { TCHAR szJunk[256]; // Copy the string into a work buffer. It may be modified. if (gbRecord) CIO_vConvertToString(&gpszNum, &gcio, nRadix); lstrcpy(szJunk, gpszNum); // Strip a trailing decimal point if it wasn't explicitly entered. if (!gbRecord || !CIO_bDecimalPt(&gcio)) { nx = lstrlen(szJunk); if (szJunk[nx - 1] == szDec[0]) szJunk[nx - 1] = 0; } /* Copy text to the clipboard through the hidden edit control.*/ SetWindowText(hEdit, szJunk); SendMessage(hEdit, EM_SETSEL, 0, -1); // select all text SendMessage(hEdit, WM_CUT, 0, 0L); break; } case IDM_PASTE: { HANDLE hClipData; char * lpClipData; char * lpEndOfBuffer; // used to ensure we don't GPF even if the clipboard data isn't NULL terminated WORD b, bLast; INT nControl; BOOL bNeedIDC_SIGN = FALSE; /* Get a handle on the clipboard data and paste by sending the*/ /* contents one character at a time like it was typed. */ if (!OpenClipboard(g_hwndDlg)) { MessageBox(g_hwndDlg, rgpsz[IDS_NOPASTE], rgpsz[IDS_CALC], MB_OK | MB_ICONEXCLAMATION); break; } hClipData=GetClipboardData(CF_TEXT); if (hClipData) { lpClipData=(char *)GlobalLock(hClipData); if (lpClipData) { lpEndOfBuffer = lpClipData + GlobalSize(hClipData); bLast=0; /* Continue this as long as no error occurs. If one */ /* does then it's useless to continue pasting. */ while (!bError && lpClipData < lpEndOfBuffer) { // we know that lpClipData points to a NULL terminated ansi // string because this is the format we requested the data in. // As a result we call CharNextA. b = *lpClipData; lpClipData = CharNextA( lpClipData ); /* Skip spaces and LF and CR. */ if (b==32 || b==10 || b==13 || b==gszSep[0]) continue; /* We're done if we get to a NULL character */ if ( b==0 ) break; if (b == szDec[0]) { bLast = b; b = IDC_PNT; goto MappingDone; } /*-----------------------------------------------------------------------------; ; Now we will check for certain special cases. These are: ; ; ; ; (1) Unary Minus. If bLast is still 0 and b is '-' we will force b to ; ; be the code for 'SIGN'. ; ; (2) If b is 'x' we will make it the code for EXP ; ; (3) if bLast is 'x' and b is '+' we will ignore b, as '+' is the dflt. ; ; (4) if bLast is 'x' and b is '-' we will force b to be SIGN. ; ; ; ; In case (3) we will go back to the top of the loop else we will jmp off ; ; to the sendmessage point, bypassing the table lookup. ; ;-----------------------------------------------------------------------------*/ /* check for unary minuses */ if (!bLast && b == TEXT('-')) { /* Doesn't work. bLast = b ; b = IDC_SIGN ; goto MappingDone ; */ bNeedIDC_SIGN = TRUE ; continue ; } /* check for 'x' */ if ((b == TEXT('x') || b == TEXT('e')) && nRadix == 10) { bLast = TEXT('x') ; b = IDC_EXP ; goto MappingDone ; } /* if the last character was a 'x' & this is '+' - ignore */ if (bLast==TEXT('x') && b ==TEXT('+') && nRadix == 10) continue ; /* if the last character was a 'x' & this is '-' - change it to be the code for SIGN */ if (bLast==TEXT('x') && b==TEXT('-') && nRadix == 10) { bLast = b ; b = IDC_SIGN ; goto MappingDone ; } /* -by- AmitC */ /*--------------------------------------------------------------------------*/ /* Check for control character. */ if (bLast==TEXT(':')) nControl=128; else nControl=0; bLast=b; if (b==TEXT(':')) continue; b=toupper(b)+nControl; nx=0; while (b!=rgbMap[nx*2] && nx < CHARSCAN) nx++; if (nx==CHARSCAN) break; b=(WORD)rgbMap[(nx*2)+1]; if (nRadix != 10) { switch(b) { case IDC_DEG: case IDC_RAD: case IDC_GRAD: b=IDC_DWORD+(b-IDC_DEG); break; } } // REVIEW NOTE: // Conversion of IDC_MOD to IDC_PERCENT done in WM_COMMAND // processing so that keyboard accelerator and paste are // handled in the same place. The old conversion was broken // anyway and actually happened in MappingDone: /* Send the message to the window. */ SendMessage(g_hwndDlg, WM_COMMAND, GET_WM_COMMAND_MPS(b, 0, 1)); /* Note that we may need to apply the "+/-" key (IDC_SIGN) now. (If it had been applied earlier, it would have been ignored.) Note further that it can't be applied if we have seen only the "-0" of something like "-0.1". */ if(bNeedIDC_SIGN && (IDC_0 != b)) { SendMessage(g_hwndDlg, WM_COMMAND, GET_WM_COMMAND_MPS(IDC_SIGN, 0, 1)); bNeedIDC_SIGN = FALSE; } } GlobalUnlock(hClipData); } } CloseClipboard(); break; } case IDM_ABOUT: /* Start the About Box. */ if(ShellAbout(g_hwndDlg, rgpsz[IDS_CALC], NULL, LoadIcon(hInst, (LPTSTR)TEXT("SC"))) == -1) MemErrorMessage(); break; case IDM_SC: case IDM_SSC: { INT nTemp; TCHAR szWinIni[2]; nTemp = (INT) nFunc - IDM_SC; if (nCalc != nTemp) { szWinIni[0] = TEXT('0') + nTemp; szWinIni[1]=0; WriteProfileString(szAppName, TEXT("layout"), szWinIni); if (hStatBox && !nCalc) SetStat(FALSE); nCalc = nTemp; InitSciCalc(TRUE); } break; } case IDM_USE_SEPARATOR: { gbUseSep = !gbUseSep; CheckMenuItem(g_hDecMenu, IDM_USE_SEPARATOR, MF_BYCOMMAND|(gbUseSep ? MF_CHECKED : MF_UNCHECKED)); if (g_hHexMenu) { CheckMenuItem(g_hHexMenu, IDM_USE_SEPARATOR, MF_BYCOMMAND | \ (gbUseSep ? MF_CHECKED:MF_UNCHECKED)); } WriteProfileString(szAppName,TEXT("UseSep"), (gbUseSep ? TEXT("1") : TEXT("0"))); break; } case IDM_HELPTOPICS: HtmlHelp(GetDesktopWindow(), rgpsz[IDS_CHMHELPFILE], HH_DISPLAY_TOPIC, 0L); break; } return; }