windows-nt/Source/XPSP1/NT/shell/osshell/accesory/calc/scimenu.c
2020-09-26 16:20:57 +08:00

361 lines
14 KiB
C

/**************************************************************************/
/*** 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 <shellapi.h>
#include <ctype.h>
#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;
}