This is ArticleDisplay.m in view mode; [Download] [Up]
// ArticleDisplay.m - #import "ArticleDisplay.h" static const char *fieldNames[FIELD_COUNT] = { "Date", "Followup-to", "Newsgroups", "Subject", "Summary", "Keywords", "Organization", "From", "Reply-To" }; @implementation ArticleDisplay + new { self = [super new]; return self; } - setupNNTP:(FILE *)newnntpFile { nntpFile = newnntpFile; } - clear { int fieldIndex; for (fieldIndex=0; fieldIndex<FIELD_COUNT; fieldIndex++) [field[fieldIndex] setStringValue:""]; [bodyText setText:""]; } - readArticle { int inCode; char inCodeText[BUFFER_SIZE]; int ch; char aLine[BUFFER_SIZE]; int aLineLength, charIndex; char fieldName[BUFFER_SIZE]; int fieldIndex; BOOL found; int newLines; static char *textBuffer; static int textBufferLines = 0; int textBufferOffset; if (selectedArticle == nil) return self; [bodyText setText:""]; // HEAD fprintf(nntpFile, "head %ld\r\n", selectedArticle->number); 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 HEAD2.\n"); // fix for (fieldIndex=0; fieldIndex<FIELD_COUNT; fieldIndex++) bogusField[fieldIndex] = TRUE; while ((ch = fgetc(nntpFile)) != '.') { ungetc(ch, nntpFile); fscanf(nntpFile, "%[^\r]\r\n", &aLine); sscanf(aLine, "%[^:]:", fieldName); for (found=FALSE,fieldIndex=0; (!found) && (fieldIndex<FIELD_COUNT); fieldIndex++) if (strcmp(fieldName, fieldNames[fieldIndex]) == 0) { [field[fieldIndex] setStringValue:aLine]; bogusField[fieldIndex] = FALSE; found = TRUE; } if (!found) { if (strcmp(fieldName, "Lines") == 0) { sscanf(aLine, "Lines: %d", &newLines); } } } for (fieldIndex=0; fieldIndex<FIELD_COUNT; fieldIndex++) if (bogusField[fieldIndex]) { [field[fieldIndex] setStringValue:""]; } fgetc(nntpFile); // \r fgetc(nntpFile); // \n fseek(nntpFile, (long)0, SEEK_END); // BODY fprintf(nntpFile, "%s\r\n", (verbose?"article":"body")); fflush(nntpFile); fseek(nntpFile, (long)0, SEEK_END); fscanf(nntpFile, "%d %[^\r]\r\n", &inCode, &inCodeText); if (inCode != (verbose?OK_ARTICLE:OK_BODY)) printf("No way, fix me HEAD3.\n"); // fix if (textBufferLines == 0) textBuffer = calloc(newLines, BUFFER_SIZE); else textBuffer = realloc(textBuffer, newLines*BUFFER_SIZE); textBufferLines = newLines; textBufferOffset = 0; while (((ch = fgetc(nntpFile)) != '.') || ((ch = fgetc(nntpFile)) != '\r')) { ungetc(ch, nntpFile); if (fscanf(nntpFile, "%[^\r]\r\n", &aLine) == 1) aLineLength = strlen(aLine); else aLineLength = 0; if (rot) { for (charIndex=0; charIndex<aLineLength; charIndex++) { if (islower(aLine[charIndex])) aLine[charIndex] = (((aLine[charIndex] - 'a') + 13) % 26) + 'a'; if (isupper(aLine[charIndex])) aLine[charIndex] = (((aLine[charIndex] - 'A') + 13) % 26) + 'A'; } } strncpy(&(textBuffer[textBufferOffset]), aLine, aLineLength); textBuffer[textBufferOffset+aLineLength] = '\n'; textBufferOffset += aLineLength+1; } textBuffer[textBufferOffset] = '\0'; [bodyText setText:textBuffer]; fgetc(nntpFile); // \n fseek(nntpFile, (long)0, SEEK_END); return self; } - setArticle:sender { IconColumnCell *selectedCell = [sender selectedCell]; Article *newSelectedArticle = [selectedCell aux]; if (newSelectedArticle != selectedArticle) { selectedArticle = newSelectedArticle; if (selectedArticle != nil) { if (!selectedArticle->seen) { [sender cellToggleSeen:selectedCell]; [sender drawCell:selectedCell]; } [self readArticle]; } else [self clear]; } return self; } - setVerbose:sender { verbose = !verbose; // [sender setText:(verbose?"Hide Header":"Show Header")]; [self readArticle]; return self; } - setRot:sender { rot = !rot; [self readArticle]; return self; } - setDateDisplay:anObject { field[DATE] = anObject; return self; } - setFollowupToTextField:anObject { field[FOLLOWUP_TO] = anObject; return self; } - setNewsgroupsTextField:anObject { field[NEWSGROUPS] = anObject; return self; } - setSubjectTextField:anObject { field[SUBJECT] = anObject; return self; } - setSummaryTextField:anObject { field[SUMMARY] = anObject; return self; } - setKeywordsTextField:anObject { field[KEYWORDS] = anObject; return self; } - setOrganizationTextField:anObject { field[ORGANIZATION] = anObject; return self; } - setFromTextField:anObject { field[FROM] = anObject; return self; } - setReplyToTextField:anObject { field[REPLY_TO] = anObject; return self; } - setBodyText:anObject { bodyText = [anObject docView]; // starts as "ScrollText" return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.