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;