pendulum68k/pendDialog.c

1 line
3.7 KiB
C

#include "pendDialog.h"
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#define DLOG_PREFS 128
#define DLOG_ABOUT 129
#define PREFS_EDIT_START 3
#define PREFS_EDIT_END 7
enum {
PREFS_THETA=0,
PREFS_DTHETA,
PREFS_MU,
PREFS_LEN,
PREFS_GRAV
};
extern Boolean forceRedraw;
static Boolean valid_input(double *n, int no) {
if( *n == HUGE_VAL ||
*n == -HUGE_VAL ||
/*isnan(*n) ||*/ /* Cannot detect NANs */
(*n == 0.0 && errno == ERANGE)) {
return false;
}
switch(no) {
case PREFS_THETA: {
*n = fmod(*n, 2*M_PI);
if(*n > M_PI) *n -= 2*M_PI;
} return true;
case PREFS_LEN:
case PREFS_GRAV:
if(*n == 0.0) return false;
return true;
}
return true;
}
static Boolean parse_pi(char *str) {
return ((tolower(str[0]) == 'p') &&
(tolower(str[1]) == 'i') &&
(str[2] == '\0'));
}
static pascal Boolean aboutFilter(DialogPtr theDialog,
EventRecord *theEvent,
int *itemHit) {
int windowCode;
WindowPtr theWindow;
if(theEvent->what != mouseDown)
return false;
windowCode = FindWindow(theEvent->where, &theWindow);
if(windowCode != inContent || theWindow != theDialog)
return false;
return true;
}
void DialogAbout() {
int itemHit;
DialogPtr dlog = GetNewDialog(DLOG_ABOUT, NULL, (WindowPtr) -1L);
ModalDialog(&aboutFilter, &itemHit);
DisposDialog(dlog);
forceRedraw = true;
}
void DialogPrefs(struct dialog_prefs_t *p) {
union prefs_choose {
struct dialog_prefs_t *rec;
double *arr; /* Size 5 */
};
union prefs_choose args;
double tmpargs[5];
StringPtr dblText;
int itemHit, itemno;
Boolean valid_settings = false;
DialogPtr dlog;
dblText = (StringPtr) NewPtr(sizeof(Str255));
if(!dblText) return;
dlog = GetNewDialog(DLOG_PREFS, NULL, (WindowPtr) -1L);
if(!dlog) goto err_dlog;
args.rec = p;
/* Convert p's fields to EditText fields */
for(itemno = PREFS_EDIT_START; itemno <= PREFS_EDIT_END; ++itemno) {
int arrval = itemno - PREFS_EDIT_START;
int itemType;
ControlHandle itemHandle;
Rect itemBox;
PLEN(dblText) = sprintf((char *) PSTR(dblText), "%.9g", args.arr[arrval]);
GetDItem(dlog, itemno, &itemType, &itemHandle, &itemBox);
SetIText(itemHandle, dblText);
}
while(!valid_settings) {
ModalDialog(NULL, &itemHit);
if(itemHit == cancel) break;
valid_settings = true;
for(itemno = PREFS_EDIT_START; itemno <= PREFS_EDIT_END; ++itemno) {
int arrval = itemno - PREFS_EDIT_START;
int itemType;
ControlHandle itemHandle;
Rect itemBox;
char *endpos;
/* Convert EditText fields to p fields */
GetDItem(dlog, itemno, &itemType, &itemHandle, &itemBox);
GetIText(itemHandle, dblText);
/* If a field was left empty */
if(PLEN(dblText) == 0) {
valid_settings = false;
break;
}
/* Convert to Cstring */
if(PLEN(dblText) == 255)
PSTR(dblText)[255] = '\0';
else
PSTR(dblText)[PLEN(dblText)] = '\0';
/* Convert to double */
tmpargs[arrval] = strtod((char *) PSTR(dblText), &endpos);
if(endpos == (char *) PSTR(dblText)) {
/* Input: "pi" */
if(parse_pi(endpos)) {
tmpargs[arrval] = M_PI;
} else {
valid_settings = false;
break;
}
} else if(*endpos != '\0') {
/* Input: "xx.xxpi" */
if(parse_pi(endpos)) {
tmpargs[arrval] *= M_PI;
} else {
valid_settings = false;
break;
}
}
/* Modifies / Verifies input */
if(!valid_input(&tmpargs[arrval], arrval)) {
valid_settings = false;
break;
}
}
/* Error condition */
if(!valid_settings) {
SelIText(dlog, itemno, 0, 32767);
SysBeep(0);
}
}
if(itemHit == ok)
memcpy(p, tmpargs, sizeof(tmpargs));
DisposDialog(dlog);
err_dlog:
DisposPtr(dblText);
forceRedraw = true;
}