5 // Created by Jan Van Tol on Sat Dec 14 2002.
6 // Copyright (c) 2002 Spiny Software. All rights reserved.
10 #import "InstantMessage.h"
11 #import "FileAttributes.h"
12 #import "AddressBookUtils.h"
16 - (id)initWithBuddy:(Buddy *)buddy path:(NSString *)path
20 myBuddy = [buddy retain];
21 creationDate = [[FileAttributes getCreationDateForPath:path] retain];
22 myPath = [path retain];
27 - (void)setCreationDate:(NSDate *)date
30 [creationDate retain];
34 - (NSDate *)creationDate
52 [[NSWorkspace sharedWorkspace] openFile:[myPath stringByExpandingTildeInPath] withApplication:@"iChat"];
55 //Returns a description of the Chat - a nicely formatted date string. We strip the leading zero on the hour so it'll look cleaner.
56 - (NSString *)description
58 NSCalendarDate *createdDate = [creationDate dateWithCalendarFormat:@"%c" timeZone:nil];
59 NSString *hourWithoutLeadingZero;
60 if ([[[createdDate descriptionWithCalendarFormat:@"%I"] substringToIndex:1] isEqualToString:@"0"])
62 hourWithoutLeadingZero = [[createdDate descriptionWithCalendarFormat:@"%I"] substringFromIndex:1];
66 hourWithoutLeadingZero = [createdDate descriptionWithCalendarFormat:@"%I"];
69 NSString *dateDescription = [createdDate descriptionWithCalendarFormat:@"%a %b %e %Y, "];
70 dateDescription = [dateDescription stringByAppendingString: hourWithoutLeadingZero];
71 dateDescription = [dateDescription stringByAppendingString: [createdDate descriptionWithCalendarFormat:@":%M %p"]];
73 return dateDescription;
76 //Comparison method for sorting by date
77 - (NSComparisonResult)compareByDate:(Chat *)otherChat
79 return (NSComparisonResult) - [creationDate compare:[otherChat creationDate]];
82 //Comparison method for sorting by buddy name
83 - (NSComparisonResult)compareByBuddy:(Chat *)otherChat
85 return [[myBuddy description] compare:[[otherChat buddy] description]];
90 if (chatContents == nil)
92 NSData *chatLog = [[NSData alloc] initWithContentsOfMappedFile:myPath];
93 if ([myPath hasSuffix:@".ichat"]) // check for tiger-style chat transcript
96 chatContents = [[NSKeyedUnarchiver unarchiveObjectWithData:chatLog] retain];
98 NSLog(@"Caught exception from NSKeyedUnarchiver - %@", [localException reason]);
106 chatContents = [[NSUnarchiver unarchiveObjectWithData:chatLog] retain];
108 NSLog(@"Caught exception from NSUnarchiver - %@", [localException reason]);
114 if (![chatContents isKindOfClass:[NSArray class]])
116 [chatContents release];
120 if (chatContents != nil)
122 for (unsigned int i=0; i < [chatContents count]; i++)
124 id obj = [chatContents objectAtIndex:i];
125 if ([obj isKindOfClass:[NSArray class]])
127 instantMessages = [obj retain];
136 - (BOOL)logContainsString:(NSString *)string
141 if (instantMessages != nil)
143 //Divide into an array of terms, so we don't search for phrases only. TO DO: More advanced searching, allowing quotes around terms to search for a phrase, and more.
144 NSArray *searchTerms = [string componentsSeparatedByString:@" "];
148 int searchTermsCount = [searchTerms count];
149 for (int i=0; i < searchTermsCount; i++)
151 NSString *searchTerm = [searchTerms objectAtIndex:i];
153 for (unsigned int j=0; j < [instantMessages count]; j++)
155 InstantMessage *im = [instantMessages objectAtIndex:j];
159 NSString *searchString = [[im text] string];
160 //We use a case-insensitive search, but there could be an option to control this.
161 if ([searchString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
169 if (foundCount >= searchTermsCount)
179 - (NSAttributedString *) getFormattedContentsWithSearchTermsHilighted:(NSString *) searchTermsStr firstFoundIndex:(int *) foundIndex
181 BOOL firstFound = false;
183 NSAttributedString *ret = [self getFormattedContents];
184 if (searchTermsStr && [searchTermsStr length] > 0)
186 NSArray *searchTerms = [searchTermsStr componentsSeparatedByString:@" "];
188 NSMutableAttributedString *retWithHilite = [[NSMutableAttributedString alloc] initWithAttributedString:ret];
189 NSString *retAsString = [retWithHilite string];
190 NSDictionary *colorAttrib = [NSDictionary dictionaryWithObject:[NSColor yellowColor] forKey:NSBackgroundColorAttributeName];
192 for (unsigned int i=0; i < [searchTerms count]; i++)
194 unsigned int strLength = [retAsString length];
195 NSString *searchTerm = [searchTerms objectAtIndex:i];
197 NSRange searchRange = NSMakeRange(0, strLength);
199 while (true && (searchRange.location + searchRange.length) <= strLength)
201 NSRange foundRange = [retAsString rangeOfString:searchTerm options:NSCaseInsensitiveSearch range:searchRange];
202 if (foundRange.location == NSNotFound)
206 searchRange.location = foundRange.location + 1;
207 searchRange.length = strLength - searchRange.location;
209 [retWithHilite addAttributes:colorAttrib range:foundRange];
213 *foundIndex = searchRange.location;
220 return [retWithHilite autorelease];
228 - (NSAttributedString *) getFormattedContents
231 NSMutableAttributedString *buf = [[NSMutableAttributedString alloc] initWithString:@""];
232 NSDictionary *gapAttrib = [NSDictionary dictionaryWithObject:[NSFont userFontOfSize:3.0] forKey:NSFontAttributeName];
233 NSAttributedString *gap = [[NSAttributedString alloc] initWithString:@"\n" attributes:gapAttrib];
235 [buf appendAttributedString:gap];
237 for (unsigned int i=0; i < [instantMessages count]; i++)
239 InstantMessage *im = [instantMessages objectAtIndex:i];
240 Presentity *sender = [im sender];
241 NSAttributedString *text = [im text];
243 NSDictionary *attribsOfText = nil;
245 if (text && [text length] > 0)
246 attribsOfText = [text attributesAtIndex:0 effectiveRange:nil];
250 NSString *realName = [AddressBookUtils lookupRealNameForIMNick:[sender senderID]];
252 realName = [sender senderID];
254 NSString *formattedName = [realName stringByAppendingString:@": "];
255 NSAttributedString *senderName = [[NSAttributedString alloc] initWithString:formattedName attributes:attribsOfText];
256 [buf appendAttributedString:senderName];
257 [senderName release];
259 [buf appendAttributedString:text];
261 NSAttributedString *lineBreak = [[NSAttributedString alloc] initWithString:@"\n" attributes:attribsOfText];
262 [buf appendAttributedString:lineBreak];
265 [buf appendAttributedString:gap];
271 //[buf addAttributes:baselineAttrib range:NSMakeRange(0, [[buf string] length])];
273 return [buf autorelease];
276 //Get tab delimited text version of chat
277 - (NSString *) exportableContents
280 NSMutableString *buf = [[NSMutableString alloc] initWithString:@""];
282 for (unsigned int i=0; i < [instantMessages count]; i++)
284 InstantMessage *im = [instantMessages objectAtIndex:i];
285 Presentity *sender = [im sender];
286 NSAttributedString *text = [im text];
287 NSDate *date = [im date];
290 [buf appendString:[[NSArray arrayWithObjects:
293 [date descriptionWithCalendarFormat:@"%m/%d/%Y" timeZone:nil locale:nil],
294 [date descriptionWithCalendarFormat:@"%H:%M:%S" timeZone:nil locale:nil],
296 componentsJoinedByString:@"\t"]];
297 [buf appendString:@"\r"];
300 return [buf autorelease];
303 - (NSArray *) participants
305 NSMutableSet *participantSet = [[NSMutableSet alloc] init];
307 for (unsigned int i=0; i < [instantMessages count]; i++)
309 InstantMessage *im = [instantMessages objectAtIndex:i];
310 Presentity *sender = [im sender];
311 [participantSet addObject:[sender senderID]];
314 return [participantSet allObjects];