/* copyright 2002 Alexander Malmberg */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ComposeWindowController.h" #include "main.h" #include "KeyWindow.h" #include "Pref_Posting.h" #include "Pref_MessageViewing.h" #include #include #include #include @implementation ComposeWindowController -(void) post: (id)sender { CWMessage *m=[[CWMessage alloc] init]; NSMutableDictionary *md; NSEnumerator *e; NSString *header,*value; NSData *d; if (state) { NSBeep(); return; } if (![[tf_subject stringValue] length] || ![[tf_newsgroups stringValue] length] || ![[tf_from stringValue] length]) { NSBeep(); return; } md=[msg_headers mutableCopy]; [md setObject: [tf_subject stringValue] forKey: @"Subject"]; [md setObject: [tf_newsgroups stringValue] forKey: @"Newsgroups"]; [md setObject: [tf_from stringValue] forKey: @"From"]; for (e=[md keyEnumerator];(header=[e nextObject]);) { value=[md objectForKey: header]; if ([header isEqualToString: @"From"]) { CWInternetAddress *ia=[[CWInternetAddress alloc] initWithString: value]; [m setFrom: ia]; DESTROY(ia); } else if ([header isEqualToString: @"Subject"]) { [m setSubject: value]; } else [m addHeader: header withValue: value]; } [m setContentType: @"text/plain"]; [m setContentTransferEncoding: PantomimeEncoding8bit]; [m setFormat: PantomimeFormatFlowed]; [m setContent: [text string]]; if(![Pref_MessageViewing defaultEncoding]) { [m setCharset: @"utf-8"]; } else { [m setCharset: [Pref_MessageViewing defaultEncoding]]; } state=1; d=[m dataValue]; { NSData *nd=[[[@"Newsgroups: " stringByAppendingString: [md objectForKey: @"Newsgroups"]] stringByAppendingString: @"\n"] dataUsingEncoding: NSASCIIStringEncoding]; nd=[nd mutableCopy]; [(NSMutableData *)nd appendData: d]; d=nd; AUTORELEASE(nd); } if ([md objectForKey: @"References"]) { NSData *nd=[[[@"References: " stringByAppendingString: [md objectForKey: @"References"]] stringByAppendingString: @"\n"] dataUsingEncoding: NSASCIIStringEncoding]; nd=[nd mutableCopy]; [(NSMutableData *)nd appendData: d]; d=nd; AUTORELEASE(nd); } /* TODO: this needs to be done in some better way */ [app_delegate postArticleFrom: self : [d bytes] : [d length]]; DESTROY(md); DESTROY(m); } -(void) postedArticle: (BOOL)success { if (!success) { state=0; NSBeep(); } else { state=2; [[self window] performClose: self]; } } -(void) windowWillClose: (NSNotification *)n { [self autorelease]; } -(void) dealloc { DESTROY(msg_headers); [super dealloc]; } - initWithHeaders: (NSDictionary *)headers content: (NSString *)content { NSWindow *win; win=[[KeyWindow alloc] initWithContentRect: NSMakeRect(100,100,550,500) styleMask: NSClosableWindowMask|NSTitledWindowMask|NSResizableWindowMask|NSMiniaturizableWindowMask backing: NSBackingStoreRetained defer: YES]; if (!(self=[super initWithWindow: win])) return nil; msg_headers=[headers copy]; state=0; { NSString *signature=[Pref_Posting postingSignature]; if (signature) { content=[[content stringByAppendingString: @"\n-- \n"] stringByAppendingString: signature]; } } { GSVbox *vbox; vbox=[[GSVbox alloc] init]; [vbox setDefaultMinYMargin: 4]; [vbox setBorder: 2]; { NSScrollView *sv; NSTextView *tv; sv=[[NSScrollView alloc] initWithFrame: NSMakeRect(0,0,1,1)]; [sv setHasVerticalScroller: YES]; [sv setHasHorizontalScroller: YES]; [sv setBorderType: NSBezelBorder]; [sv setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; text=tv=[[NSTextView alloc] initWithFrame: [[sv contentView] frame]]; [tv setHorizontallyResizable: NO]; [tv setVerticallyResizable: YES]; [tv setEditable: YES]; [[tv textContainer] setWidthTracksTextView: YES]; [[tv textContainer] setHeightTracksTextView: NO]; [[tv textContainer] setContainerSize: NSMakeSize(1e6,1e6)]; [tv setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; if (content) [tv setString: content]; [sv setDocumentView: tv]; [vbox addView: sv enablingYResizing: YES]; [sv release]; [tv release]; } [vbox addSeparator]; { GSHbox *hbox; NSButton *b; NSTextField *f; hbox=[[GSHbox alloc] init]; [hbox setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; [hbox setDefaultMinXMargin: 2]; f=[[NSTextField alloc] init]; [f setStringValue: _(@"Subject:")]; [f setEditable: NO]; [f setDrawsBackground: NO]; [f setBordered: NO]; [f setBezeled: NO]; [f setSelectable: NO]; [f sizeToFit]; [f setAutoresizingMask: 0]; [hbox addView: f enablingXResizing: NO]; DESTROY(f); tf_subject=f=[[NSTextField alloc] init]; [f setAutoresizingMask: NSViewWidthSizable]; [f sizeToFit]; [hbox addView: f enablingXResizing: YES]; DESTROY(f); [vbox addView: hbox enablingYResizing: NO]; DESTROY(hbox); hbox=[[GSHbox alloc] init]; [hbox setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; [hbox setDefaultMinXMargin: 2]; f=[[NSTextField alloc] init]; [f setStringValue: _(@"Newsgroups (separate with commas):")]; [f setEditable: NO]; [f setDrawsBackground: NO]; [f setBordered: NO]; [f setBezeled: NO]; [f setSelectable: NO]; [f sizeToFit]; [f setAutoresizingMask: 0]; [hbox addView: f enablingXResizing: NO]; DESTROY(f); tf_newsgroups=f=[[NSTextField alloc] init]; [f setAutoresizingMask: NSViewWidthSizable]; [f sizeToFit]; [hbox addView: f enablingXResizing: YES]; DESTROY(f); [vbox addView: hbox enablingYResizing: NO]; DESTROY(hbox); hbox=[[GSHbox alloc] init]; [hbox setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; [hbox setDefaultMinXMargin: 2]; f=[[NSTextField alloc] init]; [f setStringValue: _(@"From:")]; [f setEditable: NO]; [f setDrawsBackground: NO]; [f setBordered: NO]; [f setBezeled: NO]; [f setSelectable: NO]; [f sizeToFit]; [f setAutoresizingMask: 0]; [hbox addView: f enablingXResizing: NO]; DESTROY(f); tf_from=f=[[NSTextField alloc] init]; [f setAutoresizingMask: NSViewWidthSizable]; [f sizeToFit]; [hbox addView: f enablingXResizing: YES]; DESTROY(f); b_send=b=[[NSButton alloc] init]; [b setTitle: _(@"Post")]; [b sizeToFit]; [b setTarget: self]; [b setAction: @selector(post:)]; [hbox addView: b enablingXResizing: NO]; DESTROY(b); [vbox addView: hbox enablingYResizing: NO]; DESTROY(hbox); } [win setContentView: vbox]; [vbox release]; } if ([msg_headers objectForKey: @"Subject"]) [tf_subject setStringValue: [msg_headers objectForKey: @"Subject"]]; if ([msg_headers objectForKey: @"Newsgroups"]) [tf_newsgroups setStringValue: [msg_headers objectForKey: @"Newsgroups"]]; if ([msg_headers objectForKey: @"From"]) [tf_from setStringValue: [msg_headers objectForKey: @"From"]]; else { NSString *name,*from; name=[Pref_Posting postingName]; from=[Pref_Posting fromAddress]; if (from) { if (name) [tf_from setStringValue: [NSString stringWithFormat: @"\"%@\" <%@>",name,from]]; else [tf_from setStringValue: from]; } } [win setTitle: [tf_subject stringValue]]; [win setDelegate: self]; [win release]; return self; } /* returns a retained string */ -(NSMutableString *) _quoteString: (NSString *)content to: (NSMutableString *)astr { NSMutableString *str; NSString *line; NSArray *lines; int i,c; lines=[content componentsSeparatedByString: @"\n"]; c=[lines count]; if (astr) str=astr; else str=[[NSMutableString alloc] initWithCapacity: [content length]+2*c]; for (i=0;i0 && [line characterAtIndex: 0]=='>') [str appendString: @">"]; else [str appendString: @"> "]; [str appendString: line]; [str appendString: @"\n"]; } return str; } - initWithHeaders: (NSDictionary *)headers quoteContent: (NSString *)content { NSString *str; if (!content) return [self initWithHeaders: headers content: nil]; str=[self _quoteString: content to: nil]; self=[self initWithHeaders: headers content: str]; DESTROY(str); return self; } - initWithHeaders: (NSDictionary *)headers { return [self initWithHeaders: headers content: nil]; } /* TODO: handle attributation, followup to sender, followup, etc. */ - initWithFollowupToMessage: (CWMessage *)msg { NSDictionary *headers; NSString *subject,*references; NSString *msgid; int i; references=[msg headerValueForName: @"References"]; msgid=[msg messageID]; if ([msgid characterAtIndex: 0]!='<') msgid=[[@"<" stringByAppendingString: [msg messageID] ] stringByAppendingString: @">"]; if (!references) references=msgid; else { references=[[references stringByAppendingString: @" "] stringByAppendingString: msgid]; } subject=[msg subject]; if ([subject length]>=3 && [subject characterAtIndex: 2]==':') { for (i=3;i<[subject length];i++) if ([subject characterAtIndex: i]>32) break; subject=[subject substringFromIndex: i]; } subject=[@"Re: " stringByAppendingString: subject]; headers=[NSDictionary dictionaryWithObjectsAndKeys: subject,@"Subject", references,@"References", [msg headerValueForName: @"Newsgroups"],@"Newsgroups", nil]; { NSMutableString *str; str=[[NSMutableString alloc] init]; if ([[msg from] personal] && [[[msg from] personal] length]) [str appendString: [NSString stringWithFormat: @"%@ wrote:\n",[[msg from] personal]]]; else [str appendString: [NSString stringWithFormat: @"%@ wrote:\n",[[msg from] address]]]; if ([[msg content] isKindOfClass: [NSString class]]) { NSString *content=(NSString *)[msg content]; str=[self _quoteString: content to: str]; } else [str appendString: @"> (currently) unquoteable content\n"]; return [self initWithHeaders: headers content: str]; DESTROY(str); } } @end