ftp.nice.ch/pub/next/connectivity/news/NewsBase.3.02.s.tar.gz#/NewsBase302.source/MMEdit/IAppDelegate.m

This is IAppDelegate.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.
$*/
/* IAppDelegate.m connects the user interface and WorkSpace Manager
   to/from the editor/viewer. */

#import "IAppDelegate.h"
#import "IMediaTable.h"
#import <appkit/Application.h>
#import <appkit/Window.h>
#import <appkit/Panel.h>
#import <appkit/PopUpList.h>
#import <mach_init.h>
#import <objc/List.h>
#import <appkit/MenuCell.h>
#import <appkit/publicWraps.h>
#import <sys/dir.h>
#import <defaults.h>
#import <mach.h>
#import <libc.h>
#import <ctype.h>
#import "ILocalFileD.h"
#import "INewsD.h"
#import "IMMEditor.h"
#import "IBinaryD.h"
#import "ITextD.h"
#import "IOrderedListD.h"
#import "IReceiveListener.h"
#import "IReceiveSpeaker.h"
#import "data_types.h"
#import "errdebug.h"
#import "Localization.h"
#import "IConvertMIME.h"
#import "IArticleD.h"
#import "IHelp.h"
#import "InfoPanel.h"

#define LoStr(key)      doLocalString(NULL,key,NULL)

struct windowDef {
    @defs(Window)
};

extern char *ioBaseClassNameTable[];

static BOOL launchedFromDoubleClickOnFile = NO;

// ## REWRITE! ## Really shouldn't use an extern for this better to send message
HashTable *listOfTempFiles = nil;

// these tags must match the tags of the menu cell (really not a good way!)
// but IB doesn't gives us better!

#define MENU_TAG_SAVE 701
#define MENU_TAG_POST 703
#define MENU_TAG_RECURSIVE_SAVE 702
#define MENU_TAG_RECURSIVE_POST 704
#define MENU_TAG_SAVE_AS_MIME 705

#define FIND_NEXT_TAG 110
#define FIND_PREVIOUS_TAG 111
#define FIND_ENTER_SELECTION 113

@implementation IAppDelegate

- init
{
    [super init];
    iHelpPanel = nil;
    iInfoPanel = nil;
    listOfTempFiles = [[HashTable alloc] initKeyDesc:"*"];
    return(self);
}

-(int)receiveArticle:(char *)data length:(int)length
{
    const char *articleBuffer;

    articleBuffer = NXCopyInputData(0);
    DBG(10,fprintf(stderr, "***** start of article *****\n"));
    DBG(10,fputs(articleBuffer, stderr));
    DBG(10,fprintf(stderr, "*****  end of article  *****\n"));
    [INewsD openArticle:articleBuffer length:length];
    return(0);
}

- sendArticle:sender
{
    IMMEditor *sendEditor;
    IArticleD *article;

    sendEditor = [[NXApp keyWindow] delegate];
    if ([sendEditor class] == [IMMEditor class]) {
        if ((article = [sendEditor sendArticle]) != nil) {
	    if ([[article dataForKey:HEADER_INFO] 
	    				infoForKey:GROUPNAME] == NULL) {
		NXRunAlertPanel(LoStr("NewsBase"),
		    LoStr("Newsgroups field is missing, Please enter."),
		    					NULL,NULL,NULL);
		return (self);
	    }
	    // post article
            [INewsD save:article];
        }
    } else {
        NXRunAlertPanel(LoStr("NewsBase"),
            LoStr("key window is not an Editor window"),NULL,NULL,NULL);
    }
    return(self);
}

- openArticle:sender
{
    [ILocalFileD open];
    return(self);
}

- saveArticle:sender
{
    IMMEditor *theEditor;
    IArticleD *article;

    theEditor = [[NXApp keyWindow] delegate];
    if ([theEditor class] == [IMMEditor class]) {
        if ((article = [theEditor sendArticle]) != nil) {
	    if ([[article dataForKey:HEADER_INFO] 
	    				infoForKey:GROUPNAME] == NULL) {
		NXRunAlertPanel(LoStr("NewsBase"),
		    LoStr("Newsgroups field is missing, Please enter."),
		    					NULL,NULL,NULL);
		return (self);
	    }
            [ILocalFileD save:article];
        }
    } else {
        NXRunAlertPanel(LoStr("NewsBase"),LoStr("key window is not an Editor"
           " window"), NULL, NULL, NULL);
    }
    return(self);
}

- postArticle:(const char *)articleBuffer length:(int)length
{
    port_t      port;
    int         returnCode;

    port = NXPortFromName("NewsBase", NULL);
    [[NXApp appSpeaker] setSendPort:port];
    if ((returnCode = [[NXApp appSpeaker] receiveArticle:articleBuffer
        length:length]) != 0) {
        NXRunAlertPanel([self name],LoStr("cannot contact NewsBase"),
            LoStr("OK"),NULL,NULL);
    }
    return(self);
}

- sendArticleFrom:sender toIOClass:(Class)ioClass
{
    IMMEditor *sendEditor;
    IOrderedListD *article;

    sendEditor = [[NXApp keyWindow] delegate];
    if ([sendEditor class] != [IMMEditor class]) {
        NXRunAlertPanel(LoStr("NewsBase"),LoStr("key window is not an Editor window"),NULL,NULL,NULL);
        return(self);
    }
    if ((article = [sendEditor sendArticle]) != nil) {
    }
    return(self);
}

// recursiveSendArticle is the common method for saves, posts, recursive
// saves and recursive posts; menu tags will differentiate the actual
// requests

- recursiveSendArticle:sender
{
    IMMEditor *sendEditor;
    IArticleD *article;
    int i;
    id externalObject;
    const char *multipleViewerFlag;

    sendEditor = [[NXApp keyWindow] delegate];
    if ([sendEditor class] != [IMMEditor class]) {
        NXRunAlertPanel(LoStr("NewsBase"),
            LoStr("key window is not an Editor window"),NULL,NULL,NULL);
        return(self);
    }
    if ((article = [sendEditor sendArticle]) != nil) {
	if ([[article dataForKey:HEADER_INFO] 
				    infoForKey:GROUPNAME] == NULL) {
	    NXRunAlertPanel(LoStr("NewsBase"),
		LoStr("Newsgroups field is missing, Please enter."),
						    NULL,NULL,NULL);
	    return (self);
	}

        switch ([[sender selectedCell] tag]) {
        case MENU_TAG_SAVE:
        case MENU_TAG_POST:
            // check if there exists hyper links
            if ([[article externalsList] count] > 0) {
                if (NXRunAlertPanel(LoStr(MMEDITOR),
                     LoStr("Article has externally linked articles "
                     "which will not be recursively saved."), LoStr("OK"),
                     LoStr("Cancel"), NULL) == NX_ALERTDEFAULT) {
                        break;
                 } else {
                     return(self);
                 }
            }
            break;
        default:
            break;
        }

        switch ([[sender selectedCell] tag]) {
        case MENU_TAG_SAVE:
            [ILocalFileD save:article];
            break;
        case MENU_TAG_POST:
            [INewsD save:article];
            break;
        case MENU_TAG_RECURSIVE_SAVE:
            // recursive save requires multiple viewer mode so temporarily
            // set multiple viewer mode
            multipleViewerFlag = NXGetDefaultValue(OWNER, MULTIPLEVIEWERFLAG);
            NXSetDefault(OWNER, MULTIPLEVIEWERFLAG, "Yes");
            [article recursiveSaveToDomain:[ILocalFileD domain]];
            NXSetDefault(OWNER, MULTIPLEVIEWERFLAG, multipleViewerFlag);
            break;
        case MENU_TAG_RECURSIVE_POST:
            // recursive save requires multiple viewer mode so temporarily
            // set multiple viewer mode
            multipleViewerFlag = NXGetDefaultValue(OWNER, MULTIPLEVIEWERFLAG);
            NXSetDefault(OWNER, MULTIPLEVIEWERFLAG, "Yes");
            [article recursiveSaveToDomain:[INewsD domain]];
            NXSetDefault(OWNER, MULTIPLEVIEWERFLAG, multipleViewerFlag);
            break;
        case MENU_TAG_SAVE_AS_MIME:
            [ILocalFileD saveAsMIME:article];
            break;
        }
    }
    return(self);
}

- printArticle:sender
{
    IMMEditor *printEditor;

    printEditor = [[NXApp keyWindow] delegate];
    if ([printEditor class] == [IMMEditor class]) {
	[printEditor printArticle];
     } else {
        NXRunAlertPanel(LoStr("NewsBase"),LoStr("key window is not an Editor window"),NULL,NULL,NULL);
    }
    return(self);
}

- redisplayArticle:sender
{
    IMMEditor *redisplayEditor;

    redisplayEditor = [[NXApp keyWindow] delegate];
    if ([redisplayEditor class] == [IMMEditor class]) {
        [redisplayEditor redisplayArticle];
     } else {
        NXRunAlertPanel(LoStr("NewsBase"),LoStr("key window is not an Editor window"),NULL,NULL,NULL);
    }
    return(self);
}

- getReferenceListOfArticle:sender
{
    IMMEditor *currentEditor;
    MenuCell *menucell;
    const char *referenceList, *sptr;
    char messageId[512], *tptr;

    currentEditor = [[NXApp keyWindow] delegate];
    if (currentEditor == nil) {
        currentEditor = sender;
    }
    if ([currentEditor class] == [IMMEditor class]) {
        if ((referenceList = [currentEditor getReferenceList]) != NULL) {
            sptr = referenceList;
            while (*sptr != '\0') {
                for (; *sptr != '\0' && *sptr != '<'; ++sptr);
                if (*sptr != '<') {
                    break;
                }
getNextMessageId:
                messageId[0] = '<';
                for (++sptr, tptr = messageId + 1; *sptr != '\0' && *sptr != '>'
                    && *sptr != '<'; ++sptr, ++tptr) {
                    *tptr = *sptr;
                }
                if (*sptr == '<') {
                    // error message id did not end and new begins       
                    goto getNextMessageId;
                }
                if (*sptr != '>') {
                    break;
                }
                *tptr++ = *sptr++;
                *tptr = '\0';
                menucell = [[oEditorGetReMenuCell target] addItem:messageId
                    action:@selector(getArticleWithMessageID:)
                    keyEquivalent:'\0'];
                [menucell setTarget:self];
            }
        } 
//  } else {
//      NXRunAlertPanel(LoStr("NewsBase"),LoStr("key window is not an Editor window"),NULL,NULL,NULL);
    }
    return(self);
}

- getArticleWithMessageID:sender
{
    [INewsD loadFromName:[[sender selectedCell] title] inZone:NULL];
    return(self);
}

- closeAllEditorWindows:sender
{
    List *windowList;
    Window *window;
    int i;

    windowList = [NXApp windowList];
    for (i = 0; (window = [windowList objectAt:i]) != nil; ++i) {
        if ([[window delegate] class] == [IMMEditor class]) {
            if ([[window delegate] windowWillClose:self] != nil) {
                [window close];
            }
        }
    }
    return(self);
}

- openEditor:sender
{
    IArticleD *article;
    id		openPanel;
    const char	*types[2] = {"mime", NULL};
    NXStream	*stream;
    id		articleItem;
    id conv;

    switch ([[sender selectedCell] tag]) {
    case 0:
        // new editor window
        LoadLocalNib("MMRTFEditor.nib",self,NO,NULL);
/*
        [NXApp loadNibSection:"MMRTFEditor.nib" owner:self withNames:NO
            fromZone:NXCreateZone(vm_page_size, vm_page_size, YES)];
*/
        [editor editNewArticle];
        break;
    case 1:
        // post response
        editor = [[NXApp keyWindow] delegate];
        if ([editor class] == [IMMEditor class]) {
            if ((article = [editor sendArticle]) != nil) {
        LoadLocalNib("MMRTFEditor.nib",self,NO,NULL);
/*
                [NXApp loadNibSection:"MMRTFEditor.nib" owner:self withNames:NO
                    fromZone:NXCreateZone(vm_page_size, vm_page_size, YES)];
*/
                [editor postResponseToArticle:article];
            }
        } else {
            NXRunAlertPanel(LoStr("NewsBase"),LoStr("key window is not an Editor window"),NULL,NULL,NULL);
        }
        break;
/*
    case 2:
	openPanel = [OpenPanel new];
	[openPanel allowMultipleFiles:NO];
	if ([openPanel runModalForTypes:types]) {
	    stream = NXMapFile([openPanel filename], NX_READONLY);
	    LoadLocalNib("MMRTFEditor.nib",self,NO,[self zone]);
            conv = [[IConvertMIME alloc] init];
            articleItem = [conv convertToItem:stream];
	    [editor displayArticle:articleItem];
	    NXCloseMemory(stream, NX_FREEBUFFER);
	}
*/
    }
    return(self);
}

- openHelpPanel:sender
{
    if (iHelpPanel == nil) {
	iHelpPanel = [[IHelp allocFromZone:[self zone]] init];
    }
    [iHelpPanel openHelpPanel:sender];
    return self;
}

- openInfoPanel:sender
{
    if (iInfoPanel == nil) {
	iInfoPanel = [[InfoPanel allocFromZone:[self zone]] init];
    }
    [iInfoPanel openInfoPanel:sender];
    return self;
}

- appWillInit:sender
{
    [NXApp setAppListener:[[IReceiveListener alloc] init]];
    [NXApp setAppSpeaker:[[IReceiveSpeaker alloc] init]];
    return(self);
}

- appDidInit:sender
{
    // initialize IMMEditor class to prevent lockup with workspace manager
    [IMMEditor class];
    return(self);
}

- appWillTerminate:sender
{
    int n;
    Window *window;
    List *windowList;
    Class isA;
    NXHashState state;
    const char *filename;
    id value;
    char command[512];

    windowList = [NXApp windowList];
    for (n = 0; window = [windowList objectAt:n]; ++n) {
        if (NXZoneFromPtr(window) == 0) {
            DBG(1, fprintf(stderr, "NXZoneFromPtr(window = %#x) = %#x\n",
                window, NXZoneFromPtr(window)););
            [windowList removeObject:window];
            --n;
            continue;
        }
        if ((isA = ((struct windowDef *)window)->isa) != (Class)[Window class]
            && isA != (Class)[Panel class] && isA != (Class)[Menu class] &&
            isA != (Class)[PopUpList class]) {
            DBG(1, fprintf(stderr, "(window = %#x)->isa = %#x\n",
                window, ((struct windowDef *)window)->isa););
            [windowList removeObject:window];
            --n;
        }
    }
    // remove all temporary files
    state = [listOfTempFiles initState];
    while ([listOfTempFiles nextState:&state key:(const void **)&filename
        value:(void **)&value] == YES) {
        sprintf(command, "rm -r %.505s", (const char *)filename);
        system(command);
    }

    return(self);
}

- (BOOL)appAcceptsAnotherFile:sender
{
    DBG(1, ;);
    return(YES);
}

- (BOOL)app:sender openFile:(const char *)filename type:(const char *)type
{
    DBG(1, ;);
    launchedFromDoubleClickOnFile = YES;
    // initialize IMMEditor class to prevent lockup with workspace manager
    [IMMEditor class];
    return([ILocalFileD openFromName:filename]);
}

- editorDidBecomeKey:sender
{
    Menu *oEditorGetReSubMenu;
    Matrix *oEditorGetReSubMenuItemList;
    int nrows, ncols, i;

    [oEditorReMenuCell setEnabled:YES];
    [oSaveMenuCell setEnabled:YES];
    [oRecursiveSaveMenuCell setEnabled:YES];
    [oSaveAsMenuCell setEnabled:YES];
    [oPostMenuCell setEnabled:YES];
    [oRecursivePostMenuCell setEnabled:YES];
    [oPrintMenuCell setEnabled:YES];
    [oFindMenuCell setEnabled:YES];
    [oEditMenuCell setEnabled:YES];
    [oCloseMenuCell setEnabled:YES];
    [oRedisplayMenuCell setEnabled:YES];
    oEditorGetReSubMenu = [oEditorGetReMenuCell target];
    oEditorGetReSubMenuItemList = [oEditorGetReSubMenu itemList];
    [oEditorGetReSubMenuItemList getNumRows:&nrows numCols:&ncols];
    for (i = 0; i < nrows; ++i) {
        [oEditorGetReSubMenuItemList removeRowAt:i andFree:YES];
    }
    [oEditorReMenuCell setEnabled:YES];
    [self getReferenceListOfArticle:sender];
    oEditorGetReSubMenu = [oEditorGetReMenuCell target];
    [[oEditorGetReSubMenu itemList] sizeToCells];
    [oEditorGetReSubMenu sizeToFit];
    [oEditorGetReMenuCell setEnabled:YES];
    return(self);
}

- editorDidResignKey:sender
{
    Menu *oEditorGetReSubMenu;
    Matrix *oEditorGetReSubMenuItemList;
    int nrows, ncols, i;

    [oEditorReMenuCell setEnabled:NO];
    [oSaveMenuCell setEnabled:NO];
    [oRecursiveSaveMenuCell setEnabled:NO];
    [oSaveAsMenuCell setEnabled:NO];
    [oPostMenuCell setEnabled:NO];
    [oRecursivePostMenuCell setEnabled:NO];
    [oPrintMenuCell setEnabled:NO];
    [oFindMenuCell setEnabled:NO];
    [oEditMenuCell setEnabled:YES];
    [oCloseMenuCell setEnabled:NO];
    [oRedisplayMenuCell setEnabled:NO];
    [oEditorGetReMenuCell setEnabled:NO];
    oEditorGetReSubMenu = [oEditorGetReMenuCell target];
    oEditorGetReSubMenuItemList = [oEditorGetReSubMenu itemList];
    [oEditorGetReSubMenuItemList getNumRows:&nrows numCols:&ncols];
    for (i = 0; i < nrows; ++i) {
        [oEditorGetReSubMenuItemList removeRowAt:i andFree:YES];
    }
    [oEditorGetReSubMenuItemList sizeToCells];
    [oEditorGetReSubMenu sizeToFit];
    return(self);
}

static Window *iconEnteredWindow;

- (int)iconEntered:(int)windowNum at:(double)x :(double)y
    iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY
    iconWidth:(double)iconWidth iconHeight:(double)iconHeight
    pathList:(const char *)pathList
{
    unsigned int iconEnteredWindowNum;

    // ## REWRITE! ##  would be nice if this uniformly redirected the
    // message to the windows delegate

    NXConvertGlobalToWinNum(windowNum, &iconEnteredWindowNum);
    iconEnteredWindow = [NXApp findWindow:iconEnteredWindowNum];
    [iconEnteredWindow makeKeyAndOrderFront:self];
    if ([[iconEnteredWindow delegate] class] == [IMMEditor class]) {
        return([[[iconEnteredWindow delegate] text] iconEntered:windowNum
            at:x :y iconWindow:iconWindowNum iconX:iconX iconY:iconY
            iconWidth:iconWidth iconHeight:iconHeight pathList:pathList]);
    }
    return(0);
}

- (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag
{
    if ([[iconEnteredWindow delegate] class] == [IMMEditor class]) {
        return([[[iconEnteredWindow delegate] text]
            iconReleasedAt:x :y ok:flag]);
    }
    return(0);
}

- (int)iconExitedAt:(double)x :(double)y
{
    if ([[iconEnteredWindow delegate] class] == [IMMEditor class]) {
        return([[[iconEnteredWindow delegate] text] iconExitedAt:x :y]);
    }
    return(0);
}

- setOEditorReMenuCell:editorReMenuCell
{
    oEditorReMenuCell = editorReMenuCell;
    [oEditorReMenuCell setEnabled:NO];
    return(self);
}

- setOEditorGetReMenuCell:editorGetReMenuCell
{
    oEditorGetReMenuCell = editorGetReMenuCell;
    [oEditorGetReMenuCell setEnabled:NO];
    [[oEditorGetReMenuCell target] setTitle:"Message ID's"];
    [[oEditorGetReMenuCell target] setDelegate:self];
    return(self);
}

- (int)requestForPost:(char *) newsgroups sourceWindow:(int)wnum
{
    IMMEditor *sendEditor;
    IArticleD *article;
    char	*groupName;
    unsigned int	lwnum;
    id		sourceWin;

    DBG(1,fprintf(stderr," ============ requestForPost  %s\t %d",
    		newsgroups, wnum));

    [NXApp activateSelf:YES];
    NXConvertGlobalToWinNum(wnum, &lwnum);
    if ((sourceWin=[NXApp findWindow:lwnum]) == nil) {
        NXRunAlertPanel(LoStr("NewsBase"),
            LoStr("err occured when posting, try again"),NULL,NULL,NULL);
        return(-1);
    }

    [sourceWin makeKeyAndOrderFront:self];
    sendEditor = [sourceWin delegate];
    if ([sendEditor class] != [IMMEditor class]) {
        NXRunAlertPanel(LoStr("NewsBase"),
            LoStr("key window is not an Editor window"),NULL,NULL,NULL);
        return(-1);
    }

    if ((article = [sendEditor sendArticle]) != nil) {

	// check if there exists hyper links
	if ([[article externalsList] count] > 0) {
	    if (NXRunAlertPanel(LoStr(MMEDITOR),
		    LoStr("Article has externally linked articles "
		    "which will not be recursively saved."), LoStr("OK"),
		    LoStr("Cancel"), NULL) != NX_ALERTDEFAULT) {
		return (-1);
	    }
	}

	if ((groupName=[[article dataForKey:HEADER_INFO]
					 infoForKey:GROUPNAME]) != NULL) {
	    // article header has "Newsgroups:"
	    if (strncmp(newsgroups,"",strlen(newsgroups))==0) {
		// Newstoups: is in editor header
		[INewsD save:article];
		return (0);
	    } else if (strncmp(groupName,newsgroups,strlen(groupName))==0) {
		// group name is same
		[INewsD save:article];
		return (0);
	    } else {
		// groupname is different 
		NXRunAlertPanel(LoStr("NewsBase"),
		    LoStr("Newsgroups: is not matched"),NULL,NULL,NULL);
		return(-1);
	    }
	} else {
	    // header does not have "Newsgroups:"
	    if (strncmp(newsgroups,"",strlen(newsgroups))==0) {
		// posted to nextStation icon, so should have "Newsgroups:"
		NXRunAlertPanel(LoStr("NewsBase"),
		    LoStr("Newsgroups field is missing, Please enter."),
		    					NULL,NULL,NULL);
		return (-1);
	    }
	    [[article dataForKey:HEADER_INFO] 
		    addInfoString:(const char *)newsgroups key:GROUPNAME];
	    [INewsD save:article];
	    return (0);
	}
    }

    return (0);
}

// save previous context which is usually NewsBase

- setPreviousContext:(int)context
{
    if (context != myContext) {
        previousContext = context;
    }
    return(self);
}

// probably NewsBase

- (int)previousContext
{
    return(previousContext);
}

- setMyContext:(int)context
{
    myContext = context;
    return(self);
}

- (int)myContext
{
    return(myContext);
}

// find distributes find menu selections to the appropriate editor

- find:sender
{
    IMMEditor *findEditor;

    findEditor = [[NXApp mainWindow] delegate];
    if ([findEditor class] != [IMMEditor class]) {
        NXRunAlertPanel(LoStr("NewsBase"),
            LoStr("key window is not an Editor window"),NULL,NULL,NULL);
        return(self);
    }

    switch ([[sender selectedCell] tag]) {
    case FIND_NEXT_TAG:
        [[findEditor view] find:[oFindText stringValue] forward:YES
            ignoreCase:[oFindCase state]];
        break;
    case FIND_PREVIOUS_TAG:
        [[findEditor view] find:[oFindText stringValue] forward:NO
            ignoreCase:[oFindCase state]];
        break;
    case FIND_ENTER_SELECTION:
        [oFindText setStringValue:[[findEditor view] selection]];
        break;
    }
    return(self);
}

@end
	


These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.