This is ToDoItem.m in view mode; [Download] [Up]
/* * ToDoItem - implementation of ToDoItem, the basic unit of information * for the ToDoList program. The method -adjustPriority implements * the dynamic priority mechanism. * * You may freely copy, distribute and reuse the code in this example. * This code is provided AS IS without warranty of any kind, expressed * or implied, as to its fitness for any particular use. * * Copyright 1995 Ralph Zazula (rzazula@next.com). All Rights Reserved. * */ #import "ToDoItem.h" #import "RZ.h" #import <appkit/appkit.h> #import <math.h> typedef struct _toDoItemFlags { #ifdef __BIG_ENDIAN__ unsigned int type:8; unsigned int private:1; unsigned int completed:1; unsigned int _RESERVED:22; #else unsigned int _RESERVED:22; unsigned int completed:1; unsigned int private:1; unsigned int type:8; #endif } toDoItemFlags; #define _flags ((toDoItemFlags *)_reservedToDoItem1) @implementation ToDoItem + initialize { if([self class] == [ToDoItem class]) { [self setVersion:4]; } return self; } - initSubject:(char *)subj startDate:(long)start dueDate:(long)due completeDate:(long)completed type:(char)type isPrivate:(BOOL)privateFlag isCompleted:(BOOL)completeFlag data:(char *)buf dataLen:(int)len { if(self = [super init]) { _flags = (toDoItemFlags *)calloc(1, sizeof(toDoItemFlags)); [self setSubject:subj]; [self setStartDate:start]; [self setDueDate:due]; [self setType:type]; [self setPrivate:privateFlag]; /* don't want auto-calc of completion so don't use setCompleted: */ dateCompleted = completed ? completed : 0; _flags->completed = completeFlag; [self setData:buf]; } return self; } - initFromItem:(id <ToDoItems>)anItem { char *buf; int len; [anItem getData:&buf length:&len]; return [self initSubject:[anItem subject] startDate:[anItem startDate] dueDate:[anItem dueDate] completeDate:[anItem dateCompleted] type:[anItem type] isPrivate:[anItem isPrivate] isCompleted:[anItem isCompleted] data:buf dataLen:len]; } - init { return [self initSubject:NULL startDate:time(NULL) dueDate:(time(NULL)+60) completeDate:0 type:TODO_TYPE_NORMAL isPrivate:NO isCompleted:NO data:NULL dataLen:0]; } - free { if(subject) { NX_FREE(subject); subject = NULL; } if(data) { NX_FREE(data); data = NULL; dataLen = 0; } free(_flags); return [super free]; } - (char *)subject { return subject; } - (long)priority { return priority; } - (long)startDate { return startDate; } - (long)dueDate { return dueDate; } - (long)dateCompleted { return dateCompleted; } - (char)type { return _flags->type; } - (BOOL)isPrivate { return _flags->private; } - (BOOL)isCompleted { return _flags->completed; } - (const char *)asciiStartDate { static char buf[40]; if(!startDate) { return NULL; } strftime(buf, 40, "%m/%d/%y", localtime(&startDate)); return buf; } - (const char *)asciiCompletedDate { static char buf[40]; if(!dateCompleted) { return NULL; } strftime(buf, 40, "%m/%d/%y", localtime(&dateCompleted)); return buf; } - (const char *)asciiDueDate { static char buf[40]; switch(_flags->type) { case TODO_TYPE_NORMAL : case TODO_TYPE_APPOINTMENT : strftime(buf, 40, "%m/%d/%y", localtime(&dueDate)); break; case TODO_TYPE_HIGHPRIORITY : sprintf(buf, "ASAP!"); break; case TODO_TYPE_LOWPRIORITY : sprintf(buf, "LATER"); break; } return buf; } - getData:(char **)d length:(int *)len { *d = data; *len = dataLen; return self; } - setSubject:(const char *)s { subject = RZReplaceStringBuffer(&subject, s); return self; } - setPriority:(long)p { priority = p; return self; } - setStartDate:(long)newDate { startDate = newDate; return self; } - setDueDate:(long)newDate { dueDate = newDate; [self adjustPriority]; return self; } - setType:(char)newType { _flags->type = newType; priority = 0; return self; } - setPrivate:(BOOL)flag { _flags->private = flag; return self; } - setCompleted:(BOOL)flag { _flags->completed = flag; dateCompleted = flag ? time(NULL) : 0; return self; } - setData:(const char *)d { RZReplaceStringBuffer(&data, d); dataLen = data ? strlen(data) + 1 : 0; return self; } - setDataFromText:aText { NXStream *stream; BOOL failed = NO; stream = NXOpenMemory(NULL, 0, NX_READWRITE); NX_DURING [aText writeRichText:stream]; NX_HANDLER failed = YES; NX_ENDHANDLER if(!failed) { [self setDataFromStream:stream]; NXCloseMemory(stream, NX_FREEBUFFER); } return self; } - setDataFromStream:(NXStream *)stream { char *_data; int _dataLen, _maxLen; NXGetMemoryBuffer(stream, &_data, &_dataLen, &_maxLen); [self setData:_data]; return self; } - writeToStream:(NXStream *)stream { static id dummyText = nil; NXPrintf(stream, "Subject: %s\n",[self subject]); switch(_flags->type) { case TODO_TYPE_NORMAL : NXPrintf(stream, "Type: Normal\n"); break; case TODO_TYPE_APPOINTMENT : NXPrintf(stream, "Type: Appointment\n"); break; case TODO_TYPE_LOWPRIORITY : NXPrintf(stream, "Type: Low Priority\n"); break; case TODO_TYPE_HIGHPRIORITY : NXPrintf(stream, "Type: High Priority\n"); break; } NXPrintf(stream, "Created: %s\n",[self asciiStartDate]); NXPrintf(stream, "Due on: %s\n",[self asciiDueDate]); if(_flags->completed) { NXPrintf(stream, "Completed: %s\n",[self asciiCompletedDate]); } NXPrintf(stream, "\n"); if(dataLen) { NXStream *_stream; if(!dummyText) { dummyText = [[Text alloc] init]; } _stream = NXOpenMemory(NULL, 0, NX_READWRITE); NXWrite(_stream, data, dataLen); NXSeek(_stream, 0, NX_FROMSTART); [dummyText readRichText:_stream]; NXCloseMemory(_stream, NX_FREEBUFFER); [dummyText writeText:stream]; } return self; } #define LOW_PRIORITY_BASE 0 #define LOW_PRIORITY_SIZE 256 #define LOW_PRIORITY_MAX (LOW_PRIORITY_BASE + LOW_PRIORITY_SIZE) #define NORMAL_PRIORITY_BASE (LOW_PRIORITY_MAX + 1) #define NORMAL_PRIORITY_SIZE 512 #define NORMAL_PRIORITY_MAX (NORMAL_PRIORITY_BASE + NORMAL_PRIORITY_SIZE) #define HIGH_PRIORITY_BASE (NORMAL_PRIORITY_MAX + 1) #define HIGH_PRIORITY_SIZE 256 #define HIGH_PRIORITY_MAX (HIGH_PRIORITY_BASE + HIGH_PRIORITY_SIZE) #define ONE_DAY (60*60*24) #define ONE_YEAR (60*60*24*365) #define OLDEST_ITEM ONE_YEAR - adjustPriority /* * priority quantizer - I've decided to quantize priorities in the * range 0 - 1023 (if you have more than 1K of stuff to do, you're * in trouble :-) The priority space is divided into three regions: * 0 - 255 LOW PRIORITY ITEMS * 256 - 767 NORMAL PRIORITY ITEMS * 768 - 1023 HIGH PRIORITY ITEMS */ { long age = time(NULL) - startDate; long deadline = dueDate - time(NULL); if(_flags->completed) { priority = -dateCompleted; return self; } switch(_flags->type) { case TODO_TYPE_LOWPRIORITY : /* accrue priority over time but never get above LOW_PRIORITY_MAX */ priority = LOW_PRIORITY_BASE + LOW_PRIORITY_SIZE*((float)age/(float)OLDEST_ITEM); priority = MIN(priority, LOW_PRIORITY_MAX); break; case TODO_TYPE_NORMAL : /* increase priority as we get nearer the deadline */ if(deadline > 0) { /* quantize the time until the deadline */ priority = NORMAL_PRIORITY_MAX - NORMAL_PRIORITY_SIZE*((float)deadline/(float)OLDEST_ITEM); } else { /* past the due date, make max priority */ priority = NORMAL_PRIORITY_MAX; } priority = MIN(priority, NORMAL_PRIORITY_MAX); break; case TODO_TYPE_HIGHPRIORITY : /* accrue priority over time but never get above HIGH_PRIORITY_MAX */ priority = HIGH_PRIORITY_BASE + HIGH_PRIORITY_SIZE*((float)age/(float)OLDEST_ITEM); priority = MIN(priority, HIGH_PRIORITY_MAX); break; case TODO_TYPE_APPOINTMENT : /* drop into an appropriate slot based on the appointment date */ if(deadline > 10*ONE_DAY) { priority = LOW_PRIORITY_MAX; } else if(deadline < 2*ONE_DAY) { priority = HIGH_PRIORITY_MAX; } else { priority = NORMAL_PRIORITY_MAX; } break; } return self; } - awake { [self adjustPriority]; return self; } - read:(NXTypedStream *)ts { [super read:ts]; _flags = (toDoItemFlags *)calloc(1,sizeof(toDoItemFlags)); switch(NXTypedStreamClassVersion(ts, [[self class] name])) { case 4 : NXReadTypes(ts, "*llll*iI", &subject, &priority, &startDate, &dueDate, &dateCompleted, &data, &dataLen, _flags); break; case 3 : NXReadTypes(ts, "*llll*ii", &subject, &priority, &startDate, &dueDate, &dateCompleted, &data, &dataLen, _flags); break; case 2 : NXReadTypes(ts, "*lll*ii", &subject, &priority, &startDate, &dueDate, &data, &dataLen, _flags); break; case 1 : NXReadTypes(ts, "*lll*ic", &subject, &priority, &startDate, &dueDate, &data, &dataLen, &_flags->type); break; case 0 : NXReadTypes(ts, "*lll*i", &subject, &priority, &startDate, &dueDate, &data, &dataLen); break; } return self; } - write:(NXTypedStream *)ts { [super write:ts]; NXWriteTypes(ts, "*llll*iI", &subject, &priority, &startDate, &dueDate, &dateCompleted, &data, &dataLen, _flags); return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.