home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 (1993) / nebula.bin / SourceCode / MiniExamples / FindIt / FindObject.m < prev    next >
Encoding:
Text File  |  1991-10-09  |  4.9 KB  |  223 lines

  1. /* 
  2.  * FindObject.m
  3.  *
  4.  * Purpose:
  5.  *        This object controls the searching for strings in a matrix or in a text object.
  6.  *
  7.  * You may freely copy, distribute, and reuse the code in this example.
  8.  * NeXT disclaims any warranty of any kind, expressed or  implied, as to its
  9.  * fitness for any particular use.
  10.  *
  11.  * Written by: Mary McNabb
  12.  * Created: Apr 91
  13.  *
  14.  */
  15. #import "FindObject.h"
  16.  
  17. #import <libc.h>
  18. #import <strings.h>
  19. #import <appkit/publicWraps.h>
  20. #import <streams/streams.h>
  21. #import <appkit/Form.h>
  22. #import <appkit/Button.h>
  23. #import <appkit/Matrix.h>
  24. #import <appkit/Text.h>
  25. #import <appkit/Window.h>
  26. #import <appkit/Application.h>
  27.  
  28. #import "cUtils.h"
  29.  
  30. @implementation FindObject
  31.  
  32. /* initialize FindObject */
  33. - init
  34. {
  35.     [super init];
  36.     [NXApp loadNibSection:"FindPanel.nib" owner:self];
  37.     return self;
  38. }
  39.  
  40. /*
  41.  *    This method sets the local variable searchMe.
  42.  *    searchMe must be either a text object or a
  43.  *    matrix of text fields.
  44.  */
  45. - setSearchMe:object
  46. {
  47.     searchMe = object;
  48.     return self;
  49. }
  50.  
  51. /*
  52.  *    Order the findPanel front and select the search string.
  53.  */
  54. - findPanel:sender
  55. {
  56.     [findPanel makeKeyAndOrderFront:NULL];
  57.     [findForm selectTextAt:0];
  58.     return self;
  59. }
  60.  
  61. /*
  62.  *    This method is called when the user types carriage
  63.  *    return in the textfield in the find panel.
  64.  */
  65. - findNextReturn:sender
  66. {
  67.     [findNextButton performClick:NULL];
  68.     [findPanel orderOut:NULL];
  69.     return self;
  70. }
  71.  
  72. /*
  73.  *    This method is called when the user pushes the next
  74.  *    button on the find panel. It decides if the searchMe
  75.  *    is of type matrix or text and calls subsequent methods
  76.  *    accordingly.
  77.  */
  78. - findNext:sender
  79. {
  80.     const char *findStr =  [findForm stringValueAt:0];
  81.     if (!strlen(findStr) || !searchMe) {
  82.         NXBeep();
  83.         return self;
  84.     }
  85.     ignoreCase = [ignoreCaseButton state];
  86.  
  87.     if ([searchMe isKindOf:[Matrix class]]) {
  88.         [self findInMatrix:FORWARD :findStr];
  89.     } else {
  90.         [self findInText:FORWARD];
  91.     }
  92.     return self;
  93. }
  94.  
  95. /*
  96.  * This method is called when the user pushes the previous
  97.  * button on the find panel.  It decides if the searchMe is of type
  98.  * matrix or text and calls subsequent methods accordingly.
  99.  */
  100. - findPrevious:sender
  101. {
  102.     const char *findStr =  [findForm stringValueAt:0];
  103.  
  104.     if (!strlen(findStr) || !searchMe) {
  105.         NXBeep();
  106.         return self;
  107.     }
  108.     if ([searchMe isKindOf:[Matrix class]]) {
  109.         [self findInMatrix:BACKWARD :findStr];
  110.     } else {
  111.         [self findInText:BACKWARD];
  112.     }
  113.     return self;
  114. }
  115.  
  116. /*
  117.  * Searches through a text object (also wraps around if necessary).
  118.  */
  119. - findInText:(int)direction
  120. {
  121.     char    *text, *textStart, *match;
  122.     NXSelPt    start, end;
  123.     int        count, newStart;
  124.     NXStream    *stream;
  125.     
  126.     text = (char *)[findForm stringValueAt:0];
  127.  
  128.     [searchMe getSel:&start :&end];
  129.     if (start.cp == end.cp) start.cp = end.cp = 0;
  130.  
  131. /* We need to set up a stream for the search */        
  132.     stream = [searchMe stream];
  133.     if (!stream) {
  134.         NXBeep();
  135.         return self;
  136.     }
  137.  
  138. /* find out how long the text is, and position ourselves either from the beginning or from
  139.  * the selection position */
  140.     NXSeek(stream, 0, NX_FROMEND);
  141.     count = NXTell(stream);
  142.     NXSeek(stream, 0, NX_FROMSTART);
  143.     textStart = (char *)malloc(count + 1);
  144.     NXRead(stream, textStart, count);
  145.     *(textStart + count) = '\0';
  146.     
  147.     if (direction == FORWARD)
  148.         match = textInString(text, textStart + end.cp, ignoreCase);
  149.     else
  150.         match = textInStringReverse(text, textStart + start.cp + strlen(text) - 1,
  151.                 textStart, ignoreCase);
  152.                 
  153. /* wraparound if necessary */
  154.     if (!match) {
  155.         if (direction == FORWARD)
  156.             match = textInString(text, textStart, ignoreCase);
  157.         else
  158.             match = textInStringReverse(text, textStart + strlen(textStart), textStart, ignoreCase);
  159.     }
  160.  
  161. /* did we find anything? */    
  162.     newStart = match - textStart;
  163.     free(textStart);
  164.     if (!match || (newStart == start.cp && (end.cp - start.cp) == strlen(text))) {
  165.         NXBeep();
  166.         return self;
  167.     }
  168.  
  169.     [[searchMe setSel:newStart :newStart + strlen(text)]
  170.                                 scrollSelToVisible];
  171.     
  172.     return self;
  173. }
  174.  
  175. - (BOOL)searchMatrixStrings:(int)start:(int)stop:(int)dir:(const char *)findStr
  176. {
  177.     int i;
  178.  
  179.     for (i = start; dir == FORWARD? i <= stop: i >= stop; i += dir)
  180.     {
  181.         id myCell = [searchMe cellAt:i :0];
  182.         char *myContents = (char *) [myCell stringValue];
  183.          if (textInString((char *)findStr, myContents, ignoreCase))
  184.         {    /* then we've got a match */
  185.             [searchMe selectCellAt: i :0];
  186.             return YES;
  187.         }
  188.     }
  189.     return NO;
  190. }
  191.  
  192. - findInMatrix:(int) direction :(const char*) findStr
  193. {
  194.     int stop, temp, start;
  195.     if (direction == FORWARD) {
  196.         [searchMe getNumRows:&stop numCols:&temp];
  197.         stop--;
  198.         start = [searchMe selectedRow] + 1;
  199.     } else {
  200.         stop = 0;
  201.         start = [searchMe selectedRow]  - 1;
  202.     }
  203.     if (![self searchMatrixStrings:start :stop :direction :findStr])
  204.     {    /* implements wrap-around search */
  205.         if (direction == FORWARD) {
  206.             start = 0;
  207.             stop = [searchMe selectedRow];
  208.         } else {
  209.             [searchMe getNumRows:&start numCols:&temp];
  210.             start -= 1;
  211.             stop = [searchMe selectedRow] + 1;
  212.         }
  213.         if (![self searchMatrixStrings:start :stop :direction :findStr])
  214.         {
  215.             NXBeep();
  216.             return self;
  217.         }
  218.     }
  219.     return self;
  220. }
  221.  
  222. @end
  223.