Changeset 3235

Show
Ignore:
Timestamp:
05/26/06 03:05:17 (2 years ago)
Author:
timothy
Message:

Initial implementation of SQL transcript support. No usable yet.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Colloquy.xcodeproj/project.pbxproj

    r3234 r3235  
    261261                1CE6917008B183C8006D9CA0 /* NSTextSuite.scriptSuite in Resources */ = {isa = PBXBuildFile; fileRef = 1C7C76E707DBA1C100FB5F83 /* NSTextSuite.scriptSuite */; }; 
    262262                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 */; }; 
    263266                1CECE26006A37BEC00350564 /* JVBehaviorPreferences.nib in Resources */ = {isa = PBXBuildFile; fileRef = 1CECE22F06A37A8300350564 /* JVBehaviorPreferences.nib */; }; 
    264267                1CEE3B010578421400AD6DE2 /* statusAvailable.png in Resources */ = {isa = PBXBuildFile; fileRef = 1CEE3AFE0578421400AD6DE2 /* statusAvailable.png */; }; 
     
    627630                1CABFD0C0658629200801C15 /* JVStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JVStyle.h; path = Models/JVStyle.h; sourceTree = "<group>"; }; 
    628631                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; }; 
    630633                1CB3716F060CC7E200F6A81F /* KABubbleWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KABubbleWindowController.h; path = Controllers/KABubbleWindowController.h; sourceTree = "<group>"; }; 
    631634                1CB37170060CC7E200F6A81F /* KABubbleWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KABubbleWindowController.m; path = Controllers/KABubbleWindowController.m; sourceTree = "<group>"; }; 
     
    744747                1CE72A99052C79E700A8FE6E /* JVChatConsole.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = JVChatConsole.nib; path = Resources/JVChatConsole.nib; sourceTree = "<group>"; }; 
    745748                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>"; }; 
    746752                1CECE23006A37A8300350564 /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = Languages/English.lproj/JVBehaviorPreferences.nib; sourceTree = "<group>"; }; 
    747753                1CEE3AFE0578421400AD6DE2 /* statusAvailable.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = statusAvailable.png; path = Resources/statusAvailable.png; sourceTree = "<group>"; }; 
     
    766772                1CF627CA07558F79005DFCFA /* fileSend.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = fileSend.png; path = "Resources/Toolbar Icons/fileSend.png"; sourceTree = "<group>"; }; 
    767773                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>"; }; 
    769774                1CF79CBC07AC77E600696918 /* JVChatTranscript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JVChatTranscript.h; path = Models/JVChatTranscript.h; sourceTree = "<group>"; }; 
    770775                1CF79CBD07AC77E600696918 /* JVChatTranscript.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JVChatTranscript.m; path = Models/JVChatTranscript.m; sourceTree = "<group>"; }; 
     
    13601365                        isa = PBXGroup; 
    13611366                        children = ( 
    1362                                 1CF651BB06EA29D10073DEA8 /* Standard Commands.pch */, 
    13631367                                1C3B4D570427BD5200000102 /* JVStandardCommands.m */, 
    13641368                                1C3B4D560427BD5200000102 /* JVStandardCommands.h */, 
     
    14211425                                1CF79CBD07AC77E600696918 /* JVChatTranscript.m */, 
    14221426                                1CF79CBC07AC77E600696918 /* JVChatTranscript.h */, 
     1427                                1CEC00530A20F030004C2B86 /* JVSQLChatTranscript.m */, 
     1428                                1CEC00520A20F030004C2B86 /* JVSQLChatTranscript.h */, 
    14231429                                1C5EF36A07B45FBF004E66D3 /* JVChatSession.m */, 
    14241430                                1C5EF36907B45FBF004E66D3 /* JVChatSession.h */, 
     
    15661572                                F5394C0B0378E44D01A35792 /* Localizable.strings */, 
    15671573                                F5BC17DD019655DC01A35792 /* info.colloquy.plist */, 
     1574                                1CEC004D0A20EF95004C2B86 /* transcriptSchema.sql */, 
    15681575                                1CBECDCF0508C8AB000001C8 /* default.xsl */, 
    15691576                                0A5B683E0810EC9700398D5A /* default.css */, 
     
    21552162                                1C710C4F09F323F8007B4515 /* splitviewDimple.png in Resources */, 
    21562163                                1C710C5009F323F8007B4515 /* splitviewDividerBackground.png in Resources */, 
     2164                                1CEC004F0A20EF99004C2B86 /* transcriptSchema.sql in Resources */, 
    21572165                        ); 
    21582166                        runOnlyForDeploymentPostprocessing = 0; 
     
    22602268                        files = ( 
    22612269                                1C59A92009FDEBA3000682B8 /* JVChatWindowControllerTests.m in Sources */, 
     2270                                1CEC00540A20F030004C2B86 /* JVSQLChatTranscript.m in Sources */, 
    22622271                        ); 
    22632272                        runOnlyForDeploymentPostprocessing = 0; 
     
    23422351                                1C710A6E09F23AF0007B4515 /* JVSideStatusView.m in Sources */, 
    23432352                                1C710A7009F23AF0007B4515 /* JVSideOutlineView.m in Sources */, 
     2353                                1CEC00570A20F05F004C2B86 /* JVSQLChatTranscript.m in Sources */, 
    23442354                        ); 
    23452355                        runOnlyForDeploymentPostprocessing = 0; 
     
    28412851                                        "-lxml2", 
    28422852                                        "-lxslt", 
     2853                                        "-lsqlite3", 
    28432854                                ); 
    28442855                                PRODUCT_NAME = Colloquy; 
     
    28642875                                        "-lxml2", 
    28652876                                        "-lxslt", 
     2877                                        "-lsqlite3", 
    28662878                                ); 
    28672879                                PRODUCT_NAME = Colloquy; 
     
    29332945                                        "-lxml2", 
    29342946                                        "-lxslt", 
     2947                                        "-lsqlite3", 
    29352948                                ); 
    29362949                                PRODUCT_NAME = Colloquy; 
  • trunk/Models/JVChatEvent.m

    r3072 r3235  
    55 
    66@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  
    247- (id) initWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript { 
    258        if( ( self = [self init] ) ) { 
  • trunk/Models/JVChatMessage.h

    r3072 r3235  
    88 
    99@interface JVChatMessage : NSObject <NSMutableCopying, JVChatTranscriptElement> { 
    10         @protected 
     10        @public 
    1111        /* xmlNode */ void *_node; 
    1212        NSString *_messageIdentifier; 
     
    2121        NSString *_senderBuddyIdentifier; 
    2222 
    23         NSString *_htmlMessage; 
    2423        NSTextStorage *_attributedMessage; 
    2524        NSDate *_date; 
  • trunk/Models/JVChatMessage.m

    r3228 r3235  
    88#import "JVChatRoomMember.h" 
    99#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 - 
    1018 
    1119@implementation JVChatMessage 
     
    2331 
    2432+ (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]; 
    2634} 
    2735 
     
    3139 
    3240+ (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]; 
    3442} 
    3543 
     
    4149 
    4250- (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]; 
    7853} 
    7954 
    8055- (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]; 
    8958} 
    9059 
    9160- (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]; 
    14063} 
    14164 
     
    14467- (id) init { 
    14568        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; 
    15969                _ignoreStatus = JVNotIgnored; 
    16070                _type = JVChatMessageNormalType; 
     
    16474} 
    16575 
    166 - (id) initWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript { 
    167         if( ( self = [self init] ) ) { 
    168                 _node = node; 
    169                 _transcript = transcript; // weak reference 
    170  
    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  
    18676- (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]; 
    19799        } 
    198100 
     
    202104- (void) dealloc { 
    203105        [_messageIdentifier release]; 
    204         [_htmlMessage release]; 
    205106        [_attributedMessage release]; 
    206107        [_date release]; 
     
    218119        _transcript = nil; 
    219120        _messageIdentifier = nil; 
    220         _htmlMessage = nil; 
    221121        _attributedMessage = nil; 
    222122        _date = nil; 
     
    236136#pragma mark - 
    237137 
    238 + (id) messageWithNode:(xmlNode *) node andTranscript:(JVChatTranscript *) transcript { 
    239         return [[[self alloc] initWithNode:node andTranscript:transcript] autorelease]; 
    240 } 
    241  
    242 #pragma mark - 
    243  
    244138- (void *) node { 
    245139        return _node; 
    246140} 
    247141 
    248 - (void) setNode:(xmlNode *) node { 
     142- (void) _setNode:(xmlNode *) node { 
    249143        _node = node; 
    250144} 
     
    354248 
    355249- (void) setObjectSpecifier:(NSScriptObjectSpecifier *) objectSpecifier { 
    356         [_objectSpecifier autorelease]
     250        id old = _objectSpecifier
    357251        _objectSpecifier = [objectSpecifier retain]; 
     252        [old release]; 
    358253} 
    359254 
     
    365260 
    366261- (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]]; 
    368263} 
    369264 
     
    408303 
    409304+ (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 - 
    419309 
    420310- (id) initWithText:(id) body sender:(id) sender { 
     
    503393} 
    504394 
    505 - (void) setNode:(xmlNode *) node { 
     395- (void) _setNode:(xmlNode *) node { 
    506396        if( _doc ) { 
    507397                xmlFreeDoc( _doc ); 
     
    515405 
    516406- (void) setDate:(NSDate *) date { 
    517         [self setNode:NULL]; 
    518         [_date autorelease]
     407        [self _setNode:NULL]; 
     408        id old = _date
    519409        _date = [date copyWithZone:[self zone]]; 
     410        [old release]; 
    520411} 
    521412 
     
    523414 
    524415- (void) setSender:(id) sender { 
    525         [self setNode:NULL]; 
    526         [_sender autorelease]
     416        [self _setNode:NULL]; 
     417        id old = _sender
    527418        _sender = [sender retain]; 
     419        [old release]; 
    528420} 
    529421 
     
    597489 
    598490- (void) setBody:(id) message { 
    599         [self setNode:NULL]; 
     491        [self _setNode:NULL]; 
    600492        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]; 
    604496        } else if( _attributedMessage && [message isKindOfClass:[NSAttributedString class]] ) { 
    605497                [_attributedMessage setAttributedString:message]; 
    606498        } 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]; 
    608500                [_attributedMessage setAttributedString:string]; 
     501                [string release]; 
    609502        } 
    610503} 
     
    621514 
    622515- (void) setAction:(BOOL) action { 
    623         [self setNode:NULL]; 
     516        [self _setNode:NULL]; 
    624517        _action = action; 
    625518} 
    626519 
    627520- (void) setHighlighted:(BOOL) highlighted { 
    628         [self setNode:NULL]; 
     521        [self _setNode:NULL]; 
    629522        _highlighted = highlighted; 
    630523} 
    631524 
    632525- (void) setIgnoreStatus:(JVIgnoreMatchResult) ignoreStatus { 
    633         [self setNode:NULL]; 
     526        [self _setNode:NULL]; 
    634527        _ignoreStatus = ignoreStatus; 
    635528} 
    636529 
    637530- (void) setType:(JVChatMessageType) type { 
    638         [self setNode:NULL]; 
     531        [self _setNode:NULL]; 
    639532        _type = type; 
    640533} 
     
    643536 
    644537- (void) setSource:(NSURL *) source { 
    645         [self setNode:NULL]; 
    646         [_source autorelease]
     538        [self _setNode:NULL]; 
     539        id old = _source
    647540        _source = [source copyWithZone:[self zone]]; 
     541        [old release]; 
    648542} 
    649543 
    650544- (void) setMessageIdentifier:(NSString *) identifier { 
    651         [self setNode:NULL]; 
    652         [_messageIdentifier autorelease]
     545        [self _setNode:NULL]; 
     546        id old = _messageIdentifier
    653547        _messageIdentifier = [identifier copyWithZone:[self zone]]; 
     548        [old release]; 
    654549} 
    655550 
  • trunk/Models/JVChatTranscript.m

    r3072 r3235  
    44#import "JVChatEvent.h" 
    55#import "KAIgnoreRule.h" 
     6#import "NSAttributedStringMoreAdditions.h" 
    67 
    78#import <libxml/tree.h> 
     
    3940 
    4041@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; 
    4447@end 
    4548 
     
    285288        @synchronized( self ) { 
    286289                unsigned long i = 0; 
    287                 NSMutableArray *ret = [NSMutableArray arrayWithCapacity:( range.length - range.location )]; 
     290                NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:range.length]; 
    288291 
    289292                xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; 
     
    294297                                        if( subNode && subNode -> type == XML_ELEMENT_NODE && ! strncmp( "message", (char *) subNode -> name, 7 ) ) { 
    295298                                                if( NSLocationInRange( i, range ) ) { 
    296                                                         JVChatMessage *msg = [JVChatMessage messageWithNode:subNode andTranscript:self]; 
     299                                                        JVChatMessage *msg = [[JVChatMessage allocWithZone:nil] _initWithNode:subNode andTranscript:self]; 
    297300                                                        if( msg ) [ret addObject:msg]; 
     301                                                        [msg release]; 
    298302                                                } 
    299303 
     
    319323 
    320324        done: 
    321                 return [NSArray arrayWithArray:ret]; 
     325                return [ret autorelease]; 
    322326        } 
    323327} 
     
    335339                                do { 
    336340                                        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]; 
    338342                                } while( subNode && ( subNode = subNode -> prev ) ); 
    339343                        } else if( node && node -> type == XML_ELEMENT_NODE && ! strncmp( "session", (char *) node -> name, 7 ) ) { 
     
    351355 
    352356- (NSArray *) appendElements:(NSArray *) elements { 
    353         NSMutableArray *ret = [NSMutableArray arrayWithCapacity:[elements count]]; 
     357        NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:[elements count]]; 
    354358        NSEnumerator *enumerator = [elements objectEnumerator]; 
    355359        id element = nil; 
     
    366370        } 
    367371 
    368         return [NSArray arrayWithArray:ret]; 
     372        return [ret autorelease]; 
    369373} 
    370374 
     
    390394                } 
    391395 
     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 
    392403                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; 
    402404 
    403405                xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; 
     
    409411                                                if( NSLocationInRange( i, range ) ) { 
    410412                                                        if( [_messages count] > i && [[_messages objectAtIndex:i] isKindOfClass:[JVChatMessage class]] ) { 
    411                                                                 msg = [_messages objectAtIndex:i]; 
     413                                                                msg = [[_messages objectAtIndex:i] retain]; 
    412414                                                        } 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]; 
    414416                                                                id classDesc = [NSClassDescription classDescriptionForClass:[self class]]; 
    415417                                                                [msg setObjectSpecifier:[[[NSUniqueIDSpecifier alloc] initWithContainerClassDescription:classDesc containerSpecifier:[self objectSpecifier] key:@"messages" uniqueID:[msg messageIdentifier]] autorelease]]; 
    416418                                                                [_messages replaceObjectAtIndex:i withObject:msg]; 
    417419                                                        } else if( [_messages count] == i ) { 
    418                                                                 msg = [JVChatMessage messageWithNode:subNode andTranscript:self]; 
     420                                                                msg = [[JVChatMessage allocWithZone:nil] _initWithNode:subNode andTranscript:self]; 
    419421                                                                id classDesc = [NSClassDescription classDescriptionForClass:[self class]]; 
    420422                                                                [msg setObjectSpecifier:[[[NSUniqueIDSpecifier alloc] initWithContainerClassDescription:classDesc containerSpecifier:[self objectSpecifier] key:@"messages" uniqueID:[msg messageIdentifier]] autorelease]]; 
     
    422424                                                        } else continue; 
    423425                                                        if( msg ) [ret addObject:msg]; 
     426                                                        [msg release]; 
    424427                                                } 
    425428 
     
    431434 
    432435        done: 
    433                 return [NSArray arrayWithArray:ret]; 
     436                return [ret autorelease]; 
    434437        } 
    435438} 
     
    471474                } while( node && ( node = node -> next ) ); 
    472475 
    473                 return ( foundNode ? [JVChatMessage messageWithNode:foundNode andTranscript:self] : nil ); 
     476                return ( foundNode ? [[[JVChatMessage allocWithZone:nil] _initWithNode:foundNode andTranscript:self] autorelease] : nil ); 
    474477        } 
    475478} 
     
    486489                do { 
    487490                        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]; 
    489492                                if( msg ) [results addObject:msg]; 
     493                                [msg release]; 
    490494                        } 
    491495                } while( node && ( node = node -> next ) ); 
    492496 
    493                 return [NSArray arrayWithArray:results]
     497                return results
    494498        } 
    495499 
     
    514518                } while( node && ( node = node -> prev ) ); 
    515519 
    516                 return ( foundNode ? [JVChatMessage messageWithNode:foundNode andTranscript:self] : nil ); 
     520                return ( foundNode ? [[[JVChatMessage allocWithZone:nil] _initWithNode:foundNode andTranscript:self] autorelease] : nil ); 
    517521        } 
    518522} 
     
    640644                _requiresNewEnvelope = NO; 
    641645 
    642                 return [JVChatMessage messageWithNode:child andTranscript:self]; 
     646                return [[[JVChatMessage allocWithZone:nil] _initWithNode:child andTranscript:self] autorelease]; 
    643647        } 
    644648} 
     
    651655        NSEnumerator *enumerator = [messages objectEnumerator]; 
    652656        JVChatMessage *message = nil; 
    653         NSMutableArray *ret = [NSMutableArray arrayWithCapacity:[messages count]]; 
     657        NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:[messages count]]; 
    654658 
    655659        if( forceEnvelope ) _requiresNewEnvelope = YES; 
     
    663667        } 
    664668 
    665         return [NSArray arrayWithArray:ret]; 
     669        return [ret autorelease]; 
    666670} 
    667671 
     
    677681        @synchronized( self ) { 
    678682                unsigned long i = 0; 
    679                 NSMutableArray *ret = [NSMutableArray arrayWithCapacity:( range.length - range.location )]; 
     683                NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:range.length]; 
    680684 
    681685                xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; 
     
    692696 
    693697        done: 
    694                 return [NSArray arrayWithArray:ret]; 
     698                return [ret autorelease]; 
    695699        } 
    696700} 
     
    738742        @synchronized( self ) { 
    739743                unsigned long i = 0; 
    740                 NSMutableArray *ret = [NSMutableArray arrayWithCapacity:( range.length - range.location )]; 
     744                NSMutableArray *ret = [[NSMutableArray allocWithZone:nil] initWithCapacity:range.length]; 
    741745 
    742746                xmlNode *node = xmlDocGetRootElement( _xmlLog ) -> children; 
     
    753757 
    754758        done: 
    755                 return [NSArray arrayWithArray:ret]; 
     759                return [ret autorelease]; 
    756760        } 
    757761} 
     
    11521156        } 
    11531157} 
     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} 
    11541170@end 
    11551171 
     
    12541270} 
    12551271@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"