This is AddEvent.m in view mode; [Download] [Up]
//
// AddEvent.m
// Copyright (c) 1989, 1990, 1991 by Jiro Nakamura
// All rights reserved
//
// Handles the window that allows the user to add events.
// Also is the superclass of EventEdit, which lets the user edit events
//
// by Jiro Nakamura (jiro@shaman.com)
//
// RCS Information
// Revision Number-> $Revision: 2.15 $
// Last Revised-> $Date: 91/11/01 17:23:32 $
//
static char rcsid[] = "$Id: AddEvent.m,v 2.15 91/11/01 17:23:32 jiro Exp Locker: jiro $";
#import "AddEvent.h"
#import "Global.h"
#import "Cassandra.h"
#import "calendar.h"
#import <libc.h>
#import <strings.h> // for rindex() and strcpy()
#import <sys/file.h> // for access()
#import <appkit/Application.h>
#import <appkit/Button.h>
#import <appkit/Form.h>
#import <appkit/Matrix.h>
#import <appkit/Panel.h> // for NXRunAlertPanel
#import <appkit/OpenPanel.h> // for OpenPanel
#define RADIO_WEEK 0
#define RADIO_MON 1
#define RADIO_MDAY 2
#define RADIO_YEAR 3
#define RADIO_HOUR 4
#define RADIO_MIN 5
static char *frequencyChar[4] = {"day","week","month","year"};
static char *alarmExtensions[] = ALARMEXTENSIONS;
@implementation AddEvent
/* The main reason for the following method is just to avoid warnings
* about rcsid being unreferenced... Garance/Jul 28/94
*/
- (const char *) returnRcsid
{
return rcsid;
}
- open: sender
{
ev = [Event newAt: [global eventFile]];
[self resetDefaultValues : self];
return self;
}
- close
{
if( [self isDocEdited] && [self isVisible])
{
#ifdef DEBUG
fprintf(stderr,"Add/Edit Event window about to close."
"Checking save.\n");
#endif
if (NXRunAlertPanel("Changes not saved",
"You have made changes to this window. "
"Do you really want to throw them out?",
"Dump them","Cancel",NULL) == 0 )
return self;
}
[self setDocEdited: FALSE];
[super close];
[ev free];
return self;
}
- startOver:sender
{
[self resetDefaultValues: self];
return self;
}
- resetDefaultValues:sender
{
static struct tm time;
time = *timeNow();
[ev setTime: &time];
[ev setSec: 0];
[ev setSnoozeInt: 0];
[ev setSnoozeNo: 0];
[ev setPriority: 50];
[ev setDestroy: 1]; // Destroy not supported after v0.92
[ev setAnniversary: 0];
[ev setMessage: "Empty Message"];
[ev setAlarmSound: [global alarmSound]];
[ev setPlayAlarm: [global playAlarm]];
[ev setShowMessage: TRUE];
[self displayValues: sender];
[self displayValues: self];
[monthForm selectTextAt:0];
[dateRadioMatrix selectCellAt: 0: RADIO_MDAY];
return self;
}
- displayValues:sender
{
int temp, temp2;
[self displayDate: self];
if( [ev priority] < 10)
[priorityRadioMatrix selectCellAt: 0: 0];
else
{
if( [ev priority] <= 90)
[priorityRadioMatrix selectCellAt: 0:1];
else
[priorityRadioMatrix selectCellAt: 0:2];
}
[messageForm setStringValue: [ev message] at:0];
[messageButton setState: [ev showMessage]];
[self message: self];
[alarmSoundForm setStringValue: [ev alarmSound] at:0];
switch( [ev alarmAction] )
{
case 1: // playSound
case 2: // playAndDeleteSound
[alarmSoundRadioMatrix selectCellAt: 0 : 0];
break;
case 3: // runCommand
[alarmSoundRadioMatrix selectCellAt: 1 : 0];
break;
case 0: // nothing
default:
[alarmSoundRadioMatrix selectCellAt: 2 : 0];
break;
}
[self sound: self];
if( [ev snoozeNo] > 0)
{
[snoozeIntForm setIntValue: [ev snoozeInt] at:0];
[snoozeNoForm setIntValue: [ev snoozeNo] at:0];
[snoozeButton setState: TRUE];
}
else
{
[snoozeIntForm setIntValue: 5 at:0];
[snoozeNoForm setIntValue: 6 at:0];
[snoozeButton setState: FALSE];
}
[self snooze: self];
temp = [ev anniversary] % 100;
temp2 = [ev anniversary] / 100 - 1;
if( temp2 <= 0)
temp2 = 0;
[anniversaryForm setIntValue: ((temp == 0) ? 1 : temp) at:0];
[anniversaryRadioMatrix selectCellAt: 0 : temp2];
[anniversaryButton setState: ( [ev anniversary] > 0)];
[self anniversary:self];
[self makeKeyAndOrderFront : self];
// The window is new
[self setDocEdited: FALSE];
return self;
}
- displayDate: sender
{
int temp;
char min[5];
extern const char *shortMonths[12];
if( [global militaryTime])
{
[hourForm setIntValue: [ev hour]];
[amPmButton setEnabled: FALSE];
[amPmButton setState: AM];
}
else
{
temp = [ev hour];
if( temp > 12 )
temp -= 12;
if( temp == 0 )
temp = 12;
[hourForm setIntValue: temp at:0];
[amPmButton setEnabled: TRUE];
if( [ev hour] >= 12)
[amPmButton setState: PM];
else
[amPmButton setState: AM];
}
sprintf(min,"%02d",[ev min]);
[minuteForm setStringValue: min at:0];
[dayForm setIntValue: [ev mday] at:0];
[monthForm setStringValue: shortMonths[([ev mon])]
at: 0];
[yearForm setIntValue : ([ev year]+ 1900) at:0];
[self updateTestDate : [ev time]];
return self;
}
- dateUp: sender
{
struct tm *displayTime;
if( (displayTime = [self getDate: self]) == NULL)
return self;
switch( [dateRadioMatrix selectedCol])
{
case RADIO_WEEK:
displayTime->tm_mday += 7;
break;
case RADIO_MON:
displayTime->tm_mon ++;
break;
case RADIO_MDAY:
displayTime->tm_mday ++;
break;
case RADIO_YEAR:
displayTime->tm_year ++;
break;
case RADIO_HOUR:
displayTime->tm_hour ++;
break;
case RADIO_MIN:
displayTime->tm_min ++;
break;
}
fixTmStructure( displayTime);
[ev setTime: displayTime];
[self displayDate: self];
[self setDocEdited: TRUE];
return self;
}
- dateDown: sender
{
struct tm *displayTime;
if( (displayTime = [self getDate: self]) == NULL)
return self;
switch( [dateRadioMatrix selectedCol])
{
case RADIO_WEEK:
displayTime->tm_mday -= 7;
break;
case RADIO_MON:
displayTime->tm_mon --;
break;
case RADIO_MDAY:
displayTime->tm_mday --;
break;
case RADIO_YEAR:
displayTime->tm_year --;
break;
case RADIO_HOUR:
displayTime->tm_hour --;
break;
case RADIO_MIN:
displayTime->tm_min --;
break;
}
fixTmStructure( displayTime);
[ev setTime: displayTime];
[self displayDate: self];
[self setDocEdited: TRUE];
return self;
}
- anniversary:sender
{
BOOL aFlag;
#ifdef DEBUG
fprintf(stderr,"Anniversary button pressed. State = %d\n",
[anniversaryButton state]);
#endif
aFlag = [anniversaryButton state];
[anniversaryRadioMatrix setEnabled: aFlag];
[anniversaryForm setEnabled: aFlag];
[everyTextField setEnabled: aFlag];
[anniversaryUpButton setEnabled: aFlag];
[anniversaryUpButton setIcon:
(aFlag?RIGHTARROW:DISABLEDRIGHTARROW)];
[anniversaryDownButton setEnabled: aFlag];
[anniversaryDownButton setIcon:
(aFlag?LEFTARROW:DISABLEDLEFTARROW)];
if( aFlag )
[anniversaryForm selectTextAt: 0];
[self anniversaryFinished: self];
return self;
}
- anniversaryUp: sender
{
[anniversaryForm setIntValue:
([anniversaryForm intValueAt:0] +1) at:0];
[self anniversaryFinished: self];
return self;
}
- anniversaryDown: sender
{
int temp;
temp = [anniversaryForm intValueAt: 0] - 1;
if( temp > 1)
[anniversaryForm setIntValue: temp at:0];
else
[anniversaryForm setIntValue: 1 at:0];
[self anniversaryFinished: self];
return self;
}
- snooze: sender
{
BOOL aFlag; // the state of the snooze button
#ifdef DEBUG
fprintf(stderr,
"Snooze button pressed. State = %d\n",
[snoozeButton state]);
#endif
aFlag = [snoozeButton state];
[snoozeNoForm setEnabled: aFlag];
[snoozeIntForm setEnabled: aFlag];
[snoozeTimesTextField setEnabled: aFlag];
[snoozeMinutesTextField setEnabled: aFlag];
[snoozeIntUpButton setEnabled: aFlag];
[snoozeIntUpButton setIcon:
aFlag?RIGHTARROW:DISABLEDRIGHTARROW];
[snoozeIntDownButton setEnabled: aFlag];
[snoozeIntDownButton setIcon:
aFlag?LEFTARROW:DISABLEDLEFTARROW];
[snoozeNoUpButton setEnabled: aFlag];
[snoozeNoUpButton setIcon:
aFlag?RIGHTARROW:DISABLEDRIGHTARROW];
[snoozeNoDownButton setEnabled: aFlag];
[snoozeNoDownButton setIcon:
aFlag?LEFTARROW:DISABLEDLEFTARROW];
if( aFlag )
[snoozeIntForm selectTextAt:0];
[self snoozeFinished: self];
return self;
}
- snoozeIntUp: sender
{
[snoozeIntForm setIntValue:
([snoozeIntForm intValueAt: 0] + 1) at:0];
[self snoozeFinished: self];
return self;
}
- snoozeIntDown: sender
{
int temp;
temp = [snoozeIntForm intValueAt: 0] - 1;
if( temp > 1)
[snoozeIntForm setIntValue: temp at:0];
else
[snoozeIntForm setIntValue: 1 at:0];
[self snoozeFinished: self];
return self;
}
- snoozeNoUp: sender
{
[snoozeNoForm setIntValue:
([snoozeNoForm intValueAt: 0] + 1) at:0];
[self snoozeFinished: self];
return self;
}
- snoozeNoDown: sender
{
int temp;
temp = [snoozeNoForm intValueAt: 0] - 1;
if( temp > 1)
[snoozeNoForm setIntValue: temp at:0];
else
[snoozeNoForm setIntValue: 1 at:0];
[self snoozeFinished: self];
return self;
}
- snoozeFinished: sender
{
static char buf[50];
int sInt, sNo;
// The window has changed
[self setDocEdited: TRUE];
if( [snoozeButton state])
{
sInt = [snoozeIntForm intValueAt: 0];
sNo = [snoozeNoForm intValueAt: 0];
sprintf(buf, "time%s",(sNo == 1)?"":"s");
[snoozeTimesTextField setStringValue: buf];
sprintf(buf, "minute%s",(sInt == 1)?"":"s");
[snoozeMinutesTextField setStringValue: buf];
sprintf(buf,"Snooze alarm set every %d minute%s "
"for the next %d minute%s.",
sInt,
(sInt == 1)?"":"s",
(sInt * sNo),
((sInt * sNo) == 1)?"":"s"
);
[testSnoozeTextField setStringValue: buf];
}
else
[testSnoozeTextField setStringValue:
"The snooze function is not enabled."];
[self selectNextText: sender];
return self;
}
- message: sender
{
[messageForm setEnabled: [messageButton state]];
return self;
}
- messageFinished: sender
{
// The window has changed
[self setDocEdited: TRUE];
return self;
}
- sound: sender
{
int mode; // state of alarmSound matrix
mode = [alarmSoundRadioMatrix selectedRow];
[alarmSoundForm setEnabled: mode != 2];
[playButton setEnabled: mode == 0];
[setButton setEnabled: mode == 0];
[stopButton setEnabled: FALSE];
if( mode !=2)
[alarmSoundForm selectTextAt: 0];
return self;
}
- soundFinished: sender
{
// The window has changed
[self setDocEdited: TRUE];
if( [alarmSoundRadioMatrix selectedRow] == 0)
[self checkSound: self];
return self;
}
- playSound:sender
{
int error;
// If we are given a path name for an alarm sound, use the pathname
// in newFromSoundFile. Otherwise, we will have to go look for it
// using findSoundFor.
if( index((char *) [alarmSoundForm stringValueAt:0], '/')
== (char *) 0)
soundfile = [Sound findSoundFor:
(char *) [alarmSoundForm stringValueAt:0]];
else
soundfile = [[Sound alloc] initFromSoundfile:
(char *) [alarmSoundForm stringValueAt:0]];
if( soundfile != nil)
{
[soundfile setDelegate: self];
// From 1.0 Docs, Sound Kit, pp22-498
[Sound getVolume: &oldVolumeLeft:&oldVolumeRight];
if( [global volume] >= 0)
[Sound setVolume: [global volume]
: [global volume]];
error = [soundfile play];
if( error == 0)
{
[stopButton setEnabled : TRUE];
[playButton setEnabled : TRUE];
}
else
{
char errorString[200];
// Restore old volume
[Sound setVolume: oldVolumeLeft:
oldVolumeRight];
sprintf(errorString,
"Error #%d (%s) occured while "
"trying to play the sound <%s>.\n",
error, SNDSoundError(error),
[alarmSoundForm stringValueAt:0]);
NXRunAlertPanel("Alarm Error",errorString,
"Oh well...",NULL,NULL);
}
}
else
{
NXRunAlertPanel("Sound not found",
"I couldn't find that sound.",
"Oh well...",NULL,NULL);
[alarmSoundForm selectText:self];
}
return self;
}
- checkSound:sender
{
if( [alarmSoundRadioMatrix selectedRow] != 0 )
{
[self selectNextText:sender];
return self;
}
if( ([Sound findSoundFor:
(char *) [alarmSoundForm stringValueAt:0]] == nil) &&
( access( [alarmSoundForm stringValueAt:0], R_OK) == -1))
{
NXRunAlertPanel("Sound not found",
"I couldn't find that sound. "
"Please double check.",
"OK",NULL,NULL);
[alarmSoundForm selectText:self];
}
else
[self selectNextText:sender];
return self;
}
- stopSound:sender
{
[soundfile stop];
return self;
}
- willPlay : sender
{
#ifdef DEBUG
fprintf(stderr,"Alarm sound starting.\n");
#endif
[playButton setEnabled: FALSE];
return self;
}
- hadError: sender
{
char errorString[200];
int error = [[sender soundBeingProcessed] processingError];
sprintf(errorString,
"Error #%d (%s) occured while playing the sound <%s>.\n",
error, SNDSoundError(error),
[alarmSoundForm stringValueAt:0]);
NXRunAlertPanel("Alarm Error",errorString,
"Oh well...",NULL,NULL);
[stopButton setEnabled: FALSE];
if( [alarmSoundRadioMatrix selectedRow] == 0)
[playButton setEnabled: TRUE];
else
[playButton setEnabled: FALSE];
// Restore old volume
[Sound setVolume: oldVolumeLeft: oldVolumeRight];
return self;
}
- didPlay:sender
{
[soundfile free];
[stopButton setEnabled: FALSE];
if( [alarmSoundRadioMatrix selectedRow] == 0)
[playButton setEnabled: TRUE];
else
[playButton setEnabled: FALSE];
// Restore old volume
[Sound setVolume: oldVolumeLeft: oldVolumeRight];
return self;
}
- insertEventAndClose: sender
{
#ifdef DEBUG
fprintf(stderr,"InsertEventAndClose: %x is the flag.\n",
[NXApp currentEvent]->flags);
#endif
if( [self insertEvent:self] == nil) // user aborted
return self;
if( !( ([NXApp currentEvent]->flags) & NX_ALTERNATEMASK))
[self close];
[cassandra queueDidChange:self];
return self;
}
- insertEvent:sender
{
struct tm time, *timePointer;
int vAnniv;
time = *timeNow();
[ev setMessage: (char *) [messageForm stringValueAt:0]];
[ev setShowMessage: [messageButton state]];
switch( [alarmSoundRadioMatrix selectedRow] )
{
case 0: // sound
[ev setAlarmAction: 1];
break;
case 1: // runCommand
[ev setAlarmAction: 3];
break;
case 2: // nada
[ev setAlarmAction: 0];
break;
}
[ev setAlarmSound: (char *) [alarmSoundForm stringValueAt:0]];
if( (timePointer = [self getDate: self]) == NULL)
return nil;
[ev setTime: timePointer];
if( [anniversaryForm intValueAt:0] > 99)
{
NXRunAlertPanel("Anniversary Overload",
"Due to a design error that cannot be fixed "
"until a future version, you cannot have a reoccuring "
"event of more than 99 intervals.","OK",NULL,NULL);
[anniversaryForm selectTextAt: 0];
return nil;
}
vAnniv = ([anniversaryRadioMatrix selectedCol] +1 ) * 100;
[ev setAnniversary: ([anniversaryButton state]
? ([anniversaryForm intValueAt:0] + vAnniv)
: 0) ];
[ev setDestroy: 1]; // Destroy not supported after v0.9.2
[ev setSnoozeNo: ([snoozeButton state]
?[snoozeNoForm intValueAt:0]
:0)];
[ev setSnoozeInt: ([snoozeButton state]
?[snoozeIntForm intValueAt:0]
:0)];
[ev setPriority: [priorityRadioMatrix selectedCol]*50];
// If the user tries to put in an event with a date that has
// already past, inform them of the problem */
if( timeCompare( [ev time], &time ) == -1)
if( NXRunAlertPanel("Insert Warning",
"The date you have typed in has already passed. "
"Are you sure you want to insert it?",
"Insert","Cancel",NULL) == 0)
return nil;
[ev insertEvent];
// The window has been saved
[self setDocEdited: FALSE];
return self;
}
- setSound:sender
{
OpenPanel *myOpenPanel;
char tempDir[128], *tempFile;
myOpenPanel = [OpenPanel new];
if( index([ev alarmSound], '/') == (char *) 0) // If the present isn't
[ev setAlarmSound: ALARMSOUND]; // a path to a sound
strcpy(tempDir, [ev alarmSound]);
tempFile = rindex(tempDir,'/') + 1;
*(rindex (tempDir,'/')) = '\0';
#ifdef DEBUG
fprintf(stderr,"Open directory <%s> with file <%s>\n",
tempDir, tempFile);
#endif
if( [myOpenPanel runModalForDirectory: tempDir
file: tempFile types: alarmExtensions ] == 0)
return self;
#ifdef DEBUG
fprintf(stderr,"Opening file <%s>\n", [myOpenPanel filename]);
#endif
[ev setAlarmSound: (char *) [myOpenPanel filename]];
[alarmSoundForm setStringValue: [ev alarmSound] at: 0];
return self;
}
- setCassandra: anObject
{
cassandra = anObject;
return self;
}
- anniversaryFinished: sender
{
int radioCol, temp;
static char buf1[10], buf2[80];
// The window has changed
[self setDocEdited: TRUE];
radioCol = [anniversaryRadioMatrix selectedCol];
temp = [anniversaryForm intValueAt:0];
sprintf(buf1, "%s%c", frequencyChar[radioCol], (temp != 1)?'s':'\0');
[everyTextField setStringValue: buf1];
if( [anniversaryButton state])
{
if( temp == 1)
sprintf(buf2,"I will remind you every %s.",
frequencyChar[radioCol]);
else
sprintf(buf2,"I will remind you every %d %s.",
[anniversaryForm intValueAt:0],
buf1);
[testAnniversaryTextField setStringValue: buf2];
}
else
[testAnniversaryTextField setStringValue:
"This is not a reoccuring event."];
return self;
}
- updateTestDate : (struct tm *) tnow
{
static char buf[5];
extern const char *shortWeekDays[7];
[testDateTextField setStringValue:
ascMyTime( tnow, NOSEC, [global militaryTime])];
sprintf(buf,"%s", shortWeekDays[tnow->tm_wday]);
[wdayTextField setStringValue: buf ];
return self;
}
// Slight workaround for IB, since IB only likes values
// that return (id), but I need the (struct tm *) in another
// part of the program, so all we do is message getDate
// and ignore the return value.
- dateFinished: sender
{
// The window has changed
[self setDocEdited: TRUE];
[self getDate:sender];
return self;
}
- (struct tm*) getDate : (id) sender
{
static struct tm eventTime;
int month, year;
static char buf[100];
extern const char *shortMonths[12];
eventTime.tm_sec = 0;
// Get the hour form and make sure it is in good shape
strcpy(buf, [hourForm stringValueAt:0]);
eventTime.tm_hour = atoi(buf);
if( ![global militaryTime]) // if we are not using 24hr time
{
// then let's check for am/pm suffix
if( rindex( buf, 'a') || rindex(buf, 'A') ||
rindex(buf, 'n') || rindex(buf, 'N'))
[amPmButton setState: AM];
else if (rindex(buf, 'p') || rindex(buf,'P') ||
rindex(buf, 'm') || rindex(buf, 'M'))
[amPmButton setState: PM];
}
if( [global militaryTime])
{
if( eventTime.tm_hour < 0 || eventTime.tm_hour > 23)
{
NXRunAlertPanel( "Time error",
"I had trouble reading the hour "
"of the event. "
"We are using military time. "
"Please type in a number from "
"0-23 in the hour form.",
"OK",NULL,NULL);
[hourForm selectTextAt:0];
return NULL;
}
}
else
{
if( eventTime.tm_hour < 1 || eventTime.tm_hour > 12)
{
NXRunAlertPanel( "Time error",
"I had trouble reading the hour "
"of the event. "
"We are using am/pm time. "
"Please type in a number from 1-12 "
"in the hour form.",
"OK",NULL,NULL);
[hourForm selectTextAt:0];
return NULL;
}
if(eventTime.tm_hour == 12)
eventTime.tm_hour = 0;
eventTime.tm_hour += ( ([amPmButton state] == AM) ? 0 : 12);
}
// Get the minutes, check their format
eventTime.tm_min = [minuteForm intValueAt:0];
if( eventTime.tm_min < 0 || eventTime.tm_min > 59)
{
NXRunAlertPanel( "Time error",
"I had trouble reading the minute "
"of the event. "
"Please type in a number from 0-59 "
"in the minute form.",
"OK",NULL,NULL);
[minuteForm selectTextAt:0];
return NULL;
}
if( (month = monthFromAscii((char*) [monthForm stringValueAt:0])) == 0)
{
[monthForm selectTextAt:0];
return NULL; // If the month is in an incorrect format return
}
eventTime.tm_mon = ( month - 1);
// Get the year and check its format
year = [yearForm intValueAt:0];
if( year < 0 || year > 3000)
{
NXRunAlertPanel( "Time error",
"I had trouble reading the year of the event. "
"Please type in a number from 0-3000 in the "
"year form. See the manual or online help "
"for abbreviations.",
"OK",NULL,NULL);
[yearForm selectTextAt:0];
return NULL;
}
if( year < 70)
eventTime.tm_year = 100+ year;
if( year >= 70 && year < 100)
eventTime.tm_year = year;
if( year >= 100)
eventTime.tm_year = year - 1900;
// Get the day, check its form
eventTime.tm_mday = [dayForm intValueAt:0];
if( eventTime.tm_mday < 1 || eventTime.tm_mday > 31)
{
sprintf( buf, "I had trouble reading the day of the event. "
"Please type in a number from 1-31 in the "
"day form. (Hint: %s. %4d has %d days)",
shortMonths[eventTime.tm_mon],
eventTime.tm_year + 1900,
daysInMonth( eventTime.tm_mon + 1,
eventTime.tm_year + 1900));
NXRunAlertPanel( "Time error",buf,"OK",NULL,NULL);
[dayForm selectTextAt:0];
return NULL;
}
fixTmStructure( &eventTime);
[self updateTestDate: &eventTime];
[self selectNextText:sender];
return ( &eventTime);
}
- selectNextText:sender
{
// If the sender is a form class or a subclass of it, then
// we want the nextText private variable of the sender,
// to use to select the next Form after the user hits return
// but NeXT programmers haven't given us a method to access it
// so we take it by brute force (I know, I know.... breaking data
// abstractions...)
// This is out of Cox, "Object Orientated Programming, pp.147
if( [sender isKindOf: [Form class] ] )
{
struct idform {@defs(Form);} *p = (struct idform *)sender;
[p->nextText selectText:self];
}
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.