home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
warptlk3.zip
/
TOOLKIT
/
SAMPLES
/
REXX
/
API
/
REXXCALC
/
REXXCAL2.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-08-24
|
19KB
|
397 lines
/*********************************************************************/
/* */
/* REXXCAL2 - A simple PM based pocket calculator */
/* */
/*********************************************************************/
/* Standard C libraries */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
/* Include specific parts of the OS/2 and presentation manager */
/* definitions */
#define INCL_WIN
#include <os2.h>
#define INCL_RXFUNC
#include <rexxsaa.h>
/* Include the constants file created by the Dialog Box Editor. */
/* This include file defines symbols for all elements of the */
/* calculator dialog. */
#include "rexxcal2.h"
/* Declare prototypes for all subroutines. */
INT main(VOID); /* Main PM calculator program */
/* Calculator dialog */
MRESULT EXPENTRY Calculator(HWND, ULONG, MPARAM, MPARAM);
VOID ProcessArithmetic(LONG); /* Arithmetic processor */
VOID AddDigit(INT); /* add digit to display */
INT GetDisplay(VOID); /* get display value */
VOID SetDisplay(LONG); /* set new display */
VOID ProcessProgram(PSZ); /* process a programmed key */
/* Define some constants for the calculator dialog */
#define DISPLAY_WIDTH 20 /* width of display area */
#define MAX_DIGITS 8 /* maximum digits in display */
/* Global data used for the dialog */
HAB hab; /* Anchor block handle */
HWND hwndCalc; /* Handle for calculator */
/* dialog (created using */
/* the dialog editor) */
/* Global data used for the calculator */
UCHAR display[DISPLAY_WIDTH]; /* Displayed number string */
LONG accumulator; /* current register value */
LONG operand; /* converted operand number */
INT oldaction; /* pending key action */
INT digits; /* number of digits in display*/
/*********************************************************************/
/* main() - the main calculator program entry point */
/*********************************************************************/
INT main()
{
HMQ hmq; /* Message queue handle */
QMSG qmsg; /* Receive PM queue message */
/* startup PM usage */
hab = WinInitialize(0); /* Get the anchor block handle*/
hmq = WinCreateMsgQueue(hab, 0); /* Create the message queue */
/* register our window class */
WinRegisterClass(hab, "RexxCalc", Calculator, 0l, 0);
/* Load the calculator dialog. The dialog definitions are in */
/* rexxcalc.rc */
hwndCalc = WinLoadDlg(HWND_DESKTOP, HWND_DESKTOP,
NULL,
0,
REXXCALC, /* Dialog ID */
NULL);
WinSendMsg(hwndCalc, WM_SETICON, /* Set program icon */
(MPARAM)WinLoadPointer(HWND_DESKTOP, 0, REXXCALC), NULL);
/* set the window focus */
WinSetFocus(HWND_DESKTOP,
WinWindowFromID(hwndCalc, FID_CLIENT));
/* Process the standard Presentation Manager message loop until */
/* we are told to terminate */
/* While more messages */
while (WinGetMsg(hab, &qmsg, 0, 0, 0))
WinDispatchMsg(hab, &qmsg); /* dispatch application */
/* message handler */
/* The close option has been selected so we need to clean up */
/* our context. */
WinDestroyWindow(hwndCalc); /* Destroy the dialog window */
WinDestroyMsgQueue(hmq); /* Destroy the message queue */
WinTerminate(hab); /* Terminate PM usage */
return (0); /* Indicate successful */
/* completion */
}
/*********************************************************************/
/* */
/* Calculator() - the PM WinProc for handling the calculator dialog. */
/* The dialog itself has been created using the dialog box editor. */
/* This seperates the actual form of the calculator from the program */
/* source. */
/* */
/*********************************************************************/
MRESULT EXPENTRY Calculator(
HWND hwnd, /* window handle */
ULONG msg, /* dispatched message id */
MPARAM mp1, /* first message parameter */
MPARAM mp2 ) /* second message parameter */
{
ULONG action; /* Action to process */
switch (msg) { /* switch based on the message*/
/* received */
/* The initialization message has been received. We do some */
/* additional fixup of the dialog to make it look a little */
/* nicer. */
case WM_INITDLG:
accumulator = 0; /* clear the accumulator */
oldaction = 0; /* no pending operations */
operand = 0; /* no operand */
digits = 0; /* no digits in display */
SetDisplay(accumulator); /* set initial display value */
/* update the calculator */
/* display */
WinSetWindowText(WinWindowFromID(hwnd, DISPLAY), display);
return FALSE; /* initialization complete */
/* We are going away, time to post a quit message to the */
/* message loop. */
case WM_CLOSE:
/* Standard Close processing */
WinPostMsg(hwnd, WM_QUIT, 0L, 0L);
return FALSE; /* Exit now */
/* We've received a WM_COMMAND message. WM_COMMAND messages */
/* are generated by "pressing" buttons on the calculator. The */
/* additional parameters in the received message identify the */
/* button that was pressed */
case WM_COMMAND:
action = SHORT1FROMMP(mp1); /* Extract message sub-type */
switch (action) {
/* The following buttons will be processed by the actual */
/* calculator routine */
case BUTTON_CLEAR: /* Clear key */
accumulator = 0; /* clear the accumulator */
oldaction = 0; /* and any pending operations */
SetDisplay(accumulator); /* set the new display value */
/* update the calculator */
/* display */
WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
display);
return FALSE; /* All done */
case BUTTON_0: /* Numeric keys */
case BUTTON_1:
case BUTTON_2:
case BUTTON_3:
case BUTTON_4:
case BUTTON_5:
case BUTTON_6:
case BUTTON_7:
case BUTTON_8:
case BUTTON_9:
/* Add a digit to display */
AddDigit(action - BUTTON_0);
/* update the accumulator */
/* display */
WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
display);
return FALSE; /* All done */
/* The arithmetic operation keys all have a deferred */
/* execution. When one of these is pressed, the previous*/
/* arithmetic operation is processed using the */
/* accumulator and the current display. The new operator*/
/* is saved for later execution. If no operator exists, */
/* then the current display is moved to the accumulator */
/* and no arithmetic is done */
case BUTTON_MULTIPLY: /* Multiply key */
case BUTTON_DIVIDE: /* Division key */
case BUTTON_PLUS: /* Addition key */
case BUTTON_MINUS: /* Subtraction key */
case BUTTON_ENTER: /* "Total" key */
case BUTTON_PROGRAM1: /* programmed Rexx function */
case BUTTON_PROGRAM2: /* programmed Rexx function */
/* Process pending operations */
ProcessArithmetic(action);
SetDisplay(accumulator); /* set the new display value */
/* update the calculator */
/* display */
WinSetWindowText(WinWindowFromID(hwnd, DISPLAY),
display);
return FALSE; /* All done */
default: /* Unknown, can't handle this */
return FALSE;
}
case WM_ERASEBACKGROUND: /* disable background erase */
return MRFROMLONG(TRUE); /* don't allow this */
/* Message not handled by us. PM gives us first chance at all */
/* messages. Those we don't want to process we pass on to the */
/* default dialog procedure. */
default:
return WinDefWindowProc(hwnd, msg, mp1, mp2);
}
return FALSE; /* Should never reach here */
}
/*********************************************************************/
/* */
/* AddDigit(digit) - add a digit to the calculator display */
/* */
/*********************************************************************/
VOID AddDigit(
INT digit ) /* new digit to add */
{
digit += (INT)'0'; /* convert to character value */
if (digits < MAX_DIGITS) { /* if small enough */
display[digits++] = (UCHAR)digit; /* add new digit to display */
display[digits] = '\0'; /* add new string terminator */
}
}
/*********************************************************************/
/* */
/* GetDisplay() - Convert current display value into a binary long */
/* integer in the variable operand */
/* */
/*********************************************************************/
INT GetDisplay(void)
{
if (!digits) /* if nothing entered */
operand = 0L; /* just use zero */
else {
digits = 0; /* we've used this value */
operand = atol((const char *)display); /* convert the display value */
}
return operand; /* return the value */
}
/*********************************************************************/
/* */
/* SetDisplay(newdisplay) - Set the current display string to a new */
/* display value. */
/* */
/*********************************************************************/
VOID SetDisplay(
LONG newdisplay ) /* new number to display */
{
sprintf(display,"%ld",newdisplay); /* just use sprintf to update */
}
/*********************************************************************/
/* */
/* ProcessArithmetic(newaction) - Process any pending arithmetic */
/* operation updating the accumulator and the pending */
/* operation. */
/* */
/*********************************************************************/
VOID ProcessArithmetic(
LONG newaction ) /* new operator key pressed */
{
switch(oldaction) { /* process prior action key */
case BUTTON_MULTIPLY: /* multiplication */
accumulator *= GetDisplay(); /* multiplay accumulator by */
/* current display */
break; /* no more needed */
case BUTTON_DIVIDE: /* division */
accumulator /= GetDisplay(); /* divide accumulator by */
/* current display */
break; /* no more needed */
case BUTTON_PLUS: /* addition */
accumulator += GetDisplay(); /* add accumulator to */
/* current display */
break; /* no more needed */
case BUTTON_MINUS: /* subtraction */
accumulator -= GetDisplay(); /* subtract current display */
/* from accumulator */
break; /* no more needed */
case BUTTON_PROGRAM1: /* function done as a REXX */
/* program. Just call the */
/* external program. */
ProcessProgram("PROGRAM1.RXC"); /* process the program */
break;
case BUTTON_PROGRAM2: /* function done as a REXX */
/* program. Just call the */
/* external program. */
ProcessProgram("PROGRAM2.RXC"); /* process the program */
break;
case BUTTON_ENTER: /* enter key */
break; /* ignore old action */
default:
accumulator = GetDisplay(); /* just move display into the */
/* accumulator */
break; /* no more needed */
}
oldaction = newaction; /* remember the new action */
}
/*********************************************************************/
/* */
/* ProcessProgram() - Process a call to a programed Rexx function. */
/* The program is passed both the accumulator */
/* and the current display as strings. */
/* */
/*********************************************************************/
VOID ProcessProgram(
PSZ macro_name ) /* macro to invoke */
{
RXSTRING args[2]; /* passed argument strings */
RXSTRING result; /* returned result string */
UCHAR accum[MAX_DIGITS+1]; /* buffer for converted accum */
INT rc; /* Rexx return code */
SHORT return_code; /* function return code */
sprintf(accum, "%ld", accumulator); /* format accumulator */
/* build accumulator argument */
MAKERXSTRING(args[0], accum, strlen((const char *)accum));
/* and the current display */
MAKERXSTRING(args[1], display, digits);
/* ask for result in display */
MAKERXSTRING(result, display, DISPLAY_WIDTH);
rc = RexxStart(2, /* two arguments */
args, /* array of arguments */
macro_name, /* name of the macro */
NULL, NULL,
RXFUNCTION, /* calling this a function */
NULL,
&return_code, /* numeric value of return str*/
&result); /* returned string result */
display[result.strlength] = '\0'; /* convert back to ASCII-Z */
digits = result.strlength; /* set new length */
accumulator = GetDisplay(); /* accumulator is new display */
return; /* finished (ignore errors */
/* for now */
}