This is FindObject.m in view mode; [Download] [Up]
/* * FindObject.m * * Purpose: * This object controls the searching for strings in a matrix or in a text object. * * You may freely copy, distribute, and reuse the code in this example. * NeXT disclaims any warranty of any kind, expressed or implied, as to its * fitness for any particular use. * * Written by: Mary McNabb * Created: Apr 91 * */ #import "FindObject.h" #import <libc.h> #import <strings.h> #import <appkit/publicWraps.h> #import <streams/streams.h> #import <appkit/Form.h> #import <appkit/Button.h> #import <appkit/Matrix.h> #import <appkit/Text.h> #import <appkit/Window.h> #import <appkit/Application.h> #import "cUtils.h" @implementation FindObject /* initialize FindObject */ - init { [super init]; [NXApp loadNibSection:"FindPanel.nib" owner:self]; return self; } /* * This method sets the local variable searchMe. * searchMe must be either a text object or a * matrix of text fields. */ - setSearchMe:object { searchMe = object; return self; } /* * Order the findPanel front and select the search string. */ - findPanel:sender { [findPanel makeKeyAndOrderFront:NULL]; [findForm selectTextAt:0]; return self; } /* * This method is called when the user types carriage * return in the textfield in the find panel. */ - findNextReturn:sender { [findNextButton performClick:NULL]; [findPanel orderOut:NULL]; return self; } /* * This method is called when the user pushes the next * button on the find panel. It decides if the searchMe * is of type matrix or text and calls subsequent methods * accordingly. */ - findNext:sender { const char *findStr = [findForm stringValueAt:0]; if (!strlen(findStr) || !searchMe) { NXBeep(); return self; } ignoreCase = [ignoreCaseButton state]; if ([searchMe isKindOf:[Matrix class]]) { [self findInMatrix:FORWARD :findStr]; } else { [self findInText:FORWARD]; } return self; } /* * This method is called when the user pushes the previous * button on the find panel. It decides if the searchMe is of type * matrix or text and calls subsequent methods accordingly. */ - findPrevious:sender { const char *findStr = [findForm stringValueAt:0]; if (!strlen(findStr) || !searchMe) { NXBeep(); return self; } if ([searchMe isKindOf:[Matrix class]]) { [self findInMatrix:BACKWARD :findStr]; } else { [self findInText:BACKWARD]; } return self; } /* * Searches through a text object (also wraps around if necessary). */ - findInText:(int)direction { char *text, *textStart, *match; NXSelPt start, end; int count, newStart; NXStream *stream; text = (char *)[findForm stringValueAt:0]; [searchMe getSel:&start :&end]; if (start.cp == end.cp) start.cp = end.cp = 0; /* We need to set up a stream for the search */ stream = [searchMe stream]; if (!stream) { NXBeep(); return self; } /* find out how long the text is, and position ourselves either from the beginning or from * the selection position */ NXSeek(stream, 0, NX_FROMEND); count = NXTell(stream); NXSeek(stream, 0, NX_FROMSTART); textStart = (char *)malloc(count + 1); NXRead(stream, textStart, count); *(textStart + count) = '\0'; if (direction == FORWARD) match = textInString(text, textStart + end.cp, ignoreCase); else match = textInStringReverse(text, textStart + start.cp + strlen(text) - 1, textStart, ignoreCase); /* wraparound if necessary */ if (!match) { if (direction == FORWARD) match = textInString(text, textStart, ignoreCase); else match = textInStringReverse(text, textStart + strlen(textStart), textStart, ignoreCase); } /* did we find anything? */ newStart = match - textStart; free(textStart); if (!match || (newStart == start.cp && (end.cp - start.cp) == strlen(text))) { NXBeep(); return self; } [[searchMe setSel:newStart :newStart + strlen(text)] scrollSelToVisible]; return self; } - (BOOL)searchMatrixStrings:(int)start:(int)stop:(int)dir:(const char *)findStr { int i; for (i = start; dir == FORWARD? i <= stop: i >= stop; i += dir) { id myCell = [searchMe cellAt:i :0]; char *myContents = (char *) [myCell stringValue]; if (textInString((char *)findStr, myContents, ignoreCase)) { /* then we've got a match */ [searchMe selectCellAt: i :0]; return YES; } } return NO; } - findInMatrix:(int) direction :(const char*) findStr { int stop, temp, start; if (direction == FORWARD) { [searchMe getNumRows:&stop numCols:&temp]; stop--; start = [searchMe selectedRow] + 1; } else { stop = 0; start = [searchMe selectedRow] - 1; } if (![self searchMatrixStrings:start :stop :direction :findStr]) { /* implements wrap-around search */ if (direction == FORWARD) { start = 0; stop = [searchMe selectedRow]; } else { [searchMe getNumRows:&start numCols:&temp]; start -= 1; stop = [searchMe selectedRow] + 1; } if (![self searchMatrixStrings:start :stop :direction :findStr]) { NXBeep(); return self; } } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.