Plugins/Dual Window Interface/AIMessageViewController.m
changeset 2646 e6cf2d4672e5
parent 2118 9fbe80565319
child 2715 6da617b2fa7d
     1.1 --- a/Plugins/Dual Window Interface/AIMessageViewController.m	Wed May 06 17:07:28 2009 -0400
     1.2 +++ b/Plugins/Dual Window Interface/AIMessageViewController.m	Sun Oct 25 21:21:42 2009 -0400
     1.3 @@ -90,6 +90,8 @@
     1.4  - (void)setUserListVisible:(BOOL)inVisible;
     1.5  - (void)setupShelfView;
     1.6  - (void)updateUserCount;
     1.7 +
     1.8 +- (NSArray *)contactsMatchingBeginningString:(NSString *)partialWord;
     1.9  @end
    1.10  
    1.11  @implementation AIMessageViewController
    1.12 @@ -974,6 +976,12 @@
    1.13  }
    1.14  
    1.15  #pragma mark Autocompletion
    1.16 +- (BOOL)canTabCompleteForPartialWord:(NSString *)partialWord
    1.17 +{
    1.18 +	return ([self contactsMatchingBeginningString:partialWord].count > 0 ||
    1.19 +			[self.chat.displayName rangeOfString:partialWord options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound);
    1.20 +}
    1.21 +
    1.22  /*!
    1.23   * @brief Should the tab key cause an autocompletion if possible?
    1.24   *
    1.25 @@ -981,55 +989,90 @@
    1.26   */
    1.27  - (BOOL)textViewShouldTabComplete:(NSTextView *)inTextView
    1.28  {
    1.29 -	return self.chat.isGroupChat;
    1.30 +	if (self.chat.isGroupChat) {
    1.31 +		NSRange completionRange = inTextView.rangeForUserCompletion;
    1.32 +		NSString *partialWord = [inTextView.textStorage.string substringWithRange:completionRange];
    1.33 +		return [self canTabCompleteForPartialWord:partialWord]; 
    1.34 +	}
    1.35 +	
    1.36 +	return NO;
    1.37 +}
    1.38 +
    1.39 +- (NSRange)textView:(NSTextView *)inTextView rangeForCompletion:(NSRange)charRange
    1.40 +{
    1.41 +	if (self.chat.isGroupChat && charRange.location > 0) {
    1.42 +		NSString *partialWord = nil;
    1.43 +		NSString *allText = [inTextView.textStorage.string substringWithRange:NSMakeRange(0, NSMaxRange(charRange))];
    1.44 +		NSRange whitespacePosition = [allText rangeOfCharacterFromSet:[NSCharacterSet whitespaceCharacterSet] options:NSBackwardsSearch];
    1.45 +		
    1.46 +		if (whitespacePosition.location == NSNotFound) {
    1.47 +			// We went back to the beginning of the string and still didn't find a whitespace; use the whole thing.
    1.48 +			partialWord = allText;
    1.49 +			whitespacePosition = NSMakeRange(0, 0);
    1.50 +		} else {
    1.51 +			// We found a whitespace, use from it until our current position.
    1.52 +			partialWord = [allText substringWithRange:NSMakeRange(NSMaxRange(whitespacePosition), allText.length - NSMaxRange(whitespacePosition))];
    1.53 +		}
    1.54 +		
    1.55 +		// If this matches any contacts or the room name, use this new range for autocompletion.
    1.56 +		if ([self canTabCompleteForPartialWord:partialWord]) {
    1.57 +			charRange = NSMakeRange(NSMaxRange(whitespacePosition), allText.length - NSMaxRange(whitespacePosition));
    1.58 +		}
    1.59 +	}
    1.60 +	
    1.61 +	return charRange;
    1.62 +}
    1.63 +
    1.64 +- (NSArray *)contactsMatchingBeginningString:(NSString *)partialWord
    1.65 +{
    1.66 +	NSMutableArray *contacts = [NSMutableArray array];
    1.67 +	
    1.68 +	for (AIListContact *listContact in self.chat) {
    1.69 +		if ([listContact.UID rangeOfString:partialWord
    1.70 +								   options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound ||
    1.71 +			[listContact.formattedUID rangeOfString:partialWord
    1.72 +											options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound ||
    1.73 +			[listContact.displayName rangeOfString:partialWord
    1.74 +										   options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound) {
    1.75 +				[contacts addObject:listContact];
    1.76 +		}
    1.77 +	}
    1.78 +	
    1.79 +	return contacts;
    1.80  }
    1.81  
    1.82  - (NSArray *)textView:(NSTextView *)textView completions:(NSArray *)words forPartialWordRange:(NSRange)charRange indexOfSelectedItem:(NSInteger *)index
    1.83  {
    1.84 -	NSMutableArray	*completions;
    1.85 +	NSMutableArray	*completions = nil;
    1.86  	
    1.87  	if (self.chat.isGroupChat) {
    1.88 -		NSString		*partialWord = [[textView.textStorage attributedSubstringFromRange:charRange] string];
    1.89 -		
    1.90 +		NSString *suffix = nil;
    1.91 +		NSString *partialWord = [textView.textStorage.string substringWithRange:charRange];
    1.92  		BOOL autoCompleteUID = [self.chat.account chatShouldAutocompleteUID:self.chat];
    1.93  		
    1.94 -		NSString		*suffix;
    1.95 +		//At the start of a line, append ": "
    1.96  		if (charRange.location == 0) {
    1.97 -			//At the start of a line, append ": "
    1.98  			suffix = @": ";
    1.99 -		} else {
   1.100 -			suffix = nil;
   1.101  		}
   1.102  		
   1.103  		completions = [NSMutableArray array];
   1.104 -		for(AIListContact *listContact in self.chat) {
   1.105 -			if ([listContact.displayName rangeOfString:partialWord
   1.106 -												 options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound ||
   1.107 -				[listContact.formattedUID rangeOfString:partialWord
   1.108 -												options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound ||
   1.109 -				[listContact.UID rangeOfString:partialWord
   1.110 -										 options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound) {
   1.111 -
   1.112 -				NSString *displayName = [self.chat aliasForContact:listContact];
   1.113 -				
   1.114 -				if (!displayName) {
   1.115 -					displayName = autoCompleteUID ? listContact.formattedUID : listContact.displayName;
   1.116 -				}
   1.117 -
   1.118 -				[completions addObject:(suffix ? [displayName stringByAppendingString:suffix] : displayName)];
   1.119 -			}
   1.120 +		
   1.121 +		for (AIListContact *listContact in [self contactsMatchingBeginningString:partialWord]) {
   1.122 +			NSString *displayName = [self.chat aliasForContact:listContact];
   1.123 +			
   1.124 +			if (!displayName)
   1.125 +				displayName = autoCompleteUID ? listContact.formattedUID : listContact.displayName;
   1.126 +			
   1.127 +			[completions addObject:(suffix ? [displayName stringByAppendingString:suffix] : displayName)];
   1.128  		}
   1.129  		
   1.130 -		if ([self.chat.name rangeOfString:partialWord options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound) {
   1.131 -			[completions addObject:self.chat.name];
   1.132 +		if ([self.chat.displayName rangeOfString:partialWord options:(NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch | NSAnchoredSearch)].location != NSNotFound) {
   1.133 +			[completions addObject:self.chat.displayName];
   1.134  		}
   1.135  
   1.136  		if ([completions count]) {			
   1.137  			*index = 0;
   1.138  		}
   1.139 -
   1.140 -	} else {
   1.141 -		completions = nil;
   1.142  	}
   1.143  
   1.144  	return [completions count] ? completions : words;