This is INewsBase.m in view mode; [Download] [Up]
/*$Copyright: * Copyright (C) 1992.5.22. Recruit Co.,Ltd. * Institute for Supercomputing Research * All rights reserved. * NewsBase by ISR, Kazuto MIYAI, Gary ARAKAKI, Katsunori SUZUKI, Kok-meng Lue * * You may freely copy, distribute and reuse the code in this program under * following conditions. * - to include this notice in the source code, if it is to be distributed * with source code. * - to add the file named "COPYING" within the code, which shall include * GNU GENERAL PUBLIC LICENSE(*). * - to display an acknowledgement in binary code as follows: "This product * includes software developed by Recruit Co.,Ltd., ISR." * - to display a notice which shall state that the users may freely copy, * distribute and reuse the code in this program under GNU GENERAL PUBLIC * LICENSE(*) * - to indicate the way to access the copy of GNU GENERAL PUBLIC LICENSE(*) * * (*)GNU GENERAL PUBLIC LICENSE is stored in the file named COPYING * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. $*/ #import "INewsBase.h" #import "INntpIO.h" #import "IDataGroupBrowser.h" #import "IItemHeaderBrowser.h" #import "INXBrowserCellWithLinkedObject.h" #import "INewsgroupInfoD.h" #import "IUifNode.h" #import "SideSplitView.h" #import "IBaseControl.h" #import "IFolderDockMatrix.h" #import "data_types.h" #import <appkit/appkit.h> #import <stdio.h> #import <string.h> #import <mach/mach.h> #import <defaults/defaults.h> #import "data_types.h" #import "errdebug.h" #import "Localization.h" #define LoStr(key) doLocalString(NULL,key,NULL) //#define NNTPHOST "isrgwy" @implementation INewsBase + (char *)label { return ("NewsBase..."); } - init { BrowserMode newsgroupMode, articleMode; id loadingAlertPanel; NXModalSession loadingModalSession; [super init]; iNntpIO = nil; /* make zone for NewsBase */ newsbaseZone = NXCreateZone (vm_page_size, vm_page_size, YES); /* load window into screen */ LoadLocalNib("NewsBase.nib",self,NO,newsbaseZone); /* [NXApp loadNibSection:"NewsBase.nib" owner:self withNames:NO fromZone:(NXZone *)newsbaseZone]; */ /* open openNewsBasePanel */ if ([self openNewsBasePanel] == 0) { /* click cancel */ [NXApp delayedFree:self]; return(nil); } /* click OK */ /* read default database for newsgroupMode & articleMode */ if (strcmp(NXGetDefaultValue(OWNER, NEWSGROUPBROWSERMODE),"List")==0) { newsgroupMode = Flat; } else { newsgroupMode = Tree; } if (strcmp(NXGetDefaultValue(OWNER, ARTICLEBROWSERMODE),"ByReference") == 0) { articleMode = Tree; } else if (strcmp(NXGetDefaultValue(OWNER, ARTICLEBROWSERMODE),"BySubject") == 0) { articleMode = BySubject; } else if (strcmp(NXGetDefaultValue(OWNER, ARTICLEBROWSERMODE),"ByKeyword") == 0) { articleMode = ByKeyword; } else { articleMode = Flat; } [iNntpIO setArticleMode:articleMode]; /* open connection to nntp server */ loadingAlertPanel = NXGetAlertPanel(LoStr("NewsBase"), LoStr("Connecting to nntp server..., please wait"), NULL, NULL, NULL); [NXApp beginModalSession:&loadingModalSession for:loadingAlertPanel]; iNntpIO = [[INntpIO allocFromZone:newsbaseZone] initServer:iNntpHost allNews:iAllNewsFlag newsGroupMode:(BrowserMode)newsgroupMode articleMode:(BrowserMode)articleMode]; if (iNntpIO==nil) { /* failed to connect to server */ /* stop modal loop */ [NXApp endModalSession:&loadingModalSession]; [loadingAlertPanel orderOut:self]; NXFreeAlertPanel(loadingAlertPanel); /* free objects */ [oNewsReader free]; // [oViewControlPanel free]; [iNntpIO free]; [super free]; return nil; } [NXApp endModalSession:&loadingModalSession]; [loadingAlertPanel orderOut:self]; NXFreeAlertPanel(loadingAlertPanel); // set hierarchy of view and size from user's default data base [self _readWindowInfoFromDefaultDBandSetupViews]; /* make NewsBase window */ [self _setUpInterfaceWindow]; return self; } - _readWindowInfoFromDefaultDBandSetupViews { const char *buffer; NXRect newsbaseRect; NXSize folderDockSize, browserSplitViewSize, leftSideSize, rightSideSize; NXRect frameRect; /* setup for side spilited view, newsgroup browser and article browser */ [oNewsgroupView setAutoresizeSubviews:YES]; [oNewsgroupView addSubview:oNewsfolderScroll]; [oNewsgroupView addSubview:oNewsGroupNXBrowser]; if ((buffer = NXGetDefaultValue(OWNER, NNTPBROWSER_FRAME)) != 0 && sscanf(buffer, "(%f,%f):(%f,%f):(%f,%f):(%f,%f):(%f,%f):(%f,%f)", &newsbaseRect.origin.x,&newsbaseRect.origin.y, &newsbaseRect.size.width, &newsbaseRect.size.height, &folderDockSize.width, &folderDockSize.height, &browserSplitViewSize.width, &browserSplitViewSize.height, &leftSideSize.width, &leftSideSize.height, &rightSideSize.width, &rightSideSize.height ) == 12) { [oNewsReader placeWindow:&newsbaseRect]; [oNewsgroupView sizeTo:leftSideSize.width :leftSideSize.height]; [oArticleNXBrowser sizeTo:rightSideSize.width :rightSideSize.height]; [oNewsfolderDock sizeTo:folderDockSize.width :folderDockSize.height]; [oNewsfolderDockMatrix sizeTo:folderDockSize.width :folderDockSize.height]; [oBrowserSplitView sizeTo:browserSplitViewSize.width :browserSplitViewSize.height]; } /* setup side split view */ [oBrowserSplitView setRightView:oArticleNXBrowser]; [oBrowserSplitView setLeftView:oNewsgroupView]; /* setup for newsgroup folder dock and bowser */ [oSplitView addSubview:oNewsfolderDock]; [oSplitView addSubview:oBrowserSplitView]; [oBrowserSplitView initViews]; [oNewsfolderScroll setAutoresizeSubviews:YES]; // [oNewsfolderScrollMatrix notifyAncestorWhenFrameChanged:YES]; [oNewsfolderScrollMatrix getFrame:&frameRect]; frameRect.origin.x = frameRect.origin.y = 0.0; [oNewsfolderScrollMatrix setFrame:&frameRect]; [oNewsfolderScrollDocView getFrame:&frameRect]; frameRect.origin.x = frameRect.origin.y = 0.0; [oNewsfolderScrollDocView setFrame:&frameRect]; [oNewsfolderScrollDocView addSubview:oNewsfolderScrollMatrix]; [oNewsfolderScrollDocView setAutoresizeSubviews:NO]; [oNewsfolderScroll setDocView:oNewsfolderScrollDocView]; // set delegate for resizing behavior when sliding divider bar // [oSplitView setDelegate:oNewsfolderDockMatrix]; [oSplitView setDelegate:self]; // set root cell (next station icon) for newsgroup folder view // oNewsfolderScroll is scroll view, // which document view is IFolderScrollMatrix [oNewsfolderScrollMatrix setRootName:[iNntpIO rootName]]; [oNewsfolderDockMatrix setRootName:[iNntpIO rootName]]; [[oNewsReader contentView] displayFromOpaqueAncestor:NULL :0 :YES]; [oNewsfolderDockMatrix registerCells]; return self; } - _setUpInterfaceWindow { /* * The objects in this module are: * INewsBase initializes the module. * NewsGroupTree holds the newsgroups in a tree structure. * NewsGroupTreeControl initializes and maintains the NewsGroupTree. */ /* set up news group browser */ [oNewsGroupNXBrowser setIOmodule:iNntpIO]; if ([iNntpIO newsGroupMode]==Flat) { [oNewsGroupNXBrowser setMaxVisibleColumns:1]; } else { [oNewsGroupNXBrowser setMaxVisibleColumns:4]; } /* set up article browser */ [oArticleNXBrowser setIOmodule:iNntpIO]; if ([iNntpIO articleMode]==Flat) { [oArticleNXBrowser setMaxVisibleColumns:1]; } else { [oArticleNXBrowser setMaxVisibleColumns:2]; } /* load cell into NewsGroupBrowser */ [oNewsGroupNXBrowser setRootListnode:[iNntpIO subDirectoryOf:nil]]; [oNewsGroupNXBrowser loadColumnZero]; /* set up interaction of DataGroupBrowser,ItemRepBrowser,ItemBrowser */ [oNewsGroupNXBrowser setItemRepUIF:oArticleNXBrowser]; [oArticleNXBrowser setDataGroupUIF:oNewsGroupNXBrowser]; /* set control panel */ [oNewsReader setDelegate:self]; [self setArticleBrowserMode]; /* set up window for getting article number */ [iNntpIO setOGetArticleNumWindow:oGetArticleNumWindow]; [iNntpIO setOGetArticleNumField:oGetArticleNumField]; [iNntpIO setIPercentageView:oPercentageView]; [oArticleNumOKButton setTarget:iNntpIO]; [oArticleNumCancelButton setTarget:iNntpIO]; [oArticleNumOKButton setAction:@selector(okArticleNumWindow:)]; [oArticleNumCancelButton setAction:@selector(cancelArticleNumWindow:)]; DBG(10, fprintf(stderr," NewsBase is made\n")); return self; } - (char *)label { static char labelString[64]; sprintf (labelString, "NewsBase: %.53s", iNntpHost); return labelString; } - show:sender { unsigned int windowNum; NXRect oldRect; [oNewsReader display]; [oNewsReader makeKeyAndOrderFront:self]; // register window for accepting file icons NXConvertWinNumToGlobal([oNewsReader windowNum], &windowNum); [[NXApp appSpeaker] setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)]; [[NXApp appSpeaker] registerWindow:windowNum toPort:[[NXApp appListener] listenPort]]; // these statements should not be needed here. but // I could not register rectangle of cells during setting up views // in "_readWindowInfoFromDefaultDBandSetupViews" above. [oNewsfolderDockMatrix registerCells]; [oNewsfolderScrollMatrix registerCells]; [oSplitView getFrame:&oldRect]; [self splitView:oSplitView resizeSubviews:(const NXSize *)&(oldRect.size)]; return(self); } - terminateProc { [self _saveWindowInfoToDefaultDB]; return self; } - (BOOL)postArticle:(const char *)article length:(int)length { return([iNntpIO postArticle:article length:length]); } - (BOOL)sendArticle:(const char *)messageId { return([iNntpIO sendArticle:messageId]); } - newsGroupTreeControl { return iNntpIO; } - toggleNewsGroupBrowser:sender { if ([iNntpIO toggleNewsGroupMode:sender]==Flat) { [oNewsGroupNXBrowser setMaxVisibleColumns:1]; NXWriteDefault(OWNER, NEWSGROUPBROWSERMODE, "List"); } else { [oNewsGroupNXBrowser setMaxVisibleColumns:4]; NXWriteDefault(OWNER, NEWSGROUPBROWSERMODE, "Browser"); } /* reset newsgroup browser and redraw new browser */ [oNewsGroupNXBrowser setRootListnode:[iNntpIO subDirectoryOf:nil]]; [oNewsGroupNXBrowser loadColumnZero]; return self; } - toggleArticleBrowser:sender { [iNntpIO toggleArticleMode:sender]; [self setArticleBrowserMode]; return(self); } - setArticleBrowserMode { id node; id itemHeaderslist; switch ([iNntpIO articleMode]) { case Flat: [oArticleNXBrowser setMaxVisibleColumns:1]; [oArticleNXBrowser setTitle:LISTCOL0TITLE ofColumn:0]; NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "List"); break; case Tree: [oArticleNXBrowser setMaxVisibleColumns:2]; [oArticleNXBrowser setTitle:BROWSERCOL0TITLE ofColumn:0]; NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "ByReference"); break; case BySubject: [oArticleNXBrowser setMaxVisibleColumns:2]; [oArticleNXBrowser setTitle:SUBJECTCOL0TITLE ofColumn:0]; NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "BySubject"); break; case ByKeyword: [oArticleNXBrowser setTitle:KEYWORDCOL0TITLE ofColumn:0]; [oArticleNXBrowser setMaxVisibleColumns:2]; NXWriteDefault(OWNER, ARTICLEBROWSERMODE, "ByKeyword"); break; } /* reset article browser */ node = [self _nodeForSelectedCellInBrowser:oNewsGroupNXBrowser]; itemHeaderslist = [iNntpIO itemHeadersOf:node]; /* update article browser */ [oArticleNXBrowser setRootListnode:itemHeaderslist]; [oArticleNXBrowser loadColumnZero]; return(self); } - setReadFlagToAll:sender { id node; id itemHeaderslist; [iNntpIO setReadFlag:(ReadFlag)ALL]; node = [self _nodeForSelectedCellInBrowser:oNewsGroupNXBrowser]; itemHeaderslist = [iNntpIO itemHeadersOf:node]; /* update article browser */ [oArticleNXBrowser setRootListnode:itemHeaderslist]; [oArticleNXBrowser loadColumnZero]; /* set read flag to default */ [iNntpIO setReadFlag:(ReadFlag)UNMARKEDONLY]; return self; } - markAllArticleAsRead:sender { id lastColumnMatrix; switch(NXRunAlertPanel(LoStr("NewsBase"), LoStr("Cannot Undo! all article will be marked as read."), LoStr("OK"),LoStr("Cancel"),NULL)) { case NX_ALERTDEFAULT: lastColumnMatrix = [oNewsGroupNXBrowser matrixInColumn: [oNewsGroupNXBrowser lastColumn]]; [lastColumnMatrix sendAction:@selector(markAllArticleOfCell:) to:self forAllCells:NO]; break; case NX_ALERTALTERNATE: return(self); } /* reset article browser */ [oArticleNXBrowser setRootListnode:nil]; [oArticleNXBrowser loadColumnZero]; return self; } - markAllArticleOfCell:sender { /* this method will be called from oNewsGroupNXBrowser's cell */ /* "markAllArticleAsRead:" will triger it */ id newsGroup; id groupInfo; newsGroup = [[sender node] linkedData]; groupInfo = [newsGroup dataForKey:GROUPINFO]; [groupInfo markAllArticle]; return self; } - getNewArticles:sender { if ([iNntpIO reconnectServer:sender] == nil) { NXRunAlertPanel(LoStr("NewsBase"), LoStr("Can not recconect to nntp server."), LoStr("OK"),NULL,NULL); [NXApp terminate:self]; } [oArticleNXBrowser setRootListnode:nil]; [oArticleNXBrowser loadColumnZero]; return self; } - unSubscribeGroup:sender { id lastColumnMatrix; switch(NXRunAlertPanel(LoStr("NewsBase"), LoStr("Cannot Undo! Selected newsgroup in browser will be unsubscribed."), LoStr("OK"),LoStr("Cancel"),NULL)) { case NX_ALERTDEFAULT: lastColumnMatrix = [oNewsGroupNXBrowser matrixInColumn: [oNewsGroupNXBrowser lastColumn]]; [lastColumnMatrix sendAction:@selector(unSubscribeGroupOfCell:) to:self forAllCells:NO]; /* reset oNewsGroupNXBrowser browser */ [lastColumnMatrix display]; break; case NX_ALERTALTERNATE: break; } return (self); } - unSubscribeGroupOfCell:sender { /* this method will be called from oNewsGroupNXBrowser's cell */ /* "unSubscribeGroup:" will triger it */ id node; id groupInfo; node = [sender node]; groupInfo = [[node linkedData] dataForKey:GROUPINFO]; [groupInfo addInfoString:"no" key:SUBSCRIBE]; [node setActive:NO]; [sender setActive:NO]; return self; } - _nodeForSelectedCellInBrowser:kbrowser { id lastColumnMatrix; id selectedCell; lastColumnMatrix = [kbrowser matrixInColumn:[kbrowser lastColumn]]; selectedCell = [lastColumnMatrix selectedCell]; return [selectedCell node]; } - (int)openNewsBasePanel { const char *servername; int returnCode; servername = NXGetDefaultValue(OWNER, NNTPSERVER); DBG(10,fprintf(stderr,"default value nntpserver=%s",servername)); [oOpenNewsBasePanel makeKeyAndOrderFront:self]; [oNntpServerNameField setStringValue:(char *)servername]; returnCode = [NXApp runModalFor:oOpenNewsBasePanel]; [oOpenNewsBasePanel free]; return(returnCode); } - cancelConnect:sender { [NXApp stopModal:0]; return self; } - okConnect:sender { strncpy(iNntpHost, [oNntpServerNameField stringValue], (sizeof(iNntpHost)-1)); if ([[oGroupSelectionButton selectedCell] tag]==0) { iAllNewsFlag = NO; } else { iAllNewsFlag = YES; } [NXApp stopModal:1]; return self; } - windowDidBecomeKey:sender { [[NXApp delegate] browserDidBecomeKey:self]; return(self); } - windowDidResignKey:sender { [[NXApp delegate] browserDidResignKey:self]; return(self); } - windowWillClose:sender { [self _saveWindowInfoToDefaultDB]; [[NXApp delegate] browserDidResignKey:self]; [NXApp delayedFree:self]; return(self); } - _saveWindowInfoToDefaultDB { NXRect newsbaseRect; NXRect folderDockRect, browserViewRect, leftSideRect, rightSideRect; char buffer[256]; // +----------------------+ -+ // | folderDock | newsbaseRect // +----------------------+ | // | | | | // |leftSide| | | // | | | | // +----------------------+ -+ // save .newsrc file [iNntpIO saveNewsRcFile]; // save .dir.newsbase file [oNewsfolderDockMatrix saveDirFile]; // save NewsBase frameSize and location of divider [oNewsReader getFrame:&newsbaseRect]; [oNewsfolderDock getFrame:&folderDockRect]; [oBrowserSplitView getFrame:&browserViewRect]; [oNewsgroupView getFrame:&leftSideRect]; [oArticleNXBrowser getFrame:&rightSideRect]; sprintf(buffer, "(%.0f,%.0f):(%.0f,%.0f):" "(%.0f,%.0f):(%.0f,%.0f):(%.0f,%.0f):(%.0f,%.0f)", newsbaseRect.origin.x, newsbaseRect.origin.y, newsbaseRect.size.width, newsbaseRect.size.height, folderDockRect.size.width, folderDockRect.size.height, browserViewRect.size.width, browserViewRect.size.height, leftSideRect.size.width, leftSideRect.size.height, rightSideRect.size.width, rightSideRect.size.height); NXWriteDefault(OWNER, NNTPBROWSER_FRAME, buffer); return self; } - free { if (iNntpIO != nil) { [iNntpIO saveNewsRcFile]; [iNntpIO free]; } [oNewsReader free]; [oGetArticleNumWindow free]; [self perform:@selector(destroyZone:) with:nil afterDelay:1 cancelPrevious:NO]; return(nil); } - destroyZone:dummy { NXDestroyZone(newsbaseZone); [super free]; return(nil); } /* delegate method for NXSplitView */ #define SCRLLMATRIX_HEIGHT 107 // height for oNewsfolderScroll - splitView:sender resizeSubviews:(const NXSize *)oldSize { id upperView, lowerView; NXRect viewFrame, upperFrame; int ncols, nrows; int i, j; NXSize cellSize, intercell; int numRows, numCols; DBG(1,fprintf(stderr,"-- splitView:\n")); // upperView = *(NX_ADDRESS([sender subviews])); // lowerView = *(NX_ADDRESS([sender subviews]) + 1); upperView = oNewsfolderDock; lowerView = oBrowserSplitView; [[sender window] disableDisplay]; [sender adjustSubviews]; // adjust upper(self) view size [sender getFrame:&viewFrame]; [upperView getFrame:&upperFrame]; // upperView is ScrollView // and oNewsfolderDockMatrix is a docView of that ScrollView [oNewsfolderDockMatrix getCellSize:&cellSize]; [oNewsfolderDockMatrix getIntercell:&intercell]; [oNewsfolderDockMatrix getEnoughNumRows:&nrows numCols:&ncols forSize:&(upperFrame.size)]; upperFrame.size.height = cellSize.height * nrows + intercell.height * (nrows-1); [upperView setFrame:&upperFrame]; // compute lower view size viewFrame.origin.y = [sender dividerHeight] + upperFrame.size.height; // coord. is flipped in NXSplitView viewFrame.size.height -= viewFrame.origin.y; [lowerView setFrame:&viewFrame]; [[sender window] reenableDisplay]; // unregister cell's frame to viewRectList in AcceptWindow // so that the clipped cell can not be used as dropped well [oNewsfolderDockMatrix getNumRows:&numRows numCols:&numCols]; if (numCols > ncols) { // remove columns for (i = (numCols-1); i > (ncols-1); --i) { // unregister rect of cell which will be clipped by ScrollView, // which is a superview of this class for (j = (numRows-1); j >= 0; --j) { [oNewsfolderDockMatrix unregisterCellAt:j :i window:nil]; } } } if (numRows > nrows) { // remove rows for (i = (numRows-1); i > (nrows-1); --i) { // unregister rect of cell which will be clipped by ScrollView, // which is a superview of this class for (j = (numCols-1); j >= 0; --j) { [oNewsfolderDockMatrix unregisterCellAt:i :j window:nil]; } } } // reregister the cells in Scroll view [oNewsfolderScrollMatrix registerCells]; return self; } - splitView:sender getMinY:(NXCoord *)minY maxY:(NXCoord *)maxY ofSubviewAt:(int)offset { NXRect viewFrame; int nrows, ncols; id upperView, lowerView; NXSize cellSize, intercell; upperView = oNewsfolderDockMatrix; lowerView = oBrowserSplitView; [upperView getCellSize:&cellSize]; [upperView getIntercell:&intercell]; *minY = 0.0; [sender getFrame:&viewFrame]; viewFrame.size.height -= SCRLLMATRIX_HEIGHT; [upperView getEnoughNumRows:&nrows numCols:&ncols forSize:&(viewFrame.size)]; nrows -= 1; // avoid that the upperview size will be // overflow because of rounding nrows if (nrows >= 1) { *maxY = cellSize.height * nrows + intercell.height * (nrows -1); } else { *maxY = 0.0; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.