This is Article.m in view mode; [Download] [Up]
#import "Alexandra.h"
#import "Article.h"
#import "descriptors.h"
#import "headerfields.h"
#import "parsedate.h"
#import "rfc822realname.h"
#import "parse-header.h"
#import "plain-subject.h"
#import <time.h>
#import <misckit/MiscAppDefaults.h>
#import "Preferences.subproj/preferences.h"
static BOOL showAuthor,showSubject,showSize;
static int smallIs,largeIs;
static int sortType=0;
@implementation Article
+ initialize // Ein Article wird erst erzeugt nachdem das main-nib
{ // geladen wurde, d.h. die Default-Defaults sind schon
// vom Preferences Manager gesetzt!
if(self==[Article class])
{
[self prefsChanged];
[ERROR_MANAGER addObserver:self
selector:@selector(prefsChanged) forError:ENOTEPrefsChanged];
}
return self;
}
+ prefsChanged;
{
showAuthor=[NXApp defaultBoolValue:DEFAULT_SHOW_AUTHOR];
showSubject=[NXApp defaultBoolValue:DEFAULT_SHOW_SUBJECT];
showSize=[NXApp defaultBoolValue:DEFAULT_SHOW_SIZE];
smallIs=[NXApp defaultIntValue:DEFAULT_SMALL_ARTICLE];
largeIs=[NXApp defaultIntValue:DEFAULT_LARGE_ARTICLE];
return self;
}
+ setSortType:(int)t
{
sortType=t;
return self;
}
+ (int)sortType
{
return sortType;
}
- initWithNumber:(long)number
{
[self initTextCell:NULL];
[self setWrap:NO];
size=0;
unread=TRUE;
myNumber=number;
myHeader.fieldBody=(char **)calloc(FIELD_COUNT,sizeof(char *));
timeOfPosting=0;
authorRealName=NULL;
killed=FALSE;
return self;
}
- composeTitle
{
char *buf,*p=NULL;
BOOL a=FALSE;
BOOL b=FALSE;
int from,to,tsize=1;
if(showSubject && (p=myHeader.fieldBody[SUBJECT])){
a=TRUE;
tsize+=strlen(p);
}
if(showAuthor && (myHeader.fieldBody[FROM]!=NULL)){
rfc822_realname(myHeader.fieldBody[FROM],&from,&to);
if(from<to)
b=TRUE;
tsize+=to-from+6;
}
buf=calloc(tsize,sizeof(char));
if(a) strcpy(buf,p);
if(b){
strcat(buf," (");
strncat(buf,myHeader.fieldBody[FROM]+from,to-from+1);
strcat(buf,")");
}
[self setStringValueNoCopy:buf shouldFree:YES];
return self;
}
- parseHeader:(NXStream *)headerStream;
{
char *stream_buffer;
int len,a;
NXGetMemoryBuffer(headerStream,&stream_buffer,&len,&a);
parse_header(stream_buffer, len, myHeader.fieldBody, h_field_name, FIELD_COUNT,YES);
return self;
}
-free
{
int i;
for(i=0;i<FIELD_COUNT;i++)
if(myHeader.fieldBody[i]!=NULL)
free(myHeader.fieldBody[i]);
free(myHeader.fieldBody);
if(authorRealName!=NULL)
free(authorRealName);
return([super free]);
}
- (long)number
{
return myNumber;
}
- (headerDesc *)header
{
return &myHeader;
}
- (time_t)time
{
if((timeOfPosting==0)&&(myHeader.fieldBody[DATE]!=NULL)){
timeOfPosting=parsedate(myHeader.fieldBody[DATE]);
if(timeOfPosting==-1){
timeOfPosting=0;
free(myHeader.fieldBody[DATE]);
myHeader.fieldBody[DATE]=NULL;
}
}
return timeOfPosting;
}
- (const char *)realName;
{
if((authorRealName==NULL)&&(myHeader.fieldBody[FROM]!=NULL)){
int from,to;
rfc822_realname(myHeader.fieldBody[FROM],&from,&to);
if(from<to){
authorRealName=(char *)malloc((to-from+2)*sizeof(char));
strncpy(authorRealName,myHeader.fieldBody[FROM]+from,to-from+1);
authorRealName[to-from+1]='\0';
}
}
return authorRealName;
}
- setRead
{
unread=FALSE;
return self;
}
- setUnread
{
unread=TRUE;
return self;
}
- (BOOL)isRead
{
return((unread==FALSE)||(killed==TRUE));
}
- kill
{
killed=TRUE;
return self;
}
- unkill
{
killed=FALSE;
return self;
}
- (BOOL)isKilled
{
return killed;
}
- setTextAttributes:textObj
{
[super setTextAttributes:textObj];
if (unread==FALSE)
[textObj setTextGray:NX_DKGRAY];
else
[textObj setTextGray:NX_BLACK];
return textObj;
}
- unsetTag
{
myTag=0;
return self;
}
- setTag
{
myTag=1;
return self;
}
- (BOOL)isTaged
{
return((myTag==1)&&(killed==FALSE));
}
- (int)size
{
return size;
}
- setSize:(int)asize;
{
size=asize;
return self;
}
- (int)lines;
{
return lines;
}
- setLines:(int)lineCount;
{
lines=lineCount;
return self;
}
//------------------------------------
// MiscCompare protocol implementation
//------------------------------------
- (int)compare:anObject
{
int result=0;
BOOL r1,r2;
const char *s1,*s2;
headerDesc *h1,*h2;
switch (sortType) {
case SORT_BY_DATE:
result=[self time]-[anObject time];
break;
case SORT_BY_SUBJECT:
h1=[self header];
h2=[anObject header];
if(!h1 || !h2){
NXLogError("Article.m: article header is NULL pointer");
return 0;
}
s1=plain_subject(h1->fieldBody[SUBJECT],&r1);
s2=plain_subject(h2->fieldBody[SUBJECT],&r2);
if((s1==NULL)&&(s2==NULL)) result=0;
else if(s1==NULL) result=-1;
else if(s2==NULL) result=1;
else
result=strcasecmp(s1,s2);
if(result==0)
if(r1!=r2)
result=(r1? 1:-1);
else
result=[self time]-[anObject time];
break;
case SORT_BY_NUMBER:
result=[self number]-[anObject number];
break;
case SORT_BY_REAL_NAME:
s1=[self realName];
s2=[anObject realName];
if((s1==NULL)&&(s2==NULL)) result=0;
else if(s1==NULL) result=-1;
else if(s2==NULL) result=1;
else
result=strcasecmp(s1,s2);
break;
}
return result;
}
//-----------------------------------------------------------
// fancy drawing...
//-----------------------------------------------------------
#define IMAGEMARGIN 1.0
- calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect
{
[super calcCellSize:theSize inRect:aRect];
theSize->height+=1;
return self;
}
- drawInside:(const NXRect *)cellFrame inView:controlView
{
static NXImage *dotImages[] = { nil, nil, nil };
NXRect rect = *cellFrame;
NXPoint imageOrigin;
NXSize dotSize;
int sizecat;
struct _cFlags1 buf;
if(!dotImages[0])
{
dotImages[0] = [NXImage findImageNamed:"Article-short"];
dotImages[1] = [NXImage findImageNamed:"Article-medium"];
dotImages[2] = [NXImage findImageNamed:"Article-long"];
}
[dotImages[2] getSize:&dotSize];
PSsetgray((cFlags1.state || cFlags1.highlighted) ? NX_WHITE : NX_LTGRAY);
NXRectFill(cellFrame);
if(showSize && (lines>0))
{
imageOrigin.x = NX_MAXX(cellFrame) - IMAGEMARGIN * 2.0 - dotSize.width;
imageOrigin.y = NX_Y(cellFrame) + NX_HEIGHT(cellFrame) -
(NX_HEIGHT(cellFrame) - dotSize.height) / 2.0;
if(lines<=smallIs)
sizecat=0;
else if(lines<=largeIs)
sizecat=1;
else
sizecat=2;
[dotImages[sizecat] composite:NX_SOVER toPoint:&imageOrigin];
NX_WIDTH(&rect) -= (dotSize.width + IMAGEMARGIN * 2.0 - NX_X(&rect));
}
buf=cFlags1;
cFlags1.highlighted=cFlags1.state=0;
[super drawInside:&rect inView:controlView];
cFlags1=buf;
PSsetgray(NX_DKGRAY);
if (cFlags1.state || cFlags1.highlighted)
{
NXRect rectArray[2];
NXSetRect(&(rectArray[0]),NX_X(cellFrame),NX_Y(cellFrame),
NX_WIDTH(cellFrame),1);
NXSetRect(&(rectArray[1]),NX_X(cellFrame),NX_MAXY(cellFrame)-1,
NX_WIDTH(cellFrame), 1.0);
NXRectFillList(rectArray, 2);
}
return self;
}
- highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag
{
if(cFlags1.highlighted != flag)
{
cFlags1.highlighted = flag;
[self drawInside:cellFrame inView:controlView];
}
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.