This is NewsgroupSet.m in view mode; [Download] [Up]
#include <stdio.h>
#include <assert.h>
#include <math.h>
#import "Alexandra.h"
#import "NewsgroupSet.h"
#import "readline.h"
#import "Newsgroup.h"
#import "ArticleSetMatrix.h"
#import "NNTP.h"
#import "ArticleSet.h"
#import "ArticleViewControl.h"
#import <misckit/MiscSortedList.h>
#import "descriptors.h"
#import "response_codes.h"
#import "NewsGroupSetBrowser.h"
#import <misckit/MiscAppDefaults.h>
#import "MatrixScroller.h"
@implementation NewsgroupSet
- init
{
[super init];
myMList=[[MiscSortedList alloc] init];
[myMList setSortEnabled:FALSE];
[myMList setSortOrder:Misc_ASCENDING];
[ERROR_MANAGER addObserver:self
selector:@selector(dumpNewsrc:) forError:S15];
[ERROR_MANAGER addObserver:self
selector:@selector(updateNewsgroups)
forError:ENOTEPrefsChanged2];
unselAction=@selector(clearMatrix);
return self;
}
- free
{
[myMList makeObjectsPerform:@selector(free)];
[myMList free];
[ERROR_MANAGER removeObserver:self forError:S15];
[ERROR_MANAGER removeObserver:self forError:ENOTEPrefsChanged2];
return [super free];
}
- scanNewsrcAndActive
{
char aGroup[255];
int i,j;
FILE *newsrc;
Newsgroup *aNewsgroup;
HashTable *positionInList;
const char *home;
const char *nntp_server;
char *filename;
char *buffer;
int position;
BOOL exists;
Storage *array;
newsgroupDesc *ngDesc;
int statusCode;
// compose name of newsrc file
home=NXHomeDirectory();
nntp_server=[nntpServer serverName];
filename=(char *)malloc((strlen(home)+strlen(nntp_server)+12)*sizeof(char));
strcpy(filename,home);
strcat(filename,"/.");
strcat(filename,nntp_server);
strcat(filename,".newsrc");
// open newsrc file, parse all lines and make newsgroup list
exists=FALSE;
newsrc=fopen(filename,"r");
if(newsrc!=NULL){
exists=TRUE;
while(!feof(newsrc)){
readline(newsrc);
buffer=get_buffer();
i=0;
while(buffer[i]!='\0' && buffer[i]!=':' && buffer[i]!='!'){
i++;
}
if(buffer[i]!='\0'){
strncpy(aGroup,buffer,i);
aGroup[i]='\0';
aNewsgroup=[[[[Newsgroup alloc] initTextCell:aGroup] setBogus:TRUE] unsetTag];
if((buffer[i+1]!='\0')&&(buffer[i+2]!='\0'))
[aNewsgroup setReadList:(buffer+i+2)];
else
[aNewsgroup setReadList:""];
if(buffer[i]==':')
[aNewsgroup setSubscribed];
[myMList addObject:aNewsgroup];
}
}
}
fclose(newsrc);
free(filename);
//put every newsgroupname in a hashtable
j=[myMList count];
positionInList=[[HashTable alloc] initKeyDesc:"*" valueDesc:"i" capacity:(int)floor(j*1.3)];
for(i=0;i<j;i++)
[positionInList insertKey:[[myMList objectAt:i] stringValue] value:(void *)i+1];
//ISSUE LIST COMMAND
//Slow link feature means don't do the "list" command
if(([nntpServer slowLink])&&([nntpServer timeTag])&&(exists)){
j=[myMList count];
for(i=0;i<j;i++){
aNewsgroup=[myMList objectAt:i];
[[[aNewsgroup unsetTag] setBogus:FALSE] setPostable:'y'];
if([aNewsgroup isSubscribed]==TRUE)
if((statusCode=[nntpServer requestGroup:aNewsgroup])!=OK_GROUP){ //get min+max article
[aNewsgroup setBogus:TRUE];
}
}
//see if any new groups
array=[[Storage alloc] initCount:0 elementSize:sizeof(newsgroupDesc) description:"{*llc}"];
[nntpServer scanNewGroups:array];
j=[array count];
if(j>0) //new groups?
for(i=0;i<j;i++){
BOOL found;
newsgroupDesc *aNGDesc=(newsgroupDesc *)[array elementAt:(unsigned)i];
if([self lookupGroup:aNGDesc->groupname found:&found],found==FALSE){
aNewsgroup=[[Newsgroup alloc] initTextCell:aNGDesc->groupname];
[[[[[aNewsgroup setBogus:FALSE] setMin:aNGDesc->min] setMax:aNGDesc->max] setPostable:aNGDesc->post] setTag]; //set tag-> new group
[myMList addObject:aNewsgroup];
}
}
for(i=0;i<j;i++)
free(((newsgroupDesc *)[array elementAt:(unsigned)i])->groupname);
[array free];
}
else{ //NO SLOW LINK OR FIRST TIME PROGRAM WAS STARTED (NO TIMETAG)
//get active newsgroups from nntp server
array=[[Storage alloc] initCount:0 elementSize:sizeof(newsgroupDesc) description:"{*llc}"];
[nntpServer scanActive:array];
// parse active newsgroups
j=[array count];
for(i=0;i<j;i++){
ngDesc=(newsgroupDesc *)[array elementAt:(unsigned)i];
position=(int)[positionInList valueForKey:ngDesc->groupname];
//new group?
if(position==0){
aNewsgroup=[[[Newsgroup alloc] initTextCell:ngDesc->groupname] setTag];
[myMList addObject:aNewsgroup];
}
else
aNewsgroup=[myMList objectAt:(position-1)]; // subtract one of position
[[[[aNewsgroup setBogus:FALSE] setMin:ngDesc->min] setMax:ngDesc->max] setPostable:ngDesc->post];
free(ngDesc->groupname);
}
[array free];
}
[positionInList free];
//remove bogus and unvalid Newsgroups
for(i=[myMList count]-1;i>=0;i--){
id aNewsgroup=[myMList objectAt:i];
if([aNewsgroup bogus] || strchr([aNewsgroup stringValue],':'))
[[myMList removeObjectAt:i] free];
}
//approximate the number of unread articles in every group
j=[myMList count];
for(i=0;i<j;i++)
[[myMList objectAt:i] approxNumUnread];
//check for new newsgroups in newsgroup list (new ng <-> ng is taged)
exists=FALSE;
j=[myMList count];
for(i=0;i<j;i++)
if([[myMList objectAt:i] isTaged]==TRUE){
exists=TRUE;
break;
}
if(exists==TRUE)
[myMatrix setButtonTitle:"New Newsgroups"]; //some new groups
else{
[myMatrix setButtonTitle:"Subscribed Newsgroups"]; //no new groups
j=[myMList count];
for(i=0;i<j;i++){
aNewsgroup=[myMList objectAt:i];
// setTag <-> newsgroup is visible in matrix <-> newsgroup is subscribed
if([aNewsgroup isSubscribed]==TRUE)
[aNewsgroup setTag];
else
[aNewsgroup unsetTag];
}
}
return self;
}
- newGroups:sender
{
Storage *array;
int i,j;
newsgroupDesc *aNGDesc;
Newsgroup *aNewsgroup;
BOOL found;
array=[[Storage alloc] initCount:0 elementSize:sizeof(newsgroupDesc) description:"{*llc}"];
[nntpServer scanNewGroups:array];
j=[array count];
if(j==0){
NXBeep();
[myMatrix updateButtonTitle];
}
else{
[myMList makeObjectsPerform:@selector(unsetTag)];
[myMatrix setButtonTitle:"New Newsgroups"];
for(i=0;i<j;i++){
aNGDesc=(newsgroupDesc *)[array elementAt:(unsigned)i];
if([self lookupGroup:aNGDesc->groupname found:&found],found==FALSE){
aNewsgroup=[[Newsgroup alloc] initTextCell:aNGDesc->groupname];
[[[[aNewsgroup setBogus:FALSE] setMin:aNGDesc->min] setMax:aNGDesc->max] setPostable:aNGDesc->post];
[[aNewsgroup approxNumUnread] setTag];
[myMList addObject:aNewsgroup];
}
}
[[myMatrix reloadMatrix] display];
[self sync];
}
j=[array count];
for(i=0;i<j;i++)
free(((newsgroupDesc *)[array elementAt:(unsigned)i])->groupname);
[array free];
return self;
}
-newNews:sender
{
int i,j;
int statusCode;
BOOL slowLink;
id oldSelection;
BOOL oldSelNewNews=FALSE;
BOOL cellsRemoved=FALSE;
j=[myMList count];
if(j==0)
return self;
oldSelection=currentSelection;
slowLink=[nntpServer slowLink];
for(i=0;i<j;i++){
Newsgroup *aGroup=[myMList objectAt:i];
if(aGroup==nil) continue;
if(([aGroup isSubscribed]==TRUE)||(aGroup==currentSelection)){
long oldMax=[aGroup maxNumber];
statusCode=[nntpServer requestGroup:aGroup];
if(statusCode!=OK_GROUP){
[myMatrix removeInvalidCell:aGroup andUpdate:FALSE];
i--; //list length gets smaller
j--;
if(oldSelection==aGroup)
oldSelection=nil;
cellsRemoved=TRUE;
}
else{
//BOOL setBack=TRUE;
long newMax=[aGroup maxNumber];
long diff=newMax-oldMax;
if(diff>0){
if(aGroup==oldSelection)
oldSelNewNews=TRUE;
if((slowLink==TRUE)&&([aGroup isDelayed]==TRUE)){
[aGroup approxNumUnread];
//setBack=FALSE;
}
else
[aGroup incNumberUnreadArticles:(int)diff];
}
}
}
}
if(cellsRemoved==TRUE)
[myMatrix update];
if(!strcmp([[myMatrix selectionButton] title],"Groups with Articles"))
[self displayGroupsWithUnreadNews:self];
if(currentSelection!=nil){
statusCode=[nntpServer requestGroup:currentSelection];
if(statusCode!=OK_GROUP){
[myMatrix removeInvalidCell:currentSelection];
return self;
}
if((oldSelNewNews==TRUE) && (currentSelection==oldSelection)){
id artMatrix=[theArticleSet theMatrix];
[currentSelection scanArticles:nntpServer visibleIn:artMatrix];
[artMatrix reloadMatrix];
[[[artMatrix display] window] flushWindow];
[theArticleSet sync];
}
if(currentSelection!=oldSelection){
currentSelection=nil;
[self selectNewsgroup:self];
}
}
if(cellsRemoved==FALSE)
[myMatrix display];
return self;
}
- updateNewsgroups
{
int i,j=[myMList count];
for(i=0;i<j;i++)
[[myMList objectAt:i] updateArticles];
[theArticleSet redisplayMatrix];
return self;
}
- dumpNewsrc:sender
{
int i,j;
Newsgroup *aNewsgroup;
char *filename,*oldfile;
const char *home;
const char *nntp_server;
NXStream *nrcStream;
const char *aString;
char aChar;
if([myMList count]==0)
return self;
nrcStream=NXOpenMemory(NULL,0,NX_READWRITE);
j=[myMList count];
for(i=0;i<j;i++){
aNewsgroup=[myMList objectAt:i];
aString=[aNewsgroup stringValue];
NX_ASSERT([aNewsgroup stringValue]!=NULL,"Newsgroup without name");
NXWrite(nrcStream,aString,strlen(aString));
if([aNewsgroup isSubscribed]==TRUE)
NXWrite(nrcStream,": ",2);
else
NXWrite(nrcStream,"! ",2);
[aNewsgroup dumpReadList:nrcStream];
NXSeek(nrcStream,(-1)*sizeof(char),NX_FROMCURRENT);
if(NXRead(nrcStream,&aChar,sizeof(char)),aChar==' ')
NXSeek(nrcStream,(-1)*sizeof(char),NX_FROMCURRENT);
NXWrite(nrcStream,"\n",1);
}
//rename + save new
home=NXHomeDirectory();
i=strlen(home);
nntp_server=[nntpServer serverName];
j=strlen(nntp_server);
filename=(char *)calloc(i+j+12,sizeof(char));
sprintf(filename,"%s/.%s.newsrc",home,nntp_server);
oldfile=(char *)malloc((strlen(filename)+2)*sizeof(char));
strcpy(oldfile,filename);
strcat(oldfile,"~");
rename(filename,oldfile);
free(oldfile);
NXSaveToFile(nrcStream,filename);
NXCloseMemory(nrcStream,NX_FREEBUFFER);
free(filename);
return self;
}
- displayAllGroups:sender
{
int i,j;
j=[myMList count];
for(i=0;i<j;i++)
[[myMList objectAt:i] setTag];
[[myMatrix reloadMatrix] display];
[myMatrix setButtonTitle:"All Newsgroups"];
return self;
}
- displaySubscribedGroups:sender
{
int i,j;
Newsgroup *oldNG;
j=[myMList count];
for(i=0;i<j;i++){
Newsgroup* aNewsgroup;
aNewsgroup=[myMList objectAt:i];
if([aNewsgroup isSubscribed])
[aNewsgroup setTag];
else
[aNewsgroup unsetTag];
}
[[myMatrix reloadMatrix] display];
oldNG=currentSelection;
[self sync];
if((numSelCells==1)&&(oldNG!=currentSelection)){
currentSelection=oldNG;
[self selectNewsgroup:self];
}
[myMatrix setButtonTitle:"Subscribed Newsgroups"];
return self;
}
- displayGroupsWithUnreadNews:sender
{
int i,j;
Newsgroup *oldNG;
j=[myMList count];
for(i=0;i<j;i++){
Newsgroup* aNewsgroup;
aNewsgroup=[myMList objectAt:i];
if([aNewsgroup isSubscribed] && [aNewsgroup numberUnreadArticles]>0)
[aNewsgroup setTag];
else
[aNewsgroup unsetTag];
}
if(currentSelection!=nil)
[currentSelection setTag];
[[myMatrix reloadMatrix] display];
oldNG=currentSelection;
[self sync];
if((numSelCells==1)&&(oldNG!=currentSelection)){
currentSelection=oldNG;
[self selectNewsgroup:self];
}
[myMatrix setButtonTitle:"Groups with Articles"];
return self;
}
- selectNewsgroup:sender
{
Newsgroup* oldNG;
[[myMatrix window] makeFirstResponder:myMatrix];
oldNG=currentSelection;
[self sync];
if(oldNG!=currentSelection)
if(numSelCells==1){
int statusCode=[nntpServer requestGroup:currentSelection];
if(statusCode!=OK_GROUP){
[myMatrix perform:@selector(removeInvalidCell:) with:currentSelection afterDelay:0.0 cancelPrevious:YES];
return self;
}
[currentSelection scanArticles:nntpServer];
[[theArticleSet theMatrix] setButtonTitle:"Unread Articles"];
[theArticleSet loadGroup:currentSelection];
[myMatrix display];
[self dumpNewsrc:self];
}
else
[nntpServer unselectCurrentGroup];
return self;
}
- (BOOL)selectNewsgroupNamed:(const char *)gname
{
BOOL found;
Newsgroup *aGroup;
int position;
position=[self lookupGroup:gname found:&found];
if(!found)
return FALSE;
aGroup=[myMList objectAt:position];
if(![aGroup isTaged])
[self displayAllGroups:self];
return [myMatrix selectNewsgroupNamed:gname];
}
- subscribeOrUnsubscribe:(BOOL)flag
{
/*flag==TRUE <=> subscribe */
int i,j;
List *selectionList=nil;
Newsgroup *aNewsgroup;
selectionList=[myMatrix getCurrSelections];
j=[selectionList count];
for(i=0;i<j;i++){
aNewsgroup=[selectionList objectAt:i];
if(flag==TRUE)
[aNewsgroup setSubscribed];
else
[aNewsgroup setUnsubscribed];
}
[selectionList free];
[myMatrix display];
return self;
}
- subscribe:sender
{
[self subscribeOrUnsubscribe:TRUE];
return self;
}
- unsubscribe:sender
{
[self subscribeOrUnsubscribe:FALSE];
return self;
}
- markAllRead:sender
{
int i,j;
id ng=[myMatrix getCurrSelections];
j=[ng count];
if(j==0){
NXRunAlertPanel("ALEXANDRA","No newsgroup(s) selected.",NULL,NULL,NULL);
return self;
}
else if(j>1){
int r=NXRunAlertPanel("ALEXANDRA",
"Catchup %d selected groups?",NULL,"Cancel",NULL,j);
if(r==NX_ALERTALTERNATE)
return self;
}
for(i=0;i<j;i++)
[[ng objectAt:i] markAllReadUntil:nil];
if(j==1)
[theArticleSet redisplayMatrix];
[myMatrix display];
return self;
}
- markAllUntilSelRead:sender;
{
id ng=[myMatrix getCurrSelections];
if([ng count]!=1)
return self;
[[ng objectAt:0] markAllReadUntil:[theArticleSet currentSelection]];
[theArticleSet redisplayMatrix];
[myMatrix display];
return self;
}
- markAllClever:sender;
{
id selectedArticle;
static time_t lastCatchup=0;
if(!currentSelection)
return [self markAllRead:self];
selectedArticle=[theArticleSet currentSelection];
if(!selectedArticle)
[self markAllRead:sender];
else{
time_t now=time(NULL);
if(now>lastCatchup+3)
[self markAllUntilSelRead:self];
else
[self markAllRead:sender];
lastCatchup=now;
}
return self;
}
- (int)lookupGroup:(const char *)aGroup found:(BOOL *)f
{
int cmpResult,j;
Newsgroup *aNewsgroup;
for(j=[myMList count]-1;j>=0;j--){
aNewsgroup=[myMList objectAt:j];
cmpResult=strcmp([aNewsgroup stringValue],aGroup);
if(cmpResult==0){
*f=TRUE;
return j;
}
}
*f=FALSE;
return(0);
}
- shuffleList:(id)sourceCell to:(id)destCell
{
unsigned int from,to;
from=[myMList indexOf:sourceCell];
to=[myMList indexOf:destCell];
NX_ASSERT(from!=NX_NOT_IN_LIST,"Internal DS mismatch");
NX_ASSERT(to!=NX_NOT_IN_LIST,"Internal DS mismatch");
[myMList removeObjectAt:from];
[myMList insertObject:sourceCell at:to];
return self;
}
- upOrDown:(int)delta
{
while([[theArticleSet theMatrix] selectNextCell:delta]==FALSE)
if([myMatrix selectNextCell:delta]==FALSE){
NXRunAlertPanel("ALEXANDRA","No more articles.",NULL,NULL,NULL);
break;
}
return self;
}
- upOrDownOnePage:(int)delta
{
NXRect wholeBox;
NXRect visibleBox;
id theText=[theArticleViewControl theText];
[theText getVisibleRect:&visibleBox];
[theText getFrame:&wholeBox];
if(((delta==-1) && NX_Y(&visibleBox)<=3.0) ||
((delta==1) && (NX_HEIGHT(&wholeBox) - NX_Y(&visibleBox) - NX_HEIGHT(&visibleBox))<=3.0))
[self upOrDown:delta];
else{
NX_Y(&visibleBox)+=delta*(NX_HEIGHT(&visibleBox)*0.75);
[theText scrollRectToVisible:&visibleBox];
}
return self;
}
- up:sender
{
[self upOrDown:-1];
return self;
}
- down:sender
{
[self upOrDown:1];
return self;
}
- upOnePage:sender
{
[self upOrDownOnePage:-1];
return self;
}
- downOnePage:sender
{
[self upOrDownOnePage:1];
return self;
}
- sortNewsgroupList:sender
{
[myMList unsort];
[myMList sort];
[myMatrix reloadMatrix];
[myMatrix display];
return self;
}
- switchToView:view
{
NXRect frame;
id sview;
id newOther,newMatrix;
char *defaultViewerStr;
const char *nntpname;
if([myMatrix isKindOf:[NewsGroupSetBrowser class]]){
newOther=myMatrix;
newMatrix=[otherView docView];
}
else{
newOther=[[myMatrix superview] superview];
newMatrix=otherView;
}
sview=[newOther superview];
[newOther getFrame:&frame];
[newOther removeFromSuperview];
[sview addSubview:otherView];
[otherView setFrame:&frame];
myMatrix=newMatrix;
[myMatrix loadMatrix];
if(currentSelection!=nil)
if([myMatrix isKindOf:[NewsGroupSetBrowser class]]){
const char *selName=[currentSelection stringValue];
char *path=(char *)malloc((strlen(selName)+2)*sizeof(char));
sprintf(path,".%s",selName);
[[myMatrix window] disableFlushWindow];
[myMatrix setAutodisplay:NO];
[myMatrix setPath:path];
[[myMatrix setAutodisplay:YES] display];
[[[myMatrix window] reenableFlushWindow] flushWindow];
free(path);
}
else{
[otherView display];
[myMatrix selectCell:currentSelection];
}
else
[otherView display];
otherView=newOther;
nntpname=[nntpServer serverName];
defaultViewerStr=(char *)malloc((strlen(nntpname)+21)*sizeof(char));
sprintf(defaultViewerStr,"BrowserViewEnabled %s",nntpname);
if([otherView isKindOf:[NewsGroupSetBrowser class]])
[NXApp setDefault:defaultViewerStr toBool:NO];
else
[NXApp setDefault:defaultViewerStr toBool:YES];
free(defaultViewerStr);
return self;
}
- switchToListView:sender
{
if([myMatrix isKindOf:[NewsGroupSetBrowser class]]){
id aCell;
[self switchToView:otherView];
if((aCell=[myMatrix selectedCell])!=nil)
[myMatrix scrollCellToVisible:[[myMatrix cellList] indexOf:aCell]
upperOffset:1.5 lowerOffset:1.5];
}
return self;
}
- switchToBrowserView:sender
{
if(![myMatrix isKindOf:[NewsGroupSetBrowser class]]){
[self switchToView:otherView];
[myMatrix scrollSelectionToVisible];
}
return self;
}
- (BOOL)selectViewCellEnabled:menuCell
{
if([menuCell action]==@selector(switchToListView:) &&
([myMatrix isKindOf:[NewsGroupSetBrowser class]]))
return TRUE;
if([menuCell action]==@selector(switchToBrowserView:) &&
(![myMatrix isKindOf:[NewsGroupSetBrowser class]]))
return TRUE;
return FALSE;
}
- (BOOL)selectURL:(const char *)urlstring
{
BOOL success=FALSE;
BOOL apanelWasRunning=FALSE;
char *groupname=NULL;
long seqnumber=0;
char *msgid=NULL;
BOOL isNewsURL=FALSE;
char *buf1,*buf2,*buf3;
if(!urlstring)
return FALSE;
buf1=NXCopyStringBuffer(urlstring);
// nntp or news url?
buf2=strstr(buf1,"news:");
if(buf2){
success=TRUE;
isNewsURL=TRUE;
buf2+=5;
}
else{
buf2=strstr(buf1,"nntp:");
if(buf2){
success=TRUE;
isNewsURL=FALSE;
buf2+=5;
}
}
if(!success){
NXRunAlertPanel("Service","No valid URL.",NULL,NULL,NULL);
apanelWasRunning=TRUE;
}
if(success){
[[myMatrix window] makeKeyAndOrderFront:self];
//skip any / or < chars
while(*buf2=='/' || *buf2=='<')
buf2++;
//get useful string
buf3=strpbrk(buf2,"\t >\r\n");
if(buf3)
*buf3='\0';
if(isNewsURL){
if(strchr(buf2,'@')){ // message-id news url
char **groups;
// first compose real messageid
msgid=malloc((strlen(buf2)+4)*sizeof(char));
strcpy(msgid,"<");
strcat(msgid,buf2);
strcat(msgid,">");
// get all groupnames
success=[nntpServer findArticle:msgid inGroups:&groups];
if(!success){
NXRunAlertPanel("Service","Article not available.",NULL,NULL,NULL);
apanelWasRunning=TRUE;
}
//find all group objects
if(success){
char **gp=groups;
MiscSortedList *groupList=[[MiscSortedList alloc] init];
[groupList setSortEnabled:NO];
[groupList setSortOrder:Misc_ASCENDING];
while(*gp){
BOOL found=FALSE;
int pos=[self lookupGroup:*gp found:&found];
if(found)
[groupList addObject:[myMList objectAt:pos]];
free(*gp);
gp++;
}
// find best group
if([groupList count]==0){
success=FALSE;
NXRunAlertPanel("Service","There's no such article available.",NULL,NULL,NULL);
apanelWasRunning=TRUE;
}
else{
int oldStype=[Newsgroup sortType];
[Newsgroup setSortType:SORT_BY_SELECT_PRIORITY];
[groupList sort];
[Newsgroup setSortType:oldStype];
groupname=NXCopyStringBuffer([[groupList objectAt:0] stringValue]);
}
[groupList free];
}
}
else{
groupname=NXCopyStringBuffer(buf2);
}
}
else{
char *t;
if(t=strchr(buf2,'/')){
*t='\0';
groupname=NXCopyStringBuffer(buf2);
seqnumber=atol(t+1);
}
else{
success=FALSE;
NXRunAlertPanel("Service","No valid URL.",NULL,NULL,NULL);
apanelWasRunning=TRUE;
}
}
}
if(success){
// select group
success=[self selectNewsgroupNamed:groupname];
if(!success){
NXRunAlertPanel("Service","There's no newsgroup named '%s'.",NULL,NULL,NULL,groupname);
apanelWasRunning=TRUE;
}
}
if(success){
// select article
if(isNewsURL && msgid)
success=[theArticleSet selectArticleWithMsgid:msgid];
else if(!isNewsURL && seqnumber>0)
success=[theArticleSet selectArticleWithNumber:seqnumber];
if(!success){
NXRunAlertPanel("Service","Could not find article.",NULL,NULL,NULL);
apanelWasRunning=TRUE;
}
}
if(groupname) free(groupname);
if(msgid) free(msgid);
if(buf1) free(buf1);
if(!success && !apanelWasRunning)
NXRunAlertPanel("Service","Could not perform service.",NULL,NULL,NULL);
return success;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.