📄 baseimcontainer.mm
字号:
name:kHistoryDidSelectedNotificationName object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:kCustomFaceDidReceivedNotificationName object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:kCustomFaceFailedToReceiveNotificationName object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:kCustomFaceDidSentNotificationName object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:kCustomFaceListFailedToSendNotificationName object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:kIMContainerAttachedToWindowNotificationName object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:kModelMessageCountChangedNotificationName object:nil]; if(m_faceSelector) [m_faceSelector close]; if(m_data) [m_data release]; if(m_winFacePreview) { [m_winFacePreview close]; [m_winFacePreview release]; } [m_objectController release]; [m_actionIds release]; [m_faceList release]; [m_history release]; [m_faceWaitingList release]; [m_faceSendingList release]; [m_myHintAttributes release]; [m_otherHintAttributes release]; [m_errorHintAttributes release]; [m_formatter release]; [m_obj release]; [m_mainWindowController release]; [super dealloc];}- (void)awakeFromNib { // text [m_txtOutput customizeInitialization:[[m_mainWindowController me] QQ]]; [m_txtInput customizeInitialization:[[m_mainWindowController me] QQ]]; [m_txtOutput setUsesFontPanel:NO]; [m_txtInput setAllowMultiFont:NO]; [m_txtInput setTextContainerInset:NSMakeSize(0, 2)]; [m_txtOutput setTextContainerInset:NSMakeSize(0, 2)];}- (BOOL)isEqual:(id)anObject { if([self class] == [anObject class] && [m_obj isEqual:[anObject model]]) return YES; else return NO;}- (id)copyWithZone:(NSZone *)zone { return [self retain];}#pragma mark -#pragma mark helper- (void)handleWindowWillClose:(NSNotification*)notification { if(m_faceSelector) { if([notification object] == [m_faceSelector window]) { m_faceSelector = nil; } }}- (void)appendMessageHint:(NSString*)nick date:(NSDate*)date attributes:(NSDictionary*)attributes { [self appendMessageHint:m_txtOutput nick:nick date:date attributes:attributes];}- (void)appendMessageHint:(QQTextView*)textView nick:(NSString*)nick date:(NSDate*)date attributes:(NSDictionary*)attributes { NSString* hint = [NSString stringWithFormat:@"\n%@ %@\n", nick, [m_formatter stringFromDate:date]]; NSAttributedString* string = [[NSAttributedString alloc] initWithString:hint attributes:([textView allowMultiFont] ? attributes : [textView typingAttributes])]; [[textView textStorage] appendAttributedString:string]; [string release];}- (void)appendPacket:(InPacket*)inPacket { [self appendPacket:m_txtOutput packet:inPacket];}- (void)appendPacket:(QQTextView*)textView packet:(InPacket*)inPacket {}- (void)appendMessage:(NSString*)nick data:(NSData*)data style:(FontStyle*)style date:(NSDate*)date customFaces:(CustomFaceList*)faceList { [self appendMessage:m_txtOutput nick:nick data:data style:style date:date customFaces:faceList];}- (void)appendMessage:(QQTextView*)textView nick:(NSString*)nick data:(NSData*)data style:(FontStyle*)style date:(NSDate*)date customFaces:(CustomFaceList*)faceList { // create font attributes NSMutableDictionary* attributes = nil; if([textView allowMultiFont]) { attributes = [NSMutableDictionary dictionary]; NSFont* font = [FontTool fontWithStyle:style]; [attributes setObject:font forKey:NSFontAttributeName]; if([style underline]) [attributes setObject:[NSNumber numberWithBool:YES] forKey:NSUnderlineStyleAttributeName]; [attributes setObject:[style fontColor] forKey:NSForegroundColorAttributeName]; } else attributes = (NSMutableDictionary*)[textView typingAttributes]; // append hint [self appendMessageHint:textView nick:nick date:date attributes:m_otherHintAttributes]; // the tag we are concerned static char tags[] = { kQQTagDefaultFace, kQQTagCustomFace }; // search tag, append message and images int cfIndex = -1; int from = 0; int length = [data length]; const char* bytes = (const char*)[data bytes]; for(int i = [data indexOfBytes:tags length:2 from:from]; i != -1; i = [data indexOfBytes:tags length:2 from:from]) { // append message fragment if(i - from > 0) { NSData* tmp = [NSData dataWithBytes:(bytes + from) length:(i - from)]; NSString* string = [ByteTool getString:tmp]; NSAttributedString* attrString = [[NSAttributedString alloc] initWithString:string attributes:attributes]; [[textView textStorage] appendAttributedString:attrString]; [attrString release]; } // check face tag switch(bytes[i]) { case kQQTagDefaultFace: // append default face [textView appendDefaultFace:[DefaultFace code2index:(bytes[i + 1] & 0xFF)]]; // adjust from from = i + 2; break; case kQQTagCustomFace: // get face index cfIndex++; // if face list is not nil, get face or show a sending image // if it's nil, bypass the face if(faceList) { // get face CustomFace* face = [faceList face:cfIndex includeReference:YES]; int length = [face length]; if([face isReference]) face = [faceList face:[face faceIndex]]; // hope not null if(face == nil) from = i + 1; else { FaceManager* fm = [m_mainWindowController faceManager]; NSString* md5 = [[face filename] stringByDeletingPathExtension]; if([fm hasFace:md5]) { // get face object Face* faceModel = [fm face:md5]; // get face group FaceGroup* group = [fm group:[faceModel groupIndex]]; NSAssert(group != nil, @"Face group shouldn't be nil"); // append custom face [textView appendCustomFace:kFaceTypeCustomFace md5:md5 path:[FileTool getCustomFacePath:[[m_mainWindowController me] QQ] group:[group name] file:[face filename]] received:NO]; } else if([fm hasReceivedFace:[face filename]]) { // append received face [textView appendCustomFace:kFaceTypeCustomFace md5:md5 path:[FileTool getReceivedCustomFacePath:[[m_mainWindowController me] QQ] file:[face filename]] received:YES]; } else { if(textView == m_txtInput) { // // in input, means user is browsing history // NSString* path = [[NSBundle mainBundle] pathForImageResource:kImageNotFound]; [textView appendCustomFace:kFaceTypePicture md5:nil path:path received:NO]; } else if(textView == m_txtOutput) { // // in output, means we are receiving faces! // NSString* path = [[NSBundle mainBundle] pathForImageResource:kImageReceivingImage]; NSRange range = [textView appendCustomFace:kFaceTypePicture md5:nil path:path received:YES]; // put current face to waiting list [m_faceWaitingList setObject:[NSNumber numberWithInt:range.location] forKey:[face filename]]; } } // adjust from from = i + length; } } else { from = i + 1; } break; } } if(from < length) { // append message fragment NSData* tmp = [NSData dataWithBytes:(bytes + from) length:(length - from)]; NSString* string = [ByteTool getString:tmp]; NSAttributedString* attrString = [[NSAttributedString alloc] initWithString:string attributes:attributes]; [[textView textStorage] appendAttributedString:attrString]; [attrString release]; } // make message visible [textView scrollRangeToVisible:NSMakeRange([[textView textStorage] length], 0)];}- (void)createPreviewWindow { if(m_winFacePreview == nil) { // create window m_winFacePreview = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 128, 150) styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES]; [m_winFacePreview setReleasedWhenClosed:NO]; [m_winFacePreview setLevel:NSScreenSaverWindowLevel]; // create image view m_ivPreview = [[[NSImageView alloc] initWithFrame:NSMakeRect(0, 22, 128, 128)] autorelease]; [m_ivPreview setImageFrameStyle:NSImageFramePhoto]; [m_ivPreview setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; // add to window [[m_winFacePreview contentView] addSubview:m_ivPreview]; // create shortcut text m_txtShortcut = [[[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 128, 22)] autorelease]; [m_txtShortcut setAutoresizingMask:(NSViewWidthSizable | NSViewMaxYMargin)]; [m_txtShortcut setAlignment:NSCenterTextAlignment]; [m_txtShortcut setEditable:NO]; [m_txtShortcut setBezeled:NO]; [m_txtShortcut setDrawsBackground:NO]; [[m_winFacePreview contentView] addSubview:m_txtShortcut]; }}- (void)showPreviewWindow { [self createPreviewWindow]; NSRect frame = [[m_faceSelector window] frame]; NSSize previewSize = [m_winFacePreview frame].size; frame.origin.x -= previewSize.width; frame.origin.y += frame.size.height - previewSize.height; frame.size = previewSize; [m_winFacePreview setFrame:frame display:NO]; [m_winFacePreview orderFront:self];}- (void)sendNextMessage { // check queue if([m_sendQueue count] == 0) { m_sending = NO; return; } // get next message NSAttributedString* message = [m_sendQueue objectAtIndex:0]; // generate font style FontStyle* style = [FontTool chatFontStyleWithPreference:[[m_mainWindowController me] QQ]]; // if sending, check fragment count if(m_sending) { if(m_fragmentCount > 1 && m_nextFragmentIndex < m_fragmentCount) { // // has more fragment need to be sent // // get data if(m_data) { int length = MIN(kQQMaxMessageFragmentLength, [m_data length] - m_nextFragmentIndex * kQQMaxMessageFragmentLength); NSData* messageData = [NSData dataWithBytes:(((const char*)[m_data bytes]) + m_nextFragmentIndex * kQQMaxMessageFragmentLength) length:length]; m_waitingSequence = [self doSend:messageData style:style fragmentCount:m_fragmentCount fragmentIndex:m_nextFragmentIndex]; m_nextFragmentIndex++; return; } } } else m_sending = YES; // // if program executes to here, means previous message is not long message // so we go on next // // release old data if(m_data) { [m_data release]; m_data = nil; } // get custom face list if(m_faceList) { [m_faceList release]; m_faceList = nil; } m_faceList = [TextTool getCustomFaceList:message owner:[[self owner] intValue] faceManager:[m_mainWindowController faceManager]]; [m_faceList retain]; // check face count, if 0, following normal process if([m_faceList count] == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -