Changeset 3540

Show
Ignore:
Timestamp:
01/19/06 17:13:55 (3 years ago)
Author:
morris
Message:

More cleanup, cancelling connections and reconnecting seems to work now

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • WiredClient/trunk/English.lproj/Localizable.strings

    r3420 r3540  
    77/* Chat topic set by (nick, time) */ 
    88"%@ %C %@" = "%1$@ %2$C %3$@"; 
    9  
    10 /* Server disconnected message (server) */ 
    11 "%@ connection lost" = "%@ connection lost"; 
    12  
    13 /* Server reconnected message (server) */ 
    14 "%@ connection re-established" = "%@ connection re-established"; 
    159 
    1610/* Stats message */ 
     
    5852"%@,\nsince %@" = "%1$@,\nsince %2$@"; 
    5953 
    60 /* Certificate (type, size, hostname) */ 
    61 "%@/%d bits, %s" = "%1$@/%2$d bits, %3$s"; 
    62  
    6354/* Chat message, Wired style (nick, message) */ 
    6455"%@: %@" = "%1$@: %2$@"; 
     
    7869"%llu %@" = "%1$llu %2$@"; 
    7970 
    80 /* Cipher (type, size) */ 
    81 "%s/%d bits" = "%1$s/%2$d bits"; 
    82  
    8371/* Dock status (connections, 'connection(s)') */ 
    8472"%u %@" = "%1$u %2$@"; 
     
    9381"Account Editor" = "Account Editor"; 
    9482 
    95 /* Error */ 
     83/* Wired Protocol error 514 title */ 
    9684"Account Exists" = "Account Exists"; 
    9785 
    98 /* Error */ 
     86/* Wired Protocol error 513 title */ 
    9987"Account Not found" = "Account Not found"; 
    10088 
     
    10694"Add" = "Add"; 
    10795 
    108 /* Error */ 
    109 "An internal server error occured. Please contact the server administrator." = "An internal server error occured. Please contact the server administrator."; 
    110  
    111 /* Anonymous certificate */ 
    112 "Anonymous" = "Anonymous"; 
    113  
    114 /* Error */ 
    115 "Application Error" = "Application Error"; 
     96/* Wired Protocol unknown error description (code, message) */ 
     97"An unknown server error occured. The message we got back was: \"%d %@\"." = "An unknown server error occured. The message we got back was: \"%1$d %2$@\"."; 
    11698 
    11799/* Clear messages dialog title */ 
     
    132114"Are you sure you want to disconnect?" = "Are you sure you want to disconnect?"; 
    133115 
    134 /* Error */ 
     116/* Wired Protocol error 511 title */ 
    135117"Banned" = "Banned"; 
    136118 
     
    140122/* Cipher string */ 
    141123"bits" = "bits"; 
     124 
     125/* Description of Bonjour tracker (servers, 'server(s)' */ 
     126"Bonjour local service discovery %C %d %@" = "Bonjour local service discovery %1$C %2$d %3$@"; 
    142127 
    143128/* Bookmarks toolbar item */ 
     
    154139"Cancel" = "Cancel"; 
    155140 
    156 /* Error */ 
     141/* Wired Protocol error 515 title */ 
    157142"Cannot Be Disconnected" = "Cannot Be Disconnected"; 
    158143 
     
    179164"Chat" = "Chat"; 
    180165 
    181 /* Error */ 
     166/* Error 
     167   Wired Protocol error 522 title */ 
    182168"Checksum Mismatch" = "Checksum Mismatch"; 
    183169 
     
    186172"Clear" = "Clear"; 
    187173 
    188 /* Error */ 
     174/* Wired Protocol error 512 title */ 
    189175"Client Not Found" = "Client Not Found"; 
    190176 
     
    192178"connection" = "connection"; 
    193179 
    194 /* Error */ 
    195 "Connection Refused" = "Connection Refused"; 
    196  
    197180/* Connection plural */ 
    198181"connections" = "connections"; 
     
    204187"Conversations" = "Conversations"; 
    205188 
    206 /* Error (host) */ 
    207 "Could not connect to \"%@\"." = "Could not connect to \"%@\"."; 
    208  
    209189/* Error (path) */ 
    210190"Could not create the file \"%@\"." = "Could not create the file \"%@\"."; 
    211191 
    212 /* Error */ 
     192/* Wired Protocol error 521 description */ 
    213193"Could not create the file or directory, it already exists." = "Could not create the file or directory, it already exists."; 
    214194 
    215 /* Error */ 
     195/* Wired Protocol error 513 description */ 
    216196"Could not find the account you referred to. Perhaps someone deleted it." = "Could not find the account you referred to. Perhaps someone deleted it."; 
    217197 
    218 /* Error */ 
     198/* Wired Protocol error 512 description */ 
    219199"Could not find the client you referred to. Perhaps that client left before the command could be completed." = "Could not find the client you referred to. Perhaps that client left before the command could be completed."; 
    220200 
    221 /* Error */ 
     201/* Wired Protocol error 520 description */ 
    222202"Could not find the file or folder you referred to. Perhaps someone deleted it." = "Could not find the file or folder you referred to. Perhaps someone deleted it."; 
    223203 
    224 /* Error */ 
    225 "Could not login, the user name and/or password you supplied was incorrect." = "Could not login, the user name and/or password you supplied was incorrect."; 
    226  
    227 /* Error */ 
     204/* Wired Protocol error 510 description */ 
     205"Could not login, the user name and/or password you supplied was rejected." = "Could not login, the user name and/or password you supplied was rejected."; 
     206 
     207/* Wired Protocol error 511 description */ 
    228208"Could not login, you are banned from this server." = "Could not login, you are banned from this server."; 
    229209 
     
    231211"Could not open the file \"%@\"." = "Could not open the file \"%@\"."; 
    232212 
    233 /* Error (host) */ 
    234 "Could not resolve \"%@\"." = "Could not resolve \"%@\"."; 
    235  
    236 /* Error (host, error) */ 
    237 "Could not resolve \"%@\". Got the following system error: %@." = "Could not resolve \"%1$@\". Got the following system error: %2$@."; 
    238  
    239213/* Error (path) */ 
    240214"Could not resume transfer of \"%@\", the checksums do not match." = "Could not resume transfer of \"%@\", the checksums do not match."; 
    241215 
    242 /* Error */ 
     216/* Wired Protocol error 523 description */ 
    243217"Could not start a transfer, the limit has been exceeded." = "Could not start a transfer, the limit has been exceeded."; 
    244218 
    245 /* Error */ 
     219/* Wired Protocol error 522 description */ 
    246220"Could not start an upload, the checksums do not match." = "Could not start an upload, the checksums do not match."; 
    247221 
     
    279253"File Exists" = "File Exists"; 
    280254 
    281 /* Error */ 
     255/* Wired Protocol error 521 title */ 
    282256"File or Folder Exists" = "File or Folder Exists"; 
    283257 
    284 /* Error */ 
     258/* Wired Protocol error 520 title */ 
    285259"File or Folder Not Found" = "File or Folder Not Found"; 
    286260 
     
    302276/* General toolbar item */ 
    303277"General" = "General"; 
    304  
    305 /* Error (error) */ 
    306 "Got the following application error: %@." = "Got the following application error: %@."; 
    307  
    308 /* Error (error) */ 
    309 "Got the following server error: %@." = "Got the following server error: %@."; 
    310  
    311 /* Error (error) */ 
    312 "Got the following SSL error: %@." = "Got the following SSL error: %@."; 
    313  
    314 /* Error (error) */ 
    315 "Got the following system error: %@." = "Got the following system error: %@."; 
    316278 
    317279/* Group singular */ 
     
    346308"Join to open a separate private chat with %@." = "Join to open a separate private chat with %@."; 
    347309 
    348 /* Description of server via Rendezvous tracker */ 
    349 "Local server via Rendezvous" = "Local server via Rendezvous"; 
     310/* Description of server via Bonjour tracker */ 
     311"Local server via Bonjour" = "Local server via Bonjour"; 
    350312 
    351313/* Log window title */ 
    352314"Log" = "Log"; 
    353315 
    354 /* Error */ 
     316/* Wired Protocol error 510 title */ 
    355317"Login Failed" = "Login Failed"; 
    356318 
     
    372334"No" = "No"; 
    373335 
    374 /* Button title */ 
    375 "OK" = "OK"; 
    376  
    377336/* Error */ 
    378337"Open Failed" = "Open Failed"; 
    379338 
    380 /* Error */ 
     339/* Wired Protocol error 516 title */ 
    381340"Permission Denied" = "Permission Denied"; 
    382341 
     
    384343"Private Chat" = "Private Chat"; 
    385344 
    386 /* Error */ 
     345/* Error 
     346   WCWiredClientProtocolMismatch title */ 
    387347"Protocol Mismatch" = "Protocol Mismatch"; 
    388348 
    389 /* Error */ 
     349/* Wired Protocol error 523 title */ 
    390350"Queue Limit Exceeded" = "Queue Limit Exceeded"; 
    391351 
     
    395355/* Transfer queued (position) */ 
    396356"Queued at position %u" = "Queued at position %u"; 
    397  
    398 /* Description of Rendezvous tracker (servers, 'server(s)' */ 
    399 "Rendezvous local service discovery %C %d %@" = "Rendezvous local service discovery %1$C %2$d %3$@"; 
    400  
    401 /* Error */ 
    402 "Resolve Failed" = "Resolve Failed"; 
    403357 
    404358/* Account Editor button title */ 
     
    415369"server" = "server"; 
    416370 
    417 /* Server disconnected error dialog title */ 
     371/* WCWiredClientServerDisconnected title */ 
    418372"Server Disconnected" = "Server Disconnected"; 
    419373 
    420 /* Error */ 
     374/* Wired Protocol error 501 title 
     375   Wired Protocol error 500 title 
     376   Wired Protocol error 502 title 
     377   Wired Protocol error 503 title 
     378   Wired Protocol unknown error title */ 
    421379"Server Error" = "Server Error"; 
    422380 
     
    430388"Sounds" = "Sounds"; 
    431389 
    432 /* Error */ 
    433 "SSL Error" = "SSL Error"; 
    434  
    435390/* About box title */ 
    436391"Stats" = "Stats"; 
     
    442397"Stopping" = "Stopping"; 
    443398 
    444 /* Error */ 
    445 "System Error" = "System Error"; 
    446  
    447 /* Error */ 
     399/* Wired Protocol error 514 description */ 
    448400"The account you tried to create already exists on the server." = "The account you tried to create already exists on the server."; 
    449401 
    450 /* Error */ 
    451 "The client you tried to disconnect is proteceted. You cannot disconnect that client." = "The client you tried to disconnect is proteceted. You cannot disconnect that client."; 
    452  
    453 /* Error */ 
     402/* Wired Protocol error 515 description */ 
     403"The client you tried to disconnect is protected." = "The client you tried to disconnect is protected."; 
     404 
     405/* Wired Protocol error 516 description */ 
    454406"The command could not be completed due to insufficient privileges." = "The command could not be completed due to insufficient privileges."; 
    455407 
     
    460412"The folder \"%@\" already exists." = "The folder \"%@\" already exists."; 
    461413 
    462 /* Server disconnected error dialog description */ 
     414/* Wired Protocol error 503 description */ 
     415"The server could not parse a command. This is probably because of an protocol incompatibility between the client and the server." = "The server could not parse a command. This is probably because of an protocol incompatibility between the client and the server."; 
     416 
     417/* Wired Protocol error 501 description */ 
     418"The server did not recognize a command. This is probably because of an protocol incompatibility between the client and the server." = "The server did not recognize a command. This is probably because of an protocol incompatibility between the client and the server."; 
     419 
     420/* Wired Protocol error 500 description */ 
     421"The server failed to process a command. The server administrator can check the log for more information." = "The server failed to process a command. The server administrator can check the log for more information."; 
     422 
     423/* Wired Protocol error 502 description */ 
     424"The server has not implemented a command. This is probably because of an protocol incompatibility between the client and the server." = "The server has not implemented a command. This is probably because of an protocol incompatibility between the client and the server."; 
     425 
     426/* WCWiredClientServerDisconnected description */ 
    463427"The server has unexpectedly disconnected." = "The server has unexpectedly disconnected."; 
    464428 
     
    472436"This cannot be undone." = "This cannot be undone."; 
    473437 
    474 /* Error */ 
     438/* WCWiredClientProtocolMismatch description 
     439   Error */ 
    475440"This server uses a newer protocol version than this client supports. Protocol errors may occur during the connection." = "This server uses a newer protocol version than this client supports. Protocol errors may occur during the connection."; 
    476441 
     
    493458/* User list menu title */ 
    494459"Unignore" = "Unignore"; 
    495  
    496 /* Unknown certificate */ 
    497 "Unknown" = "Unknown"; 
    498460 
    499461/* Untitled bookmark 
  • WiredClient/trunk/English.lproj/MainMenu.nib/classes.nib

    r3525 r3540  
    4343                bookmark = id;  
    4444                connect = id;  
     45                hideConnection = id;  
     46                log = id;  
     47                nextConnection = id;  
     48                preferences = id;  
     49                previousConnection = id;  
     50                showDock = id;  
     51                showTrackers = id;  
     52            };  
     53            CLASS = WCApplicationController;  
     54            LANGUAGE = ObjC;  
     55            OUTLETS = { 
     56                "_bookmarksMenu" = NSMenu;  
     57                "_debugMenu" = NSMenu;  
     58                "_deleteMenuItem" = NSMenuItem;  
     59                "_disconnectMenuItem" = NSMenuItem;  
     60            };  
     61            SUPERCLASS = WIObject;  
     62        },  
     63        { 
     64            ACTIONS = { 
     65                about = id;  
     66                bookmark = id;  
     67                connect = id;  
    4568                connectToServer = id;  
    4669                hideConnection = id;  
     
    7194            SUPERCLASS = NSApplication;  
    7295        },  
     96        {CLASS = WIObject; LANGUAGE = ObjC; SUPERCLASS = NSObject; },  
    7397        { 
    7498            ACTIONS = {showViewOptions = id; };  
  • WiredClient/trunk/English.lproj/MainMenu.nib/info.nib

    r3525 r3540  
    88        <dict> 
    99                <key>29</key> 
    10                 <string>266 875 614 44 0 0 1280 1002 </string> 
     10                <string>522 1036 614 44 0 0 1920 1178 </string> 
    1111        </dict> 
    1212        <key>IBFramework Version</key> 
  • WiredClient/trunk/English.lproj/Messages.nib/info.nib

    r3427 r3540  
    1414        </array> 
    1515        <key>IBSystem Version</key> 
    16         <string>8F46</string> 
     16        <string>8G32</string> 
    1717</dict> 
    1818</plist> 
  • WiredClient/trunk/WCAboutWindow.m

    r3413 r3540  
    2020 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
    2121 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
    22        * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
     22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
    2323 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
    2424 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
     
    2828 
    2929#import "WCAboutWindow.h" 
    30 #import "WCMain.h" 
    3130 
    3231@implementation WCAboutWindow 
     
    133132 
    134133        // --- subscribe to these 
    135         [[WCMain main] addObserver:self 
    136                                           selector:@selector(applicationDidChangeActive:) 
    137                                                   name:WIApplicationDidChangeActiveNotification]; 
     134        [[NSNotificationCenter defaultCenter] 
     135                addObserver:self 
     136                   selector:@selector(applicationDidChangeActive:) 
     137                           name:WIApplicationDidChangeActiveNotification]; 
    138138 
    139139        return self; 
  • WiredClient/trunk/WCAccountEditor.m

    r3413 r3540  
    3030#import "WCAccountEditor.h" 
    3131#import "WCAccounts.h" 
    32 #import "WCMain.h" 
    3332 
    3433@implementation WCAccountEditor 
  • WiredClient/trunk/WCChat.h

    r3413 r3540  
    8585- (NSArray *)users; 
    8686- (NSArray *)nicks; 
    87 - (WCUser *)userAtIndex:(int)index; 
     87- (WCUser *)userAtIndex:(unsigned int)index; 
    8888- (WCUser *)userWithUserID:(unsigned int)uid; 
    8989- (unsigned int)chatID; 
  • WiredClient/trunk/WCChat.m

    r3503 r3540  
    3030#import "WCAccountEditor.h"  
    3131#import "WCAccounts.h"  
     32#import "WCApplicationController.h"  
    3233#import "WCChat.h" 
    33 #import "WCMain.h" 
    3434#import "WCMessage.h" 
    3535#import "WCMessages.h" 
     
    5757- (void)_printActionChat:(NSString *)chat by:(WCUser *)user; 
    5858 
     59- (NSArray *)_commands; 
    5960- (BOOL)_runCommand:(NSString *)command; 
     61 
     62- (NSString *)_completeString:(NSString *)string; 
    6063 
    6164@end 
     
    263266#pragma mark - 
    264267 
     268- (NSArray *)_commands { 
     269        return [NSArray arrayWithObjects: 
     270                @"/me", 
     271                @"/exec", 
     272                @"/nick", 
     273                @"/status", 
     274                @"/stats", 
     275                @"/clear", 
     276                @"/topic", 
     277                @"/broadcast", 
     278                NULL]; 
     279} 
     280 
     281 
     282 
    265283- (BOOL)_runCommand:(NSString *)string { 
    266284        NSString        *command, *argument; 
     
    285303                                                  withArgument:argument]; 
    286304                 
    287                 [WCStats addUnsignedLongLong:[argument length] forKey:WCStatsChat]; 
     305                [[WCStats stats] addUnsignedLongLong:[argument length] forKey:WCStatsChat]; 
    288306                 
    289307                return YES; 
     
    336354                                                          withArgument:output]; 
    337355 
    338                         [WCStats addUnsignedLongLong:[output length] forKey:WCStatsChat]; 
     356                        [[WCStats stats] addUnsignedLongLong:[output length] forKey:WCStatsChat]; 
    339357                } 
    340358                 
     
    357375                [[self connection] sendCommand:WCSayCommand 
    358376                                                  withArgument:[NSSWF:@"%u", [self chatID]] 
    359                                                   withArgument:[[WCStats stats] string]]; 
     377                                                  withArgument:[[WCStats stats] stringValue]]; 
    360378                 
    361379                return YES; 
     
    389407} 
    390408 
     409 
     410 
     411#pragma mark - 
     412 
     413- (NSString *)_completeString:(NSString *)string { 
     414        NSEnumerator    *enumerator; 
     415        NSArray                 *nicks, *commands, *set, *matches; 
     416        NSString                *p, *prefix; 
     417        unsigned int    i, count; 
     418         
     419        nicks = [self nicks]; 
     420        commands = [self _commands]; 
     421        enumerator = [[NSArray arrayWithObjects:nicks, commands, NULL] objectEnumerator]; 
     422         
     423        while((set = [enumerator nextObject])) { 
     424                matches = [set stringsMatchingString:string options:NSCaseInsensitiveSearch]; 
     425                         
     426                if([matches count] == 1) { 
     427                        string = [matches objectAtIndex:0]; 
     428                         
     429                        if(set == nicks) { 
     430                                string = [string stringByAppendingString: 
     431                                        [WCSettings objectForKey:WCTabCompleteNicksString]]; 
     432                        } 
     433                        else if(set == commands) { 
     434                                string = [string stringByAppendingString:@" "]; 
     435                        } 
     436                         
     437                        return string; 
     438                } 
     439                else if([matches count] > 1) { 
     440                        prefix = p = @""; 
     441                        count = [matches count] - 1; 
     442                         
     443                        for(i = 0; i < count; i++) { 
     444                                p = [[matches objectAtIndex:i] commonPrefixWithString:[matches objectAtIndex:i + 1] 
     445                                                                                                                          options:NSCaseInsensitiveSearch]; 
     446                                 
     447                                if([p length] > [prefix length]) 
     448                                        prefix = p; 
     449                        } 
     450                         
     451                        if([prefix length] > 0) 
     452                                return prefix; 
     453                } 
     454        } 
     455                         
     456        return string; 
     457} 
     458 
    391459@end 
    392460 
     
    414482        _shownUsers             = [[NSMutableArray alloc] init]; 
    415483 
    416         [[WCMain main] addObserver:self 
    417                                           selector:@selector(preferencesDidChange:) 
    418                                                   name:WCPreferencesDidChange]; 
    419  
    420         [[WCMain main] addObserver:self 
    421                                           selector:@selector(dateDidChange:) 
    422                                                   name:WCDateDidChange]; 
     484        [[NSNotificationCenter defaultCenter] 
     485                addObserver:self 
     486                   selector:@selector(preferencesDidChange:) 
     487                           name:WCPreferencesDidChange]; 
     488 
     489        [[NSNotificationCenter defaultCenter] 
     490                addObserver:self 
     491                   selector:@selector(dateDidChange:) 
     492                           name:WCDateDidChange]; 
    423493 
    424494        [[self connection] addObserver:self 
     
    472542 
    473543- (void)dealloc { 
    474         [[WCMain main] removeObserver:self]; 
     544        [[NSNotificationCenter defaultCenter] removeObserver:self]; 
    475545         
    476546        [_users release]; 
     
    529599 
    530600 
    531 - (void)preferencesDidChange:(NSNotification *)notification { 
    532         [self _update]; 
    533  
    534         [_chatOutputTextView scrollToBottom]; 
    535 
    536  
    537  
    538  
    539 - (void)dateDidChange:(NSNotification *)notification { 
    540         [self _updateTopic]; 
    541 
    542  
    543  
    544  
    545 /*- (void)chatConnectionHasClosed:(NSNotification *)notification { 
    546         [self printEvent:[NSSWF:NSLS(@"%@ connection lost", @"Server disconnected message (server)"), 
    547                 [[self connection] name]]]; 
    548 
    549  
    550  
    551  
    552 - (void)chatConnectionHasReattached:(NSNotification *)notification { 
     601- (void)serverConnectionWillReconnect:(NSNotification *)notification { 
    553602        [_users removeAllObjects]; 
    554603        [_shownUsers removeAllObjects]; 
    555604        [_userListTableView reloadData]; 
    556          
    557         [self printEvent:[NSSWF:NSLS(@"%@ connection re-established", @"Server reconnected message (server)"), 
    558                 [[self connection] name]]]; 
    559 }*/ 
     605
     606 
     607 
     608 
     609- (void)preferencesDidChange:(NSNotification *)notification { 
     610        [self _update]; 
     611 
     612        [_chatOutputTextView scrollToBottom]; 
     613
     614 
     615 
     616 
     617- (void)dateDidChange:(NSNotification *)notification { 
     618        [self _updateTopic]; 
     619
    560620 
    561621 
     
    10291089                                                          withArgument:string]; 
    10301090 
    1031                         [WCStats addUnsignedLongLong:[string UTF8StringLength] forKey:WCStatsChat]; 
     1091                        [[WCStats stats] addUnsignedLongLong:[string UTF8StringLength] forKey:WCStatsChat]; 
    10321092                } 
    10331093 
     
    10421102                        NSString                *p, *prefix; 
    10431103                        int                             i, count, options; 
     1104 
     1105                        [_chatInputTextView setString:[self _completeString:[_chatInputTextView string]]]; 
     1106                         
     1107                        return YES; 
    10441108 
    10451109                        options = NSCaseInsensitiveSearch; 
     
    12441308 
    12451309 
    1246 - (WCUser *)userAtIndex:(int)row
    1247         return [_shownUsers objectAtIndex:row]; 
     1310- (WCUser *)userAtIndex:(unsigned int)index
     1311        return [_shownUsers objectAtIndex:index]; 
    12481312} 
    12491313 
     
    12821346        [[self connection] sendCommand:WCSayCommand 
    12831347                                          withArgument:[NSSWF:@"%u", [self chatID]] 
    1284                                           withArgument:[[WCStats stats] string]]; 
     1348                                          withArgument:[[WCStats stats] stringValue]]; 
    12851349} 
    12861350 
     
    15081572 
    15091573@end 
    1510  
    1511  
    1512  
    1513 @implementation NSMutableAttributedString(WCStringFiltering) 
    1514  
    1515 - (void)filterWiredChat { 
    1516         static NSCharacterSet           *whitespaceSet, *nonwhitespaceSet, *nontimestampSet; 
    1517         NSMutableCharacterSet           *characterSet; 
    1518         NSEnumerator                            *enumerator; 
    1519         NSScanner                                       *scanner; 
    1520         NSMutableArray                          *highlightPatterns, *highlightStrings, *highlightColors; 
    1521         NSDictionary                            *highlight; 
    1522         NSString                                        *word, *chat; 
    1523         NSColor                                         *color, *eventsTextColor, *timestampEveryLineColor; 
    1524         NSRange                                         range, nickRange, patternRange; 
    1525         int                                                     i, style, highlightCount; 
    1526         BOOL                                            running = YES; 
    1527  
    1528         if(!whitespaceSet) { 
    1529                 whitespaceSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain]; 
    1530                 nonwhitespaceSet = [[whitespaceSet invertedSet] retain]; 
    1531                  
    1532                 characterSet = [[NSMutableCharacterSet decimalDigitCharacterSet] mutableCopy]; 
    1533                 [characterSet addCharactersInString:@":."]; 
    1534                 [characterSet invert]; 
    1535                 nontimestampSet = [characterSet copy]; 
    1536                 [characterSet release]; 
    1537         } 
    1538  
    1539         eventsTextColor = [WCSettings objectForKey:WCChatEventsColor]; 
    1540         timestampEveryLineColor = [WCSettings objectForKey:WCTimestampEveryLineColor]; 
    1541  
    1542         highlightPatterns = [NSMutableArray array]; 
    1543         highlightStrings = [NSMutableArray array]; 
    1544         highlightColors = [NSMutableArray array]; 
    1545         enumerator = [[WCSettings objectForKey:WCHighlights] objectEnumerator]; 
    1546          
    1547         while((highlight = [enumerator nextObject])) { 
    1548                 [highlightPatterns addObject:[highlight objectForKey:WCHighlightsPattern]]; 
    1549                 [highlightStrings addObject:[highlight objectForKey:WCHighlightsColor]]; 
    1550                 [highlightColors addObject:[NSNull null]]; 
    1551         } 
    1552          
    1553         highlightCount = [highlightPatterns count]; 
    1554          
    1555         scanner = [NSScanner scannerWithString:[self string]]; 
    1556         [scanner setCharactersToBeSkipped:NULL]; 
    1557  
    1558         while(running) { 
    1559                 // --- extract word 
    1560                 [scanner skipUpToCharactersFromSet:nonwhitespaceSet]; 
    1561                 range.location = [scanner scanLocation]; 
    1562                  
    1563                 if(![scanner scanUpToCharactersFromSet:whitespaceSet intoString:&word]) { 
    1564                         running = NO; 
    1565  
    1566                         continue; 
    1567                 } 
    1568                  
    1569                 range.length = [scanner scanLocation] - range.location; 
    1570                  
    1571                 // --- scan timestamps patterns 
    1572                 if([word rangeOfCharacterFromSet:nontimestampSet].location == NSNotFound || 
    1573                    [word isEqualToString:@"PM"] || [word isEqualToString:@"AM"]) { 
    1574                         [self addAttribute:NSForegroundColorAttributeName value:timestampEveryLineColor range:range]; 
    1575                          
    1576                         goto nextword; 
    1577                 } 
    1578                  
    1579                 // --- scan <<< >>> patterns 
    1580                 if([word isEqualToString:@"<<<"]) { 
    1581                         if([scanner scanUpToString:@">>>" intoString:NULL]) { 
    1582                                 range.length = [scanner scanLocation] - range.location + 3; 
    1583  
    1584                                 [self addAttribute:NSForegroundColorAttributeName value:eventsTextColor range:range]; 
    1585                                  
    1586                                 goto nextline; 
    1587                         } 
    1588                 } 
    1589                  
    1590                 // --- scan and skip action chat 
    1591                 if([word isEqualToString:@"*"] || [word isEqualToString:@"***"]) 
    1592                         goto nextline; 
    1593                  
    1594                 // --- scan nick name 
    1595                 nickRange = range; 
    1596                 style = [word hasPrefix:@"<"] ? WCChatStyleIRC : WCChatStyleWired; 
    1597                  
    1598                 if(style == WCChatStyleIRC) { 
    1599                         nickRange.location++; 
    1600                         nickRange.length--; 
    1601                 } 
    1602                  
    1603                 if(style == WCChatStyleWired && [word hasSuffix:@":"]) { 
    1604                         nickRange.length--; 
    1605  
    1606                         if(![scanner isAtEnd]) 
    1607                                 [scanner setScanLocation:[scanner scanLocation] + 1]; 
    1608                 } 
    1609                 else if(style == WCChatStyleIRC && [word hasSuffix:@">"]) { 
    1610                         nickRange.length--; 
    1611  
    1612                         if(![scanner isAtEnd]) 
    1613                                 [scanner setScanLocation:[scanner scanLocation] + 1]; 
    1614                 } 
    1615                 else { 
    1616                         [scanner scanUpToString:style == WCChatStyleWired ? @":" : @">" intoString:NULL]; 
    1617                          
    1618                         nickRange.length = [scanner scanLocation] - range.location; 
    1619  
    1620                         if(![scanner isAtEnd]) 
    1621                            [scanner setScanLocation:[scanner scanLocation] + 1]; 
    1622                 } 
    1623                  
    1624                 // --- scan rest of line 
    1625                 if([scanner scanUpToString:@"\n" intoString:&chat]) { 
    1626                         // --- scan chat line for highlight patterns 
    1627                         for(i = 0; i < highlightCount; i++) { 
    1628                                 patternRange = [chat rangeOfString:[highlightPatterns objectAtIndex:i] options:NSCaseInsensitiveSearch]; 
    1629                                  
    1630                                 if(patternRange.location != NSNotFound) { 
    1631                                         color = [highlightColors objectAtIndex:i]; 
    1632                                          
    1633                                         if(![color isKindOfClass:[NSColor class]]) { 
    1634                                                 color = NSColorFromString([highlightStrings objectAtIndex:i]); 
    1635                                                 [highlightColors replaceObjectAtIndex:i withObject:color]; 
    1636                                         } 
    1637                                          
    1638                                         [self addAttribute:NSForegroundColorAttributeName value:color range:nickRange]; 
    1639                                          
    1640                                         break; 
    1641                                 } 
    1642                         } 
    1643                 } 
    1644                  
    1645 nextword: 
    1646                 // --- scan next word 
    1647                 continue; 
    1648                  
    1649 nextline: 
    1650                 // --- scan and skip until newline 
    1651                 [scanner scanUpToString:@"\n" intoString:NULL]; 
    1652                 continue; 
    1653         } 
    1654 } 
    1655  
    1656  
    1657  
    1658 static BOOL _URLStringLooksInteresting(NSString *string) { 
    1659         if([string length] >= 8) { 
    1660                 if([string rangeOfString:@"://" options:NSLiteralSearch].location != NSNotFound) 
    1661                         return YES; 
    1662                  
    1663                 if([string rangeOfString:@"www." options:NSLiteralSearch].location != NSNotFound) 
    1664                         return YES; 
    1665                  
    1666                 if([string rangeOfString:@"wired." options:NSLiteralSearch].location != NSNotFound) 
    1667                         return YES; 
    1668         } 
    1669  
    1670         return NO; 
    1671 } 
    1672  
    1673  
    1674  
    1675 - (void)filterURLs { 
    1676         static NSCharacterSet   *whitespaceSet, *nonwhitespaceSet, *skipSet; 
    1677         static NSNumber                 *underlineNumber; 
    1678         NSScanner                               *scanner; 
    1679         NSString                                *word; 
    1680