This is ArticlesMatrix.m in view mode; [Download] [Up]
// NewsarticlesMatrix.m
#import "ArticlesMatrix.h"
@implementation ArticlesMatrix
+ newFrame:(const NXRect *)frameRect
{
self = [super newFrame:frameRect];
numBitmaps = ARTICLE_NUM_BITMAPS;
[protoCell setNumBitmaps:numBitmaps];
numColumns = ARTICLE_NUM_COLUMNS;
[protoCell setNumColumns:numColumns];
tabs[0] = ARTICLE_TAB_0;
tabs[1] = ARTICLE_TAB_1;
[self calcTabs];
return self;
}
- setupNNTP:(FILE *)newnntpFile
{
nntpFile = newnntpFile;
}
- fakeReadGroup
{
Article *article;
seenStruct *seenData;
long numSeenStruct = [selectedNewsgroup->seenStorage count];
long firstAvailable, lastAvailable,
firstUnseen, lastUnseen, number;
int i;
firstAvailable = selectedNewsgroup->available.first;
lastAvailable = selectedNewsgroup->available.last;
for (number = firstAvailable; (number<=lastAvailable) && (lastAvailable>0);
number++) {
article = [Article newNumber:number];
[itemsList addObject:article];
}
seenData = (seenStruct *)(selectedNewsgroup->seenStorage->dataPtr);
for (i=-1; i<numSeenStruct; i++) {
if (i > -1)
firstUnseen = seenData[i].last+1;
else
firstUnseen = firstAvailable;
if (i < numSeenStruct-1)
lastUnseen = seenData[i+1].first-1;
else
lastUnseen = lastAvailable;
if ((firstUnseen <= lastAvailable) && (lastUnseen >= firstAvailable))
for (number = MAX(firstUnseen, firstAvailable);
number <= MIN(lastUnseen, lastAvailable); number++)
[[itemsList objectAt:number-firstAvailable] setSeen:FALSE];
}
[self updateCells];
[[self superview] display];
return self;
}
// this makes sure the articles' subjects have been read in before it
// actually draws.
- drawSelf:(const NXRect *)rects :(int)rectCount
{
int row, col;
NXPoint point = rects[0].origin;
int cellIndex, cellFirst, cellLast;
IconColumnCell *aCell;
if ([self getRow:&row andCol:&col forPoint:&point] != nil) {
cellFirst = row;
point.y += rects[0].size.height;
cellLast = numRows-1;
if ([self getRow:&row andCol:&col forPoint:&point] != nil)
cellLast = MIN(cellLast, row);
for (cellIndex=cellFirst; cellIndex<=cellLast; cellIndex++) {
while (([(aCell = ((IconColumnCell *)(((List *)cellList)
->dataPtr[cellIndex]))) data][1][0] == '\0')
&& (cellIndex < numRows)) {
[self readNNTPFromArticle:(Article *)(aCell->aux)];
}
}
}
return [super drawSelf:rects :rectCount];
}
- readNNTPFromArticle:(Article *)article
{
int inCode;
char inCodeText[BUFFER_SIZE];
int ch;
char subject[BUFFER_SIZE];
long number, last;
int articleIndex = [itemsList indexOf:article];
int row, col;
last = MIN(article->number+ARTICLE_CHUNK, selectedNewsgroup->available.last);
fprintf(nntpFile, "xhdr subject %ld-%ld\r\n", article->number, last);
fflush(nntpFile);
fseek(nntpFile, (long)0, SEEK_END);
fscanf(nntpFile, "%d %[^\r]\r\n", &inCode, &inCodeText);
if (inCode != OK_HEAD)
printf("No way, fix me HEAD.\n"); // fix
while ((ch = getc(nntpFile)) != '.') {
ungetc(ch, nntpFile);
fscanf(nntpFile, "%d %[^\r]\r\n", &number, &subject);
while ((article != nil) && (number > article->number)) {
article->bogus = TRUE;
if (!article->seen)
[self cellToggleSeen:article->cell];
article = [itemsList objectAt:++articleIndex];
}
if (article != nil) {
strcpy(article->subject, subject);
article = [itemsList objectAt:++articleIndex];
}
}
while ((article != nil) && (last > article->number)) {
article->bogus = TRUE;
if (!article->seen)
[self cellToggleSeen:article->cell];
article = [itemsList objectAt:++articleIndex];
}
fgetc(nntpFile); // \r
fgetc(nntpFile); // \n
fseek(nntpFile, (long)0, SEEK_END);
[self updateCells];
return self;
}
- (BOOL)itemVisible:item
{
Article *article = item;
BOOL highlighted = FALSE;
if (article->cell)
highlighted = [article->cell isHighlighted];
return (article->shown = ((showSeenArticles || !article->seen)
|| highlighted)
&& !article->bogus);
}
- updateCellVisible:(IconColumnCell *)aCell
{
Article *article = (Article *)aCell->aux;
int row, col;
BOOL newShown = [self itemVisible:article];
if (!newShown) {
if ([self getRow:&row andCol:&col ofCell:article->cell] != nil) {
[self removeRowAt:row andFree:TRUE];
[self sizeToCells];
}
}
return self;
}
- cellToggleSeen:(IconColumnCell *)articleCell
{
Article *article;
if (articleCell) {
article = (Article *)(articleCell->aux);
[article setSeen:!(article->seen)];
if (article->seen) {
[selectedNewsgroup addSeenFirst:article->number last: article->number];
} else {
[selectedNewsgroup removeSeenFirst:article->number
last: article->number];
}
[newsgroupsMatrix drawCell:[newsgroupsMatrix selectedCell]];
}
return self;
}
#ifdef stupid
- sendAction:(SEL)theAction to:theTarget
{
id ret;
ret = [super sendAction:theAction to:theTarget];
if (realSelectedCell) {
// mark the current article as read
[self seenArticleCell:realSelectedCell];
[self drawCell:realSelectedCell];
// this is convoluted in order to fill in gaps if available
// articles are non-contiguous
cellIndex = [cellList indexOf:realSelectedCell];
if (cellIndex == 0) {
[selectedNewsgroup
addSeenFirst: 1
last: ((Article *)realSelectedCell->aux)->number];
} else {
[selectedNewsgroup
addSeenFirst: (((Article *)
((IconColumnCell *)
[cellList objectAt:(cellIndex-1)])
->aux))->number+1
last: ((Article *)realSelectedCell->aux)->number];
}
}
return ret;
}
#endif
- toggleSeen:sender
{
[self sendAction:@selector(cellToggleSeen:) to:self forAllCells:FALSE];
[[self superview] display];
}
- showSeenArticles:sender
{
showSeenArticles = (BOOL)[sender intValue];
[self updateCells];
[self sendAction];
[[self superview] display];
}
- selectWayUp:sender
{
if (newsgroupsMatrix)
[newsgroupsMatrix selectUp:sender];
return self;
}
- selectWayDown:sender;
{
if (newsgroupsMatrix)
[newsgroupsMatrix selectDown:sender];
return self;
}
- setNewsgroup:sender
{
Newsgroup *newSelectedNewsgroup = [[sender selectedCell] aux];
newsgroupsMatrix = sender;
if (newSelectedNewsgroup != selectedNewsgroup) {
selectedNewsgroup = newSelectedNewsgroup;
[self empty];
if (selectedNewsgroup != nil) {
if ([selectedNewsgroup selectOnNNTP:nntpFile]) {
[self fakeReadGroup];
[self selectCellAt:-1 :-1];
} else
[newsgroupsMatrix updateCells];
[[newsgroupsMatrix superview] display];
}
}
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.