Changeset 3235
- Timestamp:
- 05/26/06 03:05:17 (2 years ago)
- Files:
-
- trunk/Colloquy.xcodeproj/project.pbxproj (modified) (13 diffs)
- trunk/Models/JVChatEvent.m (modified) (1 diff)
- trunk/Models/JVChatMessage.h (modified) (2 diffs)
- trunk/Models/JVChatMessage.m (modified) (18 diffs)
- trunk/Models/JVChatTranscript.m (modified) (24 diffs)
- trunk/Models/JVSQLChatTranscript.h (added)
- trunk/Models/JVSQLChatTranscript.m (added)
- trunk/Resources/transcriptSchema.sql (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/Colloquy.xcodeproj/project.pbxproj
r3234 r3235 261 261 1CE6917008B183C8006D9CA0 /* NSTextSuite.scriptSuite in Resources */ = {isa = PBXBuildFile; fileRef = 1C7C76E707DBA1C100FB5F83 /* NSTextSuite.scriptSuite */; }; 262 262 1CE95886063F3BF90071C9C3 /* inspector.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CE95885063F3BF90071C9C3 /* inspector.png */; }; 263 1CEC004F0A20EF99004C2B86 /* transcriptSchema.sql in Resources */ = {isa = PBXBuildFile; fileRef = 1CEC004D0A20EF95004C2B86 /* transcriptSchema.sql */; }; 264 1CEC00540A20F030004C2B86 /* JVSQLChatTranscript.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC00530A20F030004C2B86 /* JVSQLChatTranscript.m */; }; 265 1CEC00570A20F05F004C2B86 /* JVSQLChatTranscript.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CEC00530A20F030004C2B86 /* JVSQLChatTranscript.m */; }; 263 266 1CECE26006A37BEC00350564 /* JVBehaviorPreferences.nib in Resources */ = {isa = PBXBuildFile; fileRef = 1CECE22F06A37A8300350564 /* JVBehaviorPreferences.nib */; }; 264 267 1CEE3B010578421400AD6DE2 /* statusAvailable.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CEE3AFE0578421400AD6DE2 /* statusAvailable.png */; }; … … 627 630 1CABFD0C0658629200801C15 /* JVStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JVStyle.h; path = Models/JVStyle.h; sourceTree = "<group>"; }; 628 631 1CABFD0D0658629200801C15 /* JVStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JVStyle.m; path = Models/JVStyle.m; sourceTree = "<group>"; }; 629 1CB2CD8C052DDC570094AAA4 /* Colloquy.app */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.application; path = Colloquy.app; sourceTree = BUILT_PRODUCTS_DIR; };632 1CB2CD8C052DDC570094AAA4 /* Colloquy.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Colloquy.app; sourceTree = BUILT_PRODUCTS_DIR; }; 630 633 1CB3716F060CC7E200F6A81F /* KABubbleWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KABubbleWindowController.h; path = Controllers/KABubbleWindowController.h; sourceTree = "<group>"; }; 631 634 1CB37170060CC7E200F6A81F /* KABubbleWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KABubbleWindowController.m; path = Controllers/KABubbleWindowController.m; sourceTree = "<group>"; }; … … 744 747 1CE72A99052C79E700A8FE6E /* JVChatConsole.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = JVChatConsole.nib; path = Resources/JVChatConsole.nib; sourceTree = "<group>"; }; 745 748 1CE95885063F3BF90071C9C3 /* inspector.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = inspector.png; path = Resources/inspector.png; sourceTree = "<group>"; }; 749 1CEC004D0A20EF95004C2B86 /* transcriptSchema.sql */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = transcriptSchema.sql; path = Resources/transcriptSchema.sql; sourceTree = "<group>"; }; 750 1CEC00520A20F030004C2B86 /* JVSQLChatTranscript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JVSQLChatTranscript.h; path = Models/JVSQLChatTranscript.h; sourceTree = "<group>"; }; 751 1CEC00530A20F030004C2B86 /* JVSQLChatTranscript.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JVSQLChatTranscript.m; path = Models/JVSQLChatTranscript.m; sourceTree = "<group>"; }; 746 752 1CECE23006A37A8300350564 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = Languages/English.lproj/JVBehaviorPreferences.nib; sourceTree = "<group>"; }; 747 753 1CEE3AFE0578421400AD6DE2 /* statusAvailable.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = statusAvailable.png; path = Resources/statusAvailable.png; sourceTree = "<group>"; }; … … 766 772 1CF627CA07558F79005DFCFA /* fileSend.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = fileSend.png; path = "Resources/Toolbar Icons/fileSend.png"; sourceTree = "<group>"; }; 767 773 1CF6511406EA22480073DEA8 /* Colloquy.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Colloquy.pch; sourceTree = "<group>"; }; 768 1CF651BB06EA29D10073DEA8 /* Standard Commands.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Standard Commands.pch"; path = "Plug-Ins/Standard Commands/Standard Commands.pch"; sourceTree = "<group>"; };769 774 1CF79CBC07AC77E600696918 /* JVChatTranscript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JVChatTranscript.h; path = Models/JVChatTranscript.h; sourceTree = "<group>"; }; 770 775 1CF79CBD07AC77E600696918 /* JVChatTranscript.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JVChatTranscript.m; path = Models/JVChatTranscript.m; sourceTree = "<group>"; }; … … 1360 1365 isa = PBXGroup; 1361 1366 children = ( 1362 1CF651BB06EA29D10073DEA8 /* Standard Commands.pch */,1363 1367 1C3B4D570427BD5200000102 /* JVStandardCommands.m */, 1364 1368 1C3B4D560427BD5200000102 /* JVStandardCommands.h */, … … 1421 1425 1CF79CBD07AC77E600696918 /* JVChatTranscript.m */, 1422 1426 1CF79CBC07AC77E600696918 /* JVChatTranscript.h */, 1427 1CEC00530A20F030004C2B86 /* JVSQLChatTranscript.m */, 1428 1CEC00520A20F030004C2B86 /* JVSQLChatTranscript.h */, 1423 1429 1C5EF36A07B45FBF004E66D3 /* JVChatSession.m */, 1424 1430 1C5EF36907B45FBF004E66D3 /* JVChatSession.h */, … … 1566 1572 F5394C0B0378E44D01A35792 /* Localizable.strings */, 1567 1573 F5BC17DD019655DC01A35792 /* info.colloquy.plist */, 1574 1CEC004D0A20EF95004C2B86 /* transcriptSchema.sql */, 1568 1575 1CBECDCF0508C8AB000001C8 /* default.xsl */, 1569 1576 0A5B683E0810EC9700398D5A /* default.css */, … … 2155 2162 1C710C4F09F323F8007B4515 /* splitviewDimple.png in Resources */, 2156 2163 1C710C5009F323F8007B4515 /* splitviewDividerBackground.png in Resources */, 2164 1CEC004F0A20EF99004C2B86 /* transcriptSchema.sql in Resources */, 2157 2165 ); 2158 2166 runOnlyForDeploymentPostprocessing = 0; … … 2260 2268 files = ( 2261 2269 1C59A92009FDEBA3000682B8 /* JVChatWindowControllerTests.m in Sources */, 2270 1CEC00540A20F030004C2B86 /* JVSQLChatTranscript.m in Sources */, 2262 2271 ); 2263 2272 runOnlyForDeploymentPostprocessing = 0; … … 2342 2351 1C710A6E09F23AF0007B4515 /* JVSideStatusView.m in Sources */, 2343 2352 1C710A7009F23AF0007B4515 /* JVSideOutlineView.m in Sources */, 2353 1CEC00570A20F05F004C2B86 /* JVSQLChatTranscript.m in Sources */, 2344 2354 ); 2345 2355 runOnlyForDeploymentPostprocessing = 0; … … 2841 2851 "-lxml2", 2842 2852 "-lxslt", 2853 "-lsqlite3", 2843 2854 ); 2844 2855 PRODUCT_NAME = Colloquy; … … 2864 2875 "-lxml2", 2865 2876 "-lxslt", 2877 "-lsqlite3", 2866 2878 ); 2867 2879 PRODUCT_NAME = Colloquy; … … 2933 2945 "-lxml2", 2934 2946 "-lxslt", 2947 "-lsqlite3", 2935 2948 ); 2936 2949 PRODUCT_NAME = Colloquy; trunk/Models/JVChatEvent.m
r3072 r3235 5 5 6 6 @implementation JVChatEvent 7 - (id) init {8 if( ( self = [super init] ) ) {9 _loadedMessage = NO;10 _loadedAttributes = NO;11 _loadedSmall = NO;12 _objectSpecifier = nil;13 _transcript = nil;14 _eventIdentifier = nil;15 _message = nil;16 _date = nil;17 _name = nil;18 _attributes = nil;19 }20 21 return self;22 }23 24 7 - (id) initWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript { 25 8 if( ( self = [self init] ) ) { trunk/Models/JVChatMessage.h
r3072 r3235 8 8 9 9 @interface JVChatMessage : NSObject <NSMutableCopying, JVChatTranscriptElement> { 10 @p rotected10 @public 11 11 /* xmlNode */ void *_node; 12 12 NSString *_messageIdentifier; … … 21 21 NSString *_senderBuddyIdentifier; 22 22 23 NSString *_htmlMessage;24 23 NSTextStorage *_attributedMessage; 25 24 NSDate *_date; trunk/Models/JVChatMessage.m
r3228 r3235 8 8 #import "JVChatRoomMember.h" 9 9 #import "NSAttributedStringMoreAdditions.h" 10 11 @interface JVChatTranscript (JVChatTranscriptPrivate) 12 - (void) _loadMessage:(JVChatMessage *) message; 13 - (void) _loadSenderForMessage:(JVChatMessage *) message; 14 - (void) _loadBodyForMessage:(JVChatMessage *) message; 15 @end 16 17 #pragma mark - 10 18 11 19 @implementation JVChatMessage … … 23 31 24 32 + (id) coerceString:(id) value toMessage:(Class) class { 25 return [[[JVMutableChatMessage alloc ] initWithText:value sender:nil] autorelease];33 return [[[JVMutableChatMessage allocWithZone:nil] initWithText:value sender:nil] autorelease]; 26 34 } 27 35 … … 31 39 32 40 + (id) coerceTextStorage:(id) value toMessage:(Class) class { 33 return [[[JVMutableChatMessage alloc ] initWithText:value sender:nil] autorelease];41 return [[[JVMutableChatMessage allocWithZone:nil] initWithText:value sender:nil] autorelease]; 34 42 } 35 43 … … 41 49 42 50 - (void) load { 43 if( _loaded || ! _node ) return; 44 45 @synchronized( [self transcript] ) { 46 xmlChar *prop = xmlGetProp( _node, (xmlChar *) "received" ); 47 [_date autorelease]; 48 _date = ( prop ? [[NSDate allocWithZone:[self zone]] initWithString:[NSString stringWithUTF8String:(char *) prop]] : nil ); 49 xmlFree( prop ); 50 51 prop = xmlGetProp( _node, (xmlChar *) "action" ); 52 _action = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? YES : NO ); 53 xmlFree( prop ); 54 55 prop = xmlGetProp( _node, (xmlChar *) "highlight" ); 56 _highlighted = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? YES : NO ); 57 xmlFree( prop ); 58 59 prop = xmlGetProp( _node, (xmlChar *) "ignored" ); 60 _ignoreStatus = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? JVMessageIgnored : _ignoreStatus ); 61 xmlFree( prop ); 62 63 prop = xmlGetProp( _node, (xmlChar *) "type" ); 64 _type = ( ( prop && ! strcmp( (char *) prop, "notice" ) ) ? JVChatMessageNoticeType : JVChatMessageNormalType ); 65 xmlFree( prop ); 66 67 prop = xmlGetProp( ((xmlNode *) _node) -> parent, (xmlChar *) "ignored" ); 68 _ignoreStatus = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? JVUserIgnored : _ignoreStatus ); 69 xmlFree( prop ); 70 71 prop = xmlGetProp( ((xmlNode *) _node) -> parent, (xmlChar *) "source" ); 72 [_source autorelease]; 73 _source = ( prop ? [[NSURL allocWithZone:[self zone]] initWithString:[NSString stringWithUTF8String:(char *) prop]] : nil ); 74 xmlFree( prop ); 75 } 76 77 _loaded = YES; 51 if( _loaded ) return; 52 [_transcript _loadMessage:self]; 78 53 } 79 54 80 55 - (void) loadBody { 81 if( _bodyLoaded || ! _node ) return; 82 83 @synchronized( [self transcript] ) { 84 [_attributedMessage autorelease]; 85 _attributedMessage = [[NSTextStorage allocWithZone:[self zone]] initWithXHTMLTree:_node baseURL:nil defaultAttributes:nil]; 86 } 87 88 _bodyLoaded = YES; 56 if( _bodyLoaded ) return; 57 [_transcript _loadBodyForMessage:self]; 89 58 } 90 59 91 60 - (void) loadSender { 92 if( _senderLoaded || ! _node ) return; 93 94 @synchronized( [self transcript] ) { 95 xmlNode *subNode = ((xmlNode *) _node) -> parent -> children; 96 97 do { 98 if( subNode -> type == XML_ELEMENT_NODE && ! strncmp( "sender", (char *) subNode -> name, 6 ) ) { 99 xmlChar *prop = xmlNodeGetContent( subNode ); 100 [_senderName autorelease]; 101 if( prop ) _senderName = [[NSString allocWithZone:[self zone]] initWithUTF8String:(char *) prop]; 102 else _senderName = nil; 103 xmlFree( prop ); 104 105 prop = xmlGetProp( subNode, (xmlChar *) "nickname" ); 106 [_senderNickname autorelease]; 107 if( prop ) _senderNickname = [[NSString allocWithZone:[self zone]] initWithUTF8String:(char *) prop]; 108 else _senderNickname = nil; 109 xmlFree( prop ); 110 111 prop = xmlGetProp( subNode, (xmlChar *) "identifier" ); 112 [_senderIdentifier autorelease]; 113 if( prop ) _senderIdentifier = [[NSString allocWithZone:[self zone]] initWithUTF8String:(char *) prop]; 114 else _senderIdentifier = nil; 115 xmlFree( prop ); 116 117 prop = xmlGetProp( subNode, (xmlChar *) "hostmask" ); 118 [_senderHostmask autorelease]; 119 if( prop ) _senderHostmask = [[NSString allocWithZone:[self zone]] initWithUTF8String:(char *) prop]; 120 else _senderHostmask = nil; 121 xmlFree( prop ); 122 123 prop = xmlGetProp( subNode, (xmlChar *) "class" ); 124 [_senderClass autorelease]; 125 if( prop ) _senderClass = [[NSString allocWithZone:[self zone]] initWithUTF8String:(char *) prop]; 126 else _senderClass = nil; 127 xmlFree( prop ); 128 129 prop = xmlGetProp( subNode, (xmlChar *) "self" ); 130 if( prop && ! strcmp( (char *) prop, "yes" ) ) _senderIsLocalUser = YES; 131 else _senderIsLocalUser = NO; 132 xmlFree( prop ); 133 134 break; 135 } 136 } while( ( subNode = subNode -> next ) ); 137 } 138 139 _senderLoaded = YES; 61 if( _senderLoaded ) return; 62 [_transcript _loadSenderForMessage:self]; 140 63 } 141 64 … … 144 67 - (id) init { 145 68 if( ( self = [super init] ) ) { 146 _loaded = NO;147 _bodyLoaded = NO;148 _senderLoaded = NO;149 _objectSpecifier = nil;150 _transcript = nil;151 _messageIdentifier = nil;152 _htmlMessage = nil;153 _attributedMessage = nil;154 _date = nil;155 _source = nil;156 _action = NO;157 _highlighted = NO;158 _senderIsLocalUser = NO;159 69 _ignoreStatus = JVNotIgnored; 160 70 _type = JVChatMessageNormalType; … … 164 74 } 165 75 166 - (id) initWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript {167 if( ( self = [self init] ) ) {168 _node = node;169 _transcript = transcript; // weak reference170 171 if( ! _node || node -> type != XML_ELEMENT_NODE ) {172 [self release];173 return nil;174 }175 176 @synchronized( [self transcript] ) {177 xmlChar *idStr = xmlGetProp( (xmlNode *) _node, (xmlChar *) "id" );178 _messageIdentifier = ( idStr ? [[NSString allocWithZone:[self zone]] initWithUTF8String:(char *) idStr] : nil );179 xmlFree( idStr );180 }181 }182 183 return self;184 }185 186 76 - (id) mutableCopyWithZone:(NSZone *) zone { 187 JVChatMessage *ret = nil; 188 189 @synchronized( [self transcript] ) { 190 ret = [[JVMutableChatMessage allocWithZone:zone] initWithNode:[self node] andTranscript:nil]; 191 192 [ret load]; 193 [ret loadBody]; 194 [ret loadSender]; 195 196 [ret performSelector:@selector( setNode: ) withObject:NULL]; // remove the node association 77 JVMutableChatMessage *ret = nil; 78 79 @synchronized( _transcript ) { 80 ret = [[JVMutableChatMessage allocWithZone:zone] init]; 81 82 ret -> _loaded = YES; 83 ret -> _senderLoaded = YES; 84 ret -> _bodyLoaded = YES; 85 86 ret -> _senderIsLocalUser = [self senderIsLocalUser]; 87 ret -> _senderIdentifier = [[self senderIdentifier] copyWithZone:zone]; 88 ret -> _senderName = [[self senderName] copyWithZone:zone]; 89 ret -> _senderHostmask = [[self senderHostmask] copyWithZone:zone]; 90 ret -> _senderClass = [[self senderClass] copyWithZone:zone]; 91 ret -> _senderBuddyIdentifier = [[self senderBuddyIdentifier] copyWithZone:zone]; 92 ret -> _attributedMessage = [[self body] mutableCopyWithZone:zone]; 93 ret -> _source = [[self source] copyWithZone:zone]; 94 ret -> _date = [[self date] copyWithZone:zone]; 95 ret -> _action = [self isAction]; 96 ret -> _highlighted = [self isHighlighted]; 97 ret -> _ignoreStatus = [self ignoreStatus]; 98 ret -> _type = [self type]; 197 99 } 198 100 … … 202 104 - (void) dealloc { 203 105 [_messageIdentifier release]; 204 [_htmlMessage release];205 106 [_attributedMessage release]; 206 107 [_date release]; … … 218 119 _transcript = nil; 219 120 _messageIdentifier = nil; 220 _htmlMessage = nil;221 121 _attributedMessage = nil; 222 122 _date = nil; … … 236 136 #pragma mark - 237 137 238 + (id) messageWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript {239 return [[[self alloc] initWithNode:node andTranscript:transcript] autorelease];240 }241 242 #pragma mark -243 244 138 - (void *) node { 245 139 return _node; 246 140 } 247 141 248 - (void) setNode:(xmlNode *) node {142 - (void) _setNode:(xmlNode *) node { 249 143 _node = node; 250 144 } … … 354 248 355 249 - (void) setObjectSpecifier:(NSScriptObjectSpecifier *) objectSpecifier { 356 [_objectSpecifier autorelease];250 id old = _objectSpecifier; 357 251 _objectSpecifier = [objectSpecifier retain]; 252 [old release]; 358 253 } 359 254 … … 365 260 366 261 - (NSString *) debugDescription { 367 return [NSString stringWithFormat:@"<%@ 0x%x : (%@) %@>", NSStringFromClass( [self class] ), (unsigned long) self, [self senderNickname], [self body]];262 return [NSString stringWithFormat:@"<%@ 0x%x [%@]: (%@) %@>", NSStringFromClass( [self class] ), (unsigned long) self, _messageIdentifier, [self senderNickname], [self body]]; 368 263 } 369 264 … … 408 303 409 304 + (id) messageWithText:(id) body sender:(id) sender { 410 return [[[self alloc] initWithText:body sender:sender] autorelease]; 411 } 412 413 #pragma mark - 414 415 - (id) init { 416 if( ( self = [super init] ) ) _doc = NULL; 417 return self; 418 } 305 return [[[self allocWithZone:nil] initWithText:body sender:sender] autorelease]; 306 } 307 308 #pragma mark - 419 309 420 310 - (id) initWithText:(id) body sender:(id) sender { … … 503 393 } 504 394 505 - (void) setNode:(xmlNode *) node {395 - (void) _setNode:(xmlNode *) node { 506 396 if( _doc ) { 507 397 xmlFreeDoc( _doc ); … … 515 405 516 406 - (void) setDate:(NSDate *) date { 517 [self setNode:NULL];518 [_date autorelease];407 [self _setNode:NULL]; 408 id old = _date; 519 409 _date = [date copyWithZone:[self zone]]; 410 [old release]; 520 411 } 521 412 … … 523 414 524 415 - (void) setSender:(id) sender { 525 [self setNode:NULL];526 [_sender autorelease];416 [self _setNode:NULL]; 417 id old = _sender; 527 418 _sender = [sender retain]; 419 [old release]; 528 420 } 529 421 … … 597 489 598 490 - (void) setBody:(id) message { 599 [self setNode:NULL];491 [self _setNode:NULL]; 600 492 if( ! _attributedMessage ) { 601 if( [message isKindOfClass:[NSTextStorage class]] ) _attributedMessage = [message retain];602 else if( [message isKindOfClass:[NSAttributedString class]] ) _attributedMessage = [[NSTextStorage alloc ] initWithAttributedString:message];603 else if( [message isKindOfClass:[NSString class]] ) _attributedMessage = [[NSTextStorage alloc ] initWithString:(NSString *)message];493 if( [message isKindOfClass:[NSTextStorage class]] ) _attributedMessage = [message mutableCopyWithZone:nil]; 494 else if( [message isKindOfClass:[NSAttributedString class]] ) _attributedMessage = [[NSTextStorage allocWithZone:nil] initWithAttributedString:message]; 495 else if( [message isKindOfClass:[NSString class]] ) _attributedMessage = [[NSTextStorage allocWithZone:nil] initWithString:(NSString *)message]; 604 496 } else if( _attributedMessage && [message isKindOfClass:[NSAttributedString class]] ) { 605 497 [_attributedMessage setAttributedString:message]; 606 498 } else if( _attributedMessage && [message isKindOfClass:[NSString class]] ) { 607 id string = [[ [NSAttributedString alloc] initWithString:(NSString *)message] autorelease];499 id string = [[NSAttributedString allocWithZone:nil] initWithString:(NSString *)message]; 608 500 [_attributedMessage setAttributedString:string]; 501 [string release]; 609 502 } 610 503 } … … 621 514 622 515 - (void) setAction:(BOOL) action { 623 [self setNode:NULL];516 [self _setNode:NULL]; 624 517 _action = action; 625 518 } 626 519 627 520 - (void) setHighlighted:(BOOL) highlighted { 628 [self setNode:NULL];521 [self _setNode:NULL]; 629 522 _highlighted = highlighted; 630 523 } 631 524 632 525 - (void) setIgnoreStatus:(JVIgnoreMatchResult) ignoreStatus { 633 [self setNode:NULL];526 [self _setNode:NULL]; 634 527 _ignoreStatus = ignoreStatus; 635 528 } 636 529 637 530 - (void) setType:(JVChatMessageType) type { 638 [self setNode:NULL];531 [self _setNode:NULL]; 639 532 _type = type; 640 533 } … … 643 536 644 537 - (void) setSource:(NSURL *) source { 645 [self setNode:NULL];646 [_source autorelease];538 [self _setNode:NULL]; 539 id old = _source; 647 540 _source = [source copyWithZone:[self zone]]; 541 [old release]; 648 542 } 649 543 650 544 - (void) setMessageIdentifier:(NSString *) identifier { 651 [self setNode:NULL];652 [_messageIdentifier autorelease];545 [self _setNode:NULL]; 546 id old = _messageIdentifier; 653 547 _messageIdentifier = [identifier copyWithZone:[self zone]]; 548 [old release]; 654 549 } 655 550 trunk/Models/JVChatTranscript.m
r3072 r3235 4 4 #import "JVChatEvent.h" 5 5 #import "KAIgnoreRule.h" 6 #import "NSAttributedStringMoreAdditions.h" 6 7 7 8 #import <libxml/tree.h> … … 39 40 40 41 @interface JVChatMessage (JVChatMessagePrivate) 41 + (id) messageWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript; 42 - (id) initWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript; 43 - (void) setNode:(xmlNode *) node; 42 - (id) _initWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript; 43 - (void) _setNode:(xmlNode *) node; 44 - (void) _loadFromXML; 45 - (void) _loadSenderFromXML; 46 - (void) _loadBodyFromXML; 44 47 @end 45 48 … … 285 288 @synchronized( self ) { 286 289 unsigned long i = 0; 287 NSMutableArray *ret = [ NSMutableArray arrayWithCapacity:( range.length - range.location )];290 NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:range.length]; 288 291 289 292 xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; … … 294 297 if( subNode && subNode -> type == XML_ELEMENT_NODE && ! strncmp( "message", (char *) subNode -> name, 7 ) ) { 295 298 if( NSLocationInRange( i, range ) ) { 296 JVChatMessage *msg = [ JVChatMessage messageWithNode:subNode andTranscript:self];299 JVChatMessage *msg = [[JVChatMessage allocWithZone:nil] _initWithNode:subNode andTranscript:self]; 297 300 if( msg ) [ret addObject:msg]; 301 [msg release]; 298 302 } 299 303 … … 319 323 320 324 done: 321 return [ NSArray arrayWithArray:ret];325 return [ret autorelease]; 322 326 } 323 327 } … … 335 339 do { 336 340 if( subNode && subNode -> type == XML_ELEMENT_NODE && ! strncmp( "message", (char *) subNode -> name, 7 ) ) 337 return [ JVChatMessage messageWithNode:subNode andTranscript:self];341 return [[[JVChatMessage allocWithZone:nil] _initWithNode:subNode andTranscript:self] autorelease]; 338 342 } while( subNode && ( subNode = subNode -> prev ) ); 339 343 } else if( node && node -> type == XML_ELEMENT_NODE && ! strncmp( "session", (char *) node -> name, 7 ) ) { … … 351 355 352 356 - (NSArray *) appendElements:(NSArray *) elements { 353 NSMutableArray *ret = [ NSMutableArray arrayWithCapacity:[elements count]];357 NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:[elements count]]; 354 358 NSEnumerator *enumerator = [elements objectEnumerator]; 355 359 id element = nil; … … 366 370 } 367 371 368 return [ NSArray arrayWithArray:ret];372 return [ret autorelease]; 369 373 } 370 374 … … 390 394 } 391 395 396 if( [_messages count] < range.location ) 397 for( unsigned long i = [_messages count]; i < range.location; i++ ) 398 [_messages insertObject:[NSNull null] atIndex:i]; 399 400 NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:range.length]; 401 JVChatMessage *msg = nil; 402 392 403 unsigned long i = 0; 393 394 if( [_messages count] < range.location )395 for( i = [_messages count]; i < range.location; i++ )396 [_messages insertObject:[NSNull null] atIndex:i];397 398 NSMutableArray *ret = [NSMutableArray arrayWithCapacity:( range.length - range.location )];399 JVChatMessage *msg = nil;400 401 i = 0;402 404 403 405 xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; … … 409 411 if( NSLocationInRange( i, range ) ) { 410 412 if( [_messages count] > i && [[_messages objectAtIndex:i] isKindOfClass:[JVChatMessage class]] ) { 411 msg = [ _messages objectAtIndex:i];413 msg = [[_messages objectAtIndex:i] retain]; 412 414 } else if( [_messages count] > i && [[_messages objectAtIndex:i] isKindOfClass:[NSNull class]] ) { 413 msg = [ JVChatMessage messageWithNode:subNode andTranscript:self];415 msg = [[JVChatMessage allocWithZone:nil] _initWithNode:subNode andTranscript:self]; 414 416 id classDesc = [NSClassDescription classDescriptionForClass:[self class]]; 415 417 [msg setObjectSpecifier:[[[NSUniqueIDSpecifier alloc] initWithContainerClassDescription:classDesc containerSpecifier:[self objectSpecifier] key:@"messages" uniqueID:[msg messageIdentifier]] autorelease]]; 416 418 [_messages replaceObjectAtIndex:i withObject:msg]; 417 419 } else if( [_messages count] == i ) { 418 msg = [ JVChatMessage messageWithNode:subNode andTranscript:self];420 msg = [[JVChatMessage allocWithZone:nil] _initWithNode:subNode andTranscript:self]; 419 421 id classDesc = [NSClassDescription classDescriptionForClass:[self class]]; 420 422 [msg setObjectSpecifier:[[[NSUniqueIDSpecifier alloc] initWithContainerClassDescription:classDesc containerSpecifier:[self objectSpecifier] key:@"messages" uniqueID:[msg messageIdentifier]] autorelease]]; … … 422 424 } else continue; 423 425 if( msg ) [ret addObject:msg]; 426 [msg release]; 424 427 } 425 428 … … 431 434 432 435 done: 433 return [ NSArray arrayWithArray:ret];436 return [ret autorelease]; 434 437 } 435 438 } … … 471 474 } while( node && ( node = node -> next ) ); 472 475 473 return ( foundNode ? [ JVChatMessage messageWithNode:foundNode andTranscript:self] : nil );476 return ( foundNode ? [[[JVChatMessage allocWithZone:nil] _initWithNode:foundNode andTranscript:self] autorelease] : nil ); 474 477 } 475 478 } … … 486 489 do { 487 490 if( node && node -> type == XML_ELEMENT_NODE && ! strncmp( "message", (char *) node -> name, 7 ) ) { 488 JVChatMessage *msg = [ JVChatMessage messageWithNode:node andTranscript:self];491 JVChatMessage *msg = [[JVChatMessage allocWithZone:nil] _initWithNode:node andTranscript:self]; 489 492 if( msg ) [results addObject:msg]; 493 [msg release]; 490 494 } 491 495 } while( node && ( node = node -> next ) ); 492 496 493 return [NSArray arrayWithArray:results];497 return results; 494 498 } 495 499 … … 514 518 } while( node && ( node = node -> prev ) ); 515 519 516 return ( foundNode ? [ JVChatMessage messageWithNode:foundNode andTranscript:self] : nil );520 return ( foundNode ? [[[JVChatMessage allocWithZone:nil] _initWithNode:foundNode andTranscript:self] autorelease] : nil ); 517 521 } 518 522 } … … 640 644 _requiresNewEnvelope = NO; 641 645 642 return [ JVChatMessage messageWithNode:child andTranscript:self];646 return [[[JVChatMessage allocWithZone:nil] _initWithNode:child andTranscript:self] autorelease]; 643 647 } 644 648 } … … 651 655 NSEnumerator *enumerator = [messages objectEnumerator]; 652 656 JVChatMessage *message = nil; 653 NSMutableArray *ret = [ NSMutableArray arrayWithCapacity:[messages count]];657 NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:[messages count]]; 654 658 655 659 if( forceEnvelope ) _requiresNewEnvelope = YES; … … 663 667 } 664 668 665 return [ NSArray arrayWithArray:ret];669 return [ret autorelease]; 666 670 } 667 671 … … 677 681 @synchronized( self ) { 678 682 unsigned long i = 0; 679 NSMutableArray *ret = [ NSMutableArray arrayWithCapacity:( range.length - range.location )];683 NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:range.length]; 680 684 681 685 xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; … … 692 696 693 697 done: 694 return [ NSArray arrayWithArray:ret];698 return [ret autorelease]; 695 699 } 696 700 } … … 738 742 @synchronized( self ) { 739 743 unsigned long i = 0; 740 NSMutableArray *ret = [ NSMutableArray arrayWithCapacity:( range.length - range.location )];744 NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:range.length]; 741 745 742 746 xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; … … 753 757 754 758 done: 755 return [ NSArray arrayWithArray:ret];759 return [ret autorelease]; 756 760 } 757 761 } … … 1152 1156 } 1153 1157 } 1158 1159 - (void) _loadMessage:(JVChatMessage *) message { 1160 [message _loadFromXML]; 1161 } 1162 1163 - (void) _loadSenderForMessage:(JVChatMessage *) message { 1164 [message _loadSenderFromXML]; 1165 } 1166 1167 - (void) _loadBodyForMessage:(JVChatMessage *) message { 1168 [message _loadBodyFromXML]; 1169 } 1154 1170 @end 1155 1171 … … 1254 1270 } 1255 1271 @end 1272 1273 #pragma mark - 1274 1275 @implementation JVChatMessage (JVChatMessageChatTranscriptPrivate) 1276 - (id) _initWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript { 1277 if( ( self = [self init] ) ) { 1278 _node = node; 1279 _transcript = transcript; // weak reference 1280 1281 if( ! _node || node -> type != XML_ELEMENT_NODE ) { 1282 [self release]; 1283 return nil; 1284 } 1285 1286 @synchronized( _transcript ) { 1287 xmlChar *idStr = xmlGetProp( (xmlNode *) _node, (xmlChar *) "id" ); 1288 _messageIdentifier = ( idStr ? [[NSString allocWithZone:[self zone]] initWithUTF8String:(char *) idStr] : nil ); 1289 xmlFree( idStr ); 1290 } 1291 } 1292 1293 return self; 1294 } 1295 1296 - (void) _loadFromXML { 1297 if( _loaded || ! _node ) return; 1298 1299 @synchronized( _transcript ) { 1300 xmlChar *prop = xmlGetProp( _node, (xmlChar *) "received" ); 1301 [_date autorelease]; 1302 _date = ( prop ? [[NSDate allocWithZone:[self zone]] initWithString:[NSString stringWithUTF8String:(char *) prop]] : nil ); 1303 xmlFree( prop ); 1304 1305 prop = xmlGetProp( _node, (xmlChar *) "action" ); 1306 _action = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? YES : NO ); 1307 xmlFree( prop ); 1308 1309 prop = xmlGetProp( _node, (xmlChar *) "highlight" ); 1310 _highlighted = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? YES : NO ); 1311 xmlFree( prop ); 1312 1313 prop = xmlGetProp( _node, (xmlChar *) "ignored" ); 1314 _ignoreStatus = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? JVMessageIgnored : _ignoreStatus ); 1315 xmlFree( prop ); 1316 1317 prop = xmlGetProp( _node, (xmlChar *) "type" ); 1318 _type = ( ( prop && ! strcmp( (char *) prop, "notice" ) ) ? JVChatMessageNoticeType : JVChatMessageNormalType ); 1319 xmlFree( prop ); 1320 1321 prop = xmlGetProp( ((xmlNode *) _node) -> parent, (xmlChar *) "ignored" ); 1322 _ignoreStatus = ( ( prop && ! strcmp( (char *) prop, "yes" ) ) ? JVUserIgnored : _ignoreStatus ); 1323 xmlFree( prop ); 1324 1325 prop = xmlGetProp( ((xmlNode *) _node) -> parent, (xmlChar *) "source" ); 1326 [_source autorelease]; 1327 _source = ( prop ? [[NSURL allocWithZone:[self zone]] initWithString:[NSString stringWithUTF8String:(char *) prop]] : nil ); 1328 xmlFree( prop ); 1329 } 1330 1331 _loaded = YES; 1332 } 1333 1334 - (void) _loadSenderFromXML { 1335 if( _senderLoaded || ! _node ) return; 1336 1337 @synchronized( _transcript ) { 1338 xmlNode *subNode = ((xmlNode *) _node) -> parent -> children; 1339 1340 do { 1341 if( subNode -> type == XML_ELEMENT_NODE && ! strncmp( "sender"
