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.