KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > mail > MessageBuffer


1 /*
2  * MessageBuffer.java
3  *
4  * Copyright (C) 2000-2003 Peter Graves
5  * $Id: MessageBuffer.java,v 1.16 2003/05/26 17:08:14 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.j.mail;
23
24 import java.awt.Image JavaDoc;
25 import java.awt.Rectangle JavaDoc;
26 import java.io.BufferedReader JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.StringReader JavaDoc;
29 import java.util.ArrayList JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Vector JavaDoc;
33 import javax.swing.Icon JavaDoc;
34 import javax.swing.SwingUtilities JavaDoc;
35 import org.armedbear.j.Annotation;
36 import org.armedbear.j.Buffer;
37 import org.armedbear.j.BufferIterator;
38 import org.armedbear.j.Debug;
39 import org.armedbear.j.Display;
40 import org.armedbear.j.Editor;
41 import org.armedbear.j.EditorIterator;
42 import org.armedbear.j.File;
43 import org.armedbear.j.FastStringBuffer;
44 import org.armedbear.j.FastStringReader;
45 import org.armedbear.j.Headers;
46 import org.armedbear.j.ImageLine;
47 import org.armedbear.j.ImageLoader;
48 import org.armedbear.j.Line;
49 import org.armedbear.j.LineSequence;
50 import org.armedbear.j.Log;
51 import org.armedbear.j.MessageDialog;
52 import org.armedbear.j.MessageHeaderLine;
53 import org.armedbear.j.Position;
54 import org.armedbear.j.ProgressNotifier;
55 import org.armedbear.j.Property;
56 import org.armedbear.j.SaveFileDialog;
57 import org.armedbear.j.Sidebar;
58 import org.armedbear.j.SystemBuffer;
59 import org.armedbear.j.TextLine;
60 import org.armedbear.j.Utilities;
61 import org.armedbear.j.WebBuffer;
62 import org.armedbear.j.WebFormatter;
63 import org.armedbear.j.WebLine;
64 import org.armedbear.j.WebLoader;
65
66 public class MessageBuffer extends Buffer
67 {
68     protected Mailbox mailbox;
69     protected MailboxEntry entry;
70     protected Message message;
71     protected boolean showFullHeaders;
72     protected boolean showRawText;
73     protected String JavaDoc allHeaders;
74     protected String JavaDoc defaultHeaders;
75     protected String JavaDoc rawBody;
76     protected String JavaDoc body;
77     protected String JavaDoc mimeBody;
78     protected MimePart selectedPart;
79     protected int headerLineCount;
80
81     private boolean wrap = true;
82
83     protected MessageBuffer()
84     {
85         super();
86         setInitialized(true);
87     }
88
89     public MessageBuffer(String JavaDoc rawText)
90     {
91         initializeUndo();
92         type = TYPE_NORMAL;
93         lineSeparator = "\n";
94         mode = MessageMode.getMode();
95         setFormatter(new MessageFormatter(this));
96         readOnly = true;
97         message = new Message(rawText);
98         parseMessage();
99         title = message.getHeaderValue(Headers.SUBJECT);
100         if (title == null)
101             title = "";
102         allHeaders = message.getAllHeaders();
103         defaultHeaders = getDefaultHeaders(allHeaders);
104         rawBody = message.getRawBody();
105         setText();
106         renumber();
107         formatter.parseBuffer();
108         setInitialized(true);
109     }
110
111     public final boolean isPrimary()
112     {
113         if (mailbox == null)
114             return true;
115         return mailbox.getPreviewBuffer() != this;
116     }
117
118     public final boolean isSecondary()
119     {
120         if (mailbox == null)
121             return false;
122         return mailbox.getPreviewBuffer() == this;
123     }
124
125     public final Buffer getPrimary()
126     {
127         if (mailbox != null && mailbox.getPreviewBuffer() == this)
128             return mailbox;
129         return null;
130     }
131
132     public final void promote()
133     {
134         if (mailbox != null && mailbox.getPreviewBuffer() == this)
135             mailbox.setPreviewBuffer(null);
136     }
137
138     public int getHeaderLineCount()
139     {
140         return headerLineCount;
141     }
142
143     public int getDisplayHeight()
144     {
145         int height = 0;
146         for (Line line = getFirstLine(); line != null; line = line.nextVisible())
147             height += line.getHeight();
148         return height;
149     }
150
151     public int getDisplayWidth()
152     {
153         int width = 0;
154         for (Line line = getFirstLine(); line != null; line = line.nextVisible()) {
155             int lineWidth = line.getWidth();
156             if (lineWidth > width)
157                 width = lineWidth;
158         }
159         return Display.getGutterWidth(this) + width + Display.getCharWidth();
160     }
161
162     // Returns cumulative height to top of target line.
163
public int getY(Line target)
164     {
165         int y = 0;
166         for (Line line = getFirstLine(); line != null && line != target; line = line.nextVisible())
167             y += line.getHeight();
168         return y;
169     }
170
171     protected void setEntry(MailboxEntry entry)
172     {
173         Debug.assertTrue(entry != null);
174         reset();
175         this.entry = entry;
176         FastStringBuffer sb = new FastStringBuffer();
177         sb.append(mailbox.getLineNumberForEntry(entry) + 1);
178         sb.append('/');
179         sb.append(mailbox.getLineCount());
180         sb.append(' ');
181         sb.append(entry.formatSubject());
182         title = sb.toString();
183         Sidebar.setUpdateFlagInAllFrames(SIDEBAR_REPAINT_BUFFER_LIST);
184     }
185
186     protected void reset()
187     {
188         try {
189             lockWrite();
190         }
191         catch (InterruptedException JavaDoc e) {
192             Log.debug(e);
193             return;
194         }
195         try {
196             empty();
197             message = null;
198             mimeBody = null;
199             selectedPart = null;
200         }
201         finally {
202             unlockWrite();
203         }
204     }
205
206     public int load()
207     {
208         Debug.assertTrue(false); // Shouldn't be called.
209
return LOAD_COMPLETED;
210     }
211
212     protected void loadMessage(ProgressNotifier progressNotifier)
213     {
214         Debug.assertTrue(entry != null);
215         mailbox.setBusy(true);
216         message = mailbox.getMessage(entry, progressNotifier);
217         mailbox.setBusy(false);
218         if (message == null)
219             return;
220         parseMessage();
221         allHeaders = message.getAllHeaders();
222         defaultHeaders = getDefaultHeaders(allHeaders);
223         rawBody = message.getRawBody();
224         wrap = true;
225         setText();
226         formatter.parseBuffer();
227         int flags = entry.getFlags();
228         if ((flags & MailboxEntry.SEEN) == 0) {
229             flags |= MailboxEntry.SEEN;
230             flags &= ~MailboxEntry.RECENT;
231             entry.setFlags(flags);
232             mailbox.setDirty(true);
233             mailbox.updateEntry(entry);
234             mailbox.countMessages();
235         }
236         Runnable JavaDoc r = new Runnable JavaDoc() {
237             public void run()
238             {
239                 setBusy(false);
240                 for (EditorIterator it = new EditorIterator(); it.hasNext();) {
241                     Editor ed = it.nextEditor();
242                     if (ed.getBuffer() == MessageBuffer.this) {
243                         ed.setDot(getFirstLine(), 0);
244                         ed.setUpdateFlag(REFRAME);
245                         ed.moveCaretToDotCol();
246                         ed.setTopLine(getFirstLine());
247                         ed.setMark(null);
248                         ed.setUpdateFlag(REPAINT);
249                         ed.updateDisplay();
250                     } else if (ed.getBuffer() == mailbox)
251                         ed.updateDisplay();
252                 }
253                 Sidebar.repaintBufferListInAllFrames();
254             }
255         };
256         SwingUtilities.invokeLater(r);
257     }
258
259     public final MailboxEntry getMailboxEntry()
260     {
261         return entry;
262     }
263
264     public final Message getMessage()
265     {
266         return message;
267     }
268
269     public final int getMessageNumber()
270     {
271         Debug.assertTrue(entry != null);
272         return entry.getMessageNumber();
273     }
274
275     public final Mailbox getMailbox()
276     {
277         return mailbox;
278     }
279
280     public void nextMessage()
281     {
282         if (entry == null)
283             return;
284         Editor editor = Editor.currentEditor();
285         MailboxEntry nextEntry = mailbox.getNextUndeleted(entry);
286         if (nextEntry != null) {
287             mailbox.setDotEntry(nextEntry);
288             load(editor, nextEntry);
289         } else {
290             MailCommands.messageIndex(editor);
291             editor.status("Last undeleted message");
292         }
293     }
294
295     public void previousMessage()
296     {
297         if (entry == null)
298             return;
299         Editor editor = Editor.currentEditor();
300         MailboxEntry previousEntry = mailbox.getPreviousUndeleted(entry);
301         if (previousEntry != null) {
302             mailbox.setDotEntry(previousEntry);
303             load(editor, previousEntry);
304         } else {
305             MailCommands.messageIndex(editor);
306             editor.status("First undeleted message");
307         }
308     }
309
310     public void nextInThread()
311     {
312         if (entry == null)
313             return;
314         Editor editor = Editor.currentEditor();
315         MailboxEntry nextEntry = mailbox.getNextInThread(entry);
316         if (nextEntry != null) {
317             mailbox.setDotEntry(nextEntry);
318             load(editor, nextEntry);
319         } else {
320             MailCommands.messageIndex(editor);
321             editor.status("Last message in thread");
322         }
323     }
324
325     public void previousInThread()
326     {
327         if (entry == null)
328             return;
329         Editor editor = Editor.currentEditor();
330         MailboxEntry previousEntry = mailbox.getPreviousInThread(entry);
331         if (previousEntry != null) {
332             mailbox.setDotEntry(previousEntry);
333             load(editor, previousEntry);
334         } else {
335             MailCommands.messageIndex(editor);
336             editor.status("First message in thread");
337         }
338     }
339
340     public void parentMessage()
341     {
342         final Editor editor = Editor.currentEditor();
343         String JavaDoc inReplyTo = message.getHeaderValue(Headers.IN_REPLY_TO);
344         Log.debug("inReplyTo = |" + inReplyTo + "|");
345         if (inReplyTo != null) {
346             String JavaDoc msgId = extractMessageId(inReplyTo);
347             if (msgId != null) {
348                 Log.debug("msgId = |" + msgId + "|");
349                 MailboxEntry parentEntry = mailbox.getEntryForMessageId(msgId);
350                 if (parentEntry != null) {
351                     load(editor, parentEntry);
352                     return;
353                 }
354             }
355         }
356         String JavaDoc references = message.getHeaderValue(Headers.REFERENCES);
357         Log.debug("references = |" + references + "|");
358         if (references != null) {
359             List JavaDoc list = extractAllMessageIds(references);
360             if (list != null) {
361                 for (int i = 0; i < list.size(); i++) {
362                     String JavaDoc msgId = (String JavaDoc) list.get(i);
363                     if (msgId != null) {
364                         Log.debug("msgId = |" + msgId + "|");
365                         MailboxEntry parentEntry =
366                             mailbox.getEntryForMessageId(msgId);
367                         if (parentEntry != null) {
368                             load(editor, parentEntry);
369                             return;
370                         }
371                     }
372                 }
373             }
374         }
375         editor.status("No parent");
376     }
377
378     private static String JavaDoc extractMessageId(String JavaDoc s)
379     {
380         if (s == null)
381             return null;
382         int begin = s.indexOf('<');
383         if (begin < 0)
384             return null;
385         int end = s.indexOf('>');
386         if (end < 0)
387             return null;
388         return s.substring(begin, end + 1);
389     }
390
391     private static List JavaDoc extractAllMessageIds(String JavaDoc s)
392     {
393         if (s == null)
394             return null;
395         ArrayList JavaDoc list = null;
396         while (s.length() > 2) {
397             int begin = s.indexOf('<');
398             if (begin < 0)
399                 break;
400             int end = s.indexOf('>');
401             if (end < 0)
402                 break;
403             String JavaDoc msgId = s.substring(begin, end + 1);
404             if (list == null)
405                 list = new ArrayList JavaDoc();
406             Log.debug("adding |" + msgId + "|");
407             list.add(msgId);
408             s = s.substring(end+1);
409         }
410         return list;
411     }
412
413     private void load(Editor editor, MailboxEntry nextEntry)
414     {
415         if (mailbox.lock()) {
416             setBusy(true);
417             setEntry(nextEntry);
418             Runnable JavaDoc r = new Runnable JavaDoc() {
419                 public void run()
420                 {
421                     try {
422                         loadMessage(null);
423                     }
424                     finally {
425                         mailbox.unlock();
426                     }
427                 }
428             };
429             new Thread JavaDoc(r).start();
430         } else
431             editor.status("Mailbox is locked");
432     }
433
434     // Might return null.
435
public String JavaDoc quoteBody(int wrapCol)
436     {
437         String JavaDoc toBeQuoted = mimeBody != null ? mimeBody : rawBody;
438         if (toBeQuoted == null) {
439             Log.debug("quoteBody toBeQuoted is null");
440             return null;
441         }
442         if (Utilities.isWhitespace(toBeQuoted)) {
443             Log.debug("quoteBody toBeQuoted is whitespace");
444             return null;
445         }
446         String JavaDoc wrapped = wrap(toBeQuoted, wrapCol-2, 8);
447         FastStringReader reader = new FastStringReader(wrapped);
448         FastStringBuffer sb = new FastStringBuffer(4096);
449         String JavaDoc s;
450         while ((s = reader.readLine()) != null) {
451             sb.append('>');
452             if (s.length() > 0) {
453                 sb.append(' ');
454                 sb.append(s);
455             }
456             sb.append('\n');
457         }
458         return sb.toString();
459     }
460
461     private static final String JavaDoc wrap(String JavaDoc s, int wrapCol, int tabWidth)
462     {
463         FastStringReader reader = new FastStringReader(s);
464         FastStringBuffer sb = new FastStringBuffer(4096);
465         java.io.StringWriter JavaDoc writer = new java.io.StringWriter JavaDoc();
466         String JavaDoc line;
467         while ((line = reader.readLine()) != null) {
468             if (line.length() == 0) {
469                 if (sb.length() > 0) {
470                     writer.write(Utilities.wrap(sb.toString(), wrapCol,
471                         tabWidth));
472                     sb.setLength(0);
473                     writer.write('\n');
474                 }
475                 writer.write('\n');
476             } else {
477                 // Line is not empty.
478
if (sb.length() == 0 &&
479                     Utilities.getDetabbedLength(line, tabWidth) <= 78) {
480                     // Line is a reasonable length.
481
writer.write(line);
482                     writer.write('\n');
483                     continue;
484                 }
485                 char c = line.charAt(0);
486                 if (c == ' ' || c == '\t' || c == '>') {
487                     if (sb.length() > 0) {
488                         writer.write(Utilities.wrap(sb.toString(), wrapCol,
489                             tabWidth));
490                         sb.setLength(0);
491                         writer.write('\n');
492                     }
493                     writer.write(line);
494                     writer.write('\n');
495                 } else {
496                     if (sb.length() > 0) {
497                         // Make sure last char is a space or tab.
498
c = sb.charAt(sb.length()-1);
499                         if (c != ' ' && c != '\t')
500                             sb.append(' ');
501                     }
502                     sb.append(line);
503                 }
504             }
505         }
506         if (sb.length() > 0) {
507             writer.write(Utilities.wrap(sb.toString(), wrapCol, tabWidth));
508             sb.append('\n');
509         }
510         return writer.toString();
511     }
512
513     public void deleteMessage() {}
514
515     public void flagMessage() {}
516
517     public void moveMessage() {}
518
519     public void bounce()
520     {
521         Debug.assertTrue(SwingUtilities.isEventDispatchThread());
522         final Editor editor = Editor.currentEditor();
523         final MailAddress[] to = MailCommands.bounceGetTo(editor, 1);
524         if (to == null)
525             return;
526         Runnable JavaDoc bounceRunnable = new Runnable JavaDoc() {
527             public void run()
528             {
529                 Log.debug("MessageBuffer bounceRunnable.run()");
530                 boolean succeeded = false;
531                 try {
532                     succeeded = Mail.bounceMessage(message, to);
533                 }
534                 finally {
535                     setBusy(false);
536                     editor.updateDisplayLater();
537                 }
538                 if (succeeded) {
539                     Runnable JavaDoc successRunnable = new Runnable JavaDoc() {
540                         public void run()
541                         {
542                             editor.status("Message bounced");
543                         }
544                     };
545                     SwingUtilities.invokeLater(successRunnable);
546                 } else {
547                     Runnable JavaDoc errorRunnable = new Runnable JavaDoc() {
548                         public void run()
549                         {
550                             MessageDialog.showMessageDialog(editor, "Failed",
551                                 "Bounce Message");
552                         }
553                     };
554                     SwingUtilities.invokeLater(errorRunnable);
555                 }
556             }
557         };
558         setBusy(true);
559         new Thread JavaDoc(bounceRunnable).start();
560     }
561
562     protected String JavaDoc getBeautifiedHeaders()
563     {
564         if (message == null)
565             return "";
566         Headers headers = Headers.parse(message.getRawHeaders());
567         ArrayList JavaDoc names = new ArrayList JavaDoc(); // Header names.
568
names.add("From");
569         names.add("To");
570         names.add("Cc");
571         names.add("Subject");
572         names.add("Date");
573         int width = 0;
574         for (Iterator JavaDoc it = names.iterator(); it.hasNext();) {
575             int w = ((String JavaDoc)it.next()).length();
576             if (w > width)
577                 width = w;
578         }
579         FastStringBuffer sb = new FastStringBuffer();
580         for (Iterator JavaDoc it = names.iterator(); it.hasNext();) {
581             String JavaDoc name = (String JavaDoc) it.next();
582             String JavaDoc value = headers.getValue(name);
583             if (value != null) {
584                 if (name == "From" || name== "To" || name == "Cc") {
585                     MailAddress[] array =
586                         MailAddress.parseAddresses(RFC2047.decode(value));
587                     ArrayList JavaDoc list = new ArrayList JavaDoc();
588                     for (int i = 0; i < array.length; i++)
589                         list.add(array[i]);
590                     String JavaDoc prefix =
591                         Utilities.rightJustify(name, width).concat(": ");
592                     sb.append(MailUtilities.constructAddressHeader(prefix,
593                         list, prefix.length()));
594                 } else {
595                     // Subject, date.
596
sb.append(Utilities.rightJustify(name, width));
597                     sb.append(": ");
598                     sb.append(RFC2047.decode(value));
599                 }
600                 sb.append('\n');
601             }
602         }
603         return sb.toString();
604     }
605
606     protected String JavaDoc getDefaultHeaders(String JavaDoc s)
607     {
608         FastStringBuffer sb = new FastStringBuffer();
609         if (s.length() > 0) {
610             BufferedReader JavaDoc reader = new BufferedReader JavaDoc(new StringReader JavaDoc(s));
611             boolean maybeContinuation = false;
612             try {
613                 while (true) {
614                     String JavaDoc text = reader.readLine();
615                     if (text == null || text.length() == 0)
616                         break;
617                     if (maybeContinuation &&
618                         Character.isWhitespace(text.charAt(0))) {
619                         sb.append(text);
620                         sb.append('\n');
621                     } else if (isDefaultHeader(text)) {
622                         sb.append(text);
623                         sb.append('\n');
624                         maybeContinuation = true;
625                     } else
626                         maybeContinuation = false;
627                 }
628             }
629             catch (IOException JavaDoc e) {
630                 Log.error(e);
631             }
632         }
633         return sb.toString();
634     }
635
636     private boolean isDefaultHeader(String JavaDoc s)
637     {
638         s = s.toLowerCase();
639         if (s.startsWith("from:") ||
640             s.startsWith("to:") ||
641             s.startsWith("cc:") ||
642             s.startsWith("subject:") ||
643             s.startsWith("date:"))
644             return true;
645         return false;
646     }
647
648     public void viewAttachment()
649     {
650         final MimePart part = getAttachmentAtDot();
651         if (part == null)
652             return;
653         final Editor editor = Editor.currentEditor();
654         editor.setWaitCursor();
655         final String JavaDoc contentType = part.getContentType();
656         if (contentType != null && contentType.equals("message/rfc822")) {
657             final String JavaDoc rawText = part.getRawBody();
658             Buffer buf = null;
659             // See if we already have this attachment open in a buffer.
660
for (BufferIterator it = new BufferIterator(); it.hasNext();) {
661                 Buffer b = it.nextBuffer();
662                 if (b instanceof MessageBuffer) {
663                     MessageBuffer mb = (MessageBuffer) b;
664                     Message m = mb.getMessage();
665                     if (m.getRawText().equals(rawText)) {
666                         buf = b;
667                         break;
668                     }
669                 }
670             }
671             if (buf == null) // Attachment is not in an existing buffer.
672
buf = new MessageBuffer(rawText);
673             editor.makeNext(buf);
674             editor.switchToBuffer(buf);
675             return;
676         }
677         File cache = part.cacheDecoded();
678         if (cache == null || !cache.isFile()) {
679             MessageDialog.showMessageDialog("Unable to decode attachment",
680                 "View Attachment");
681             return;
682         }
683         if (contentType != null && contentType.equals("text/html")) {
684             WebBuffer.browse(editor, cache, null);
685             return;
686         }
687         Buffer buf = editor.openFile(cache);
688         if (buf != null) {
689             editor.makeNext(buf);
690             editor.switchToBuffer(buf);
691         }
692     }
693
694     public void saveAttachment()
695     {
696         MimePart part = getAttachmentAtDot();
697         if (part == null)
698             return;
699         final Editor editor = Editor.currentEditor();
700         SaveFileDialog d =
701             new SaveFileDialog(editor, "Save Attachment", "File:");
702         File suggested = File.getInstance(editor.getCurrentDirectory(),
703             part.getAttachmentFileName());
704         if (suggested != null)
705             d.setInitialText(suggested.canonicalPath());
706         editor.centerDialog(d);
707         d.show();
708         File saveAs = d.getDestination();
709         if (saveAs == null)
710             return;
711         editor.repaintNow();
712         editor.setWaitCursor();
713         boolean success = part.saveDecoded(saveAs);
714         editor.setDefaultCursor();
715         if (!success)
716             MessageDialog.showMessageDialog("Unable to save attachment",
717                 "Save Attachment");
718     }
719
720     private MimePart getAttachmentAtDot()
721     {
722         Position dot = Editor.currentEditor().getDot();
723         if (dot != null) {
724             Annotation annotation = dot.getLine().getAnnotation();
725             if (annotation != null) {
726                 Object JavaDoc obj = annotation.getUserObject();
727                 if (obj instanceof MimePart)
728                     return (MimePart) obj;
729             }
730         }
731         return null;
732     }
733
734     public void toggleRaw()
735     {
736         showRawText = !showRawText;
737         if (mailbox != null)
738             mailbox.showRawText = showRawText;
739         reloadInternal();
740         FastStringBuffer sb = new FastStringBuffer("Raw mode ");
741         sb.append(showRawText ? "on" : "off");
742         Editor.currentEditor().status(sb.toString());
743     }
744
745     public void toggleHeaders()
746     {
747         if (mailbox != null)
748             mailbox.showFullHeaders = showFullHeaders = !showFullHeaders;
749         reloadInternal();
750     }
751
752     public void toggleWrap()
753     {
754         wrap = !wrap;
755         reloadInternal();
756         FastStringBuffer sb = new FastStringBuffer("Wrap ");
757         sb.append(wrap ? "on" : "off");
758         Editor.currentEditor().status(sb.toString());
759     }
760
761     private void reloadInternal()
762     {
763         setText();
764         formatter.parseBuffer();
765         for (EditorIterator it = new EditorIterator(); it.hasNext();) {
766             Editor ed = it.nextEditor();
767             if (ed.getBuffer() == this) {
768                 ed.setDot(getFirstLine(), 0);
769                 ed.moveCaretToDotCol();
770                 ed.setMark(null);
771                 ed.setTopLine(getFirstLine());
772                 ed.repaintDisplay();
773             }
774         }
775     }
776
777     protected void parseMessage()
778     {
779         if (mimeBody != null)
780             Debug.bug();
781         message.parse();
782         List JavaDoc parts = message.getParts();
783         if (parts == null || parts.size() == 0) {
784             // Not multipart.
785
mimeBody = message.getDecodedBody();
786             return;
787         }
788         for (Iterator JavaDoc it = parts.iterator(); it.hasNext();) {
789             MimePart part = (MimePart) it.next();
790             final String JavaDoc contentType = part.getContentType();
791             if (contentType == null || contentType.equals("text/plain")) {
792                 selectedPart = part;
793                 mimeBody = part.getDecodedBody();
794                 return;
795             }
796         }
797         for (Iterator JavaDoc it = parts.iterator(); it.hasNext();) {
798             MimePart part = (MimePart) it.next();
799             final String JavaDoc contentType = part.getContentType();
800             if (contentType == null || contentType.equals("text/html")) {
801                 selectedPart = part;
802                 mimeBody = part.getDecodedBody();
803                 return;
804             }
805         }
806         mimeBody = "";
807     }
808
809     private List JavaDoc getAttachmentLines()
810     {
811         List JavaDoc parts = message.getParts();
812         if (parts == null || parts.size() == 0) {
813             // Not multipart.
814
return null;
815         }
816         int shown = -1;
817         ArrayList JavaDoc list = new ArrayList JavaDoc();
818         list.add(new MessageHeaderLine("Parts/Attachments:"));
819         for (int i = 0; i < parts.size(); i++) {
820             FastStringBuffer sb = new FastStringBuffer();
821             sb.append(" ");
822             sb.append(i+1);
823             MimePart part = (MimePart) parts.get(i);
824             final String JavaDoc contentType = part.getContentType();
825             if (part == selectedPart) {
826                 sb.append(" Shown");
827             } else {
828                 String JavaDoc filename = part.getAttachmentFileName();
829                 if (filename != null && filename.length() > 0) {
830                     if (part.isAttachment())
831                         sb.append(" Attachment:");
832                     else if (part.isInline())
833                         sb.append(" Inline:");
834                     sb.append(' ');
835                     sb.append(filename);
836                 } else if (part.isAttachment()) {
837                     sb.append(" Attachment");
838                 } else if (part.isInline()) {
839                     sb.append(" Inline");
840                 }
841             }
842             sb.append(" (");
843             if (contentType != null) {
844                 sb.append(contentType);
845                 sb.append(", ");
846             }
847             final String JavaDoc encoding = part.getTransferEncoding();
848             if (encoding != null) {
849                 sb.append(encoding);
850                 sb.append(", ");
851             }
852             sb.append(part.getSize());
853             sb.append(" bytes)");
854             Line line = new MessageHeaderLine(sb.toString());
855             line.setAnnotation(new Annotation(part));
856             list.add(line);
857         }
858         return list;
859     }
860
861     protected void setText()
862     {
863         try {
864             lockWrite();
865         }
866         catch (InterruptedException JavaDoc e) {
867             Log.debug(e);
868             return;
869         }
870         try {
871             _setText();
872             setLoaded(true);
873         }
874         finally {
875             unlockWrite();
876         }
877     }
878
879     private void _setText()
880     {
881         empty();
882         if (showRawText) {
883             body = rawBody;
884             setText(message.getRawText());
885             headerLineCount = Utilities.countLines(allHeaders);
886             if (!(formatter instanceof MessageFormatter))
887                 setFormatter(new MessageFormatter(this));
888             return;
889         }
890         // Not raw mode.
891
final String JavaDoc headers;
892         if (showFullHeaders)
893             headers = allHeaders;
894         else if (Editor.preferences().getBooleanProperty(Property.BEAUTIFY_HEADERS))
895             headers = getBeautifiedHeaders();
896         else
897             headers = defaultHeaders;
898         final String JavaDoc contentType = message.getContentType();
899         if (contentType != null) {
900             if (contentType.startsWith("image/")) {
901                 File cache = message.cacheDecoded();
902                 if (cache != null && cache.isFile()) {
903                     ImageLoader loader = new ImageLoader(cache);
904                     Image JavaDoc image = loader.loadImage();
905                     appendHeaderLines(headers);
906                     appendHeaderLine("");
907                     if (image != null) {
908                         final int lineHeight = new TextLine("").getHeight();
909                         final int imageHeight = image.getHeight(null);
910                         final int imageWidth = image.getWidth(null);
911                         int y = 0;
912                         while (y < imageHeight) {
913                             Rectangle JavaDoc r = new Rectangle JavaDoc(0, y, imageWidth,
914                                 Math.min(lineHeight, imageHeight - y));
915                             appendLine(new ImageLine(image, r));
916                             y += lineHeight;
917                         }
918                     }
919                     renumber();
920                 } else {
921                     appendHeaderLines(headers);
922                     appendHeaderLine("");
923                     append(body);
924                 }
925                 renumber();
926                 if (!(formatter instanceof MessageFormatter))
927                     setFormatter(new MessageFormatter(this));
928                 return;
929             }
930             if (contentType.equals("text/html")) {
931                 appendHeaderLines(headers);
932                 appendHeaderLine("");
933                 StringReader JavaDoc reader =
934                     new StringReader JavaDoc(message.getDecodedBody());
935                 WebLoader loader = new WebLoader(reader);
936                 LineSequence lines = loader.load();
937                 Line lastLine = getLastLine();
938                 lastLine.setNext(lines.getFirstLine());
939                 lines.getFirstLine().setPrevious(lastLine);
940                 renumber();
941                 if (!(formatter instanceof WebFormatter))
942                     setFormatter(new WebFormatter(this));
943                 return;
944             }
945         }
946         appendHeaderLines(headers);
947         headerLineCount = Utilities.countLines(headers);
948         List JavaDoc attachmentLines = getAttachmentLines();
949         if (attachmentLines != null) {
950             appendHeaderLine("");
951             ++headerLineCount;
952             Iterator JavaDoc iter = attachmentLines.iterator();
953             while (iter.hasNext()) {
954                 Line line = (Line) iter.next();
955                 if (!(line instanceof MessageHeaderLine))
956                     Debug.bug();
957                 appendLine(line);
958                 ++headerLineCount;
959             }
960         }
961         if (mimeBody != null)
962             body = mimeBody;
963         else
964             body = rawBody;
965         if (selectedPart != null && "text/html".equals(selectedPart.getContentType())) {
966             appendLine("");
967             StringReader JavaDoc reader = new StringReader JavaDoc(mimeBody);
968             WebLoader loader = new WebLoader(reader);
969             LineSequence lines = loader.load();
970             Line lastLine = getLastLine();
971             lastLine.setNext(lines.getFirstLine());
972             lines.getFirstLine().setPrevious(lastLine);
973             if (!(formatter instanceof WebFormatter))
974                 setFormatter(new WebFormatter(this));
975         } else {
976             if (wrap)
977                 body = wrapBody(body);
978             appendLine("");
979             append(body);
980             if (!(formatter instanceof MessageFormatter))
981                 setFormatter(new MessageFormatter(this));
982         }
983         // Don't try to display images inline if the message is too big.
984
if (message.getSize() < 1024 * 1024) {
985             List JavaDoc parts = message.getParts();
986             if (parts != null) {
987                 for (int i = 0; i < parts.size(); i++) {
988                     MimePart part = (MimePart) parts.get(i);
989                     String JavaDoc partContentType = part.getContentType();
990                     if (partContentType == null)
991                         continue;
992                     File cache = null;
993                     if (partContentType.equals("application/octet-stream")) {
994                         String JavaDoc filename = part.getAttachmentFileName();
995                         if (filename == null)
996                             continue;
997                         filename = filename.toLowerCase();
998                         if (filename.endsWith(".jpg") ||
999                             filename.endsWith(".jpeg") ||
1000                            filename.endsWith(".png") ||
1001                            filename.endsWith(".gif"))
1002                            cache = part.cacheDecoded();
1003                    } else if (partContentType.startsWith("image/"))
1004                        cache = part.cacheDecoded();
1005                    if (cache != null && cache.isFile()) {
1006                        ImageLoader loader = new ImageLoader(cache);
1007                        Image JavaDoc image = loader.loadImage();
1008                        if (image != null) {
1009                            if (getLastLine() instanceof ImageLine)
1010                                appendLine("");
1011                            final int lineHeight = new TextLine("").getHeight();
1012                            final int imageHeight = image.getHeight(null);
1013                            final int imageWidth = image.getWidth(null);
1014                            int y = 0;
1015                            while (y < imageHeight) {
1016                                Rectangle JavaDoc r = new Rectangle JavaDoc(0, y, imageWidth,
1017                                    Math.min(lineHeight, imageHeight - y));
1018                                appendLine(new ImageLine(image, r));
1019                                y += lineHeight;
1020                            }
1021                        }
1022                    }
1023                }
1024            }
1025        }
1026        renumber();
1027    }
1028
1029    private static String JavaDoc wrapBody(String JavaDoc body)
1030    {
1031        final int wrapCol = Editor.currentEditor().getDisplay().getColumns();
1032        final int tabWidth = 8;
1033        final int IN_DIFF = 1;
1034        SystemBuffer buf = new SystemBuffer();
1035        FastStringReader reader = new FastStringReader(body);
1036        String JavaDoc s;
1037        while ((s = reader.readLine()) != null)
1038            buf.appendLine(s);
1039        boolean containsDiff = false;
1040        boolean inDiff = false;
1041        for (Line line = buf.getFirstLine(); line != null; line = line.next()) {
1042            if (inDiff) {
1043                if (MessageFormatter.isDiffContinuation(line))
1044                    line.setFlags(IN_DIFF);
1045                else {
1046                    inDiff = false;
1047                    line.setFlags(0);
1048                }
1049                continue;
1050            }
1051            // Not in diff.
1052
if (MessageFormatter.isDiffStart(line)) {
1053                inDiff = true;
1054                line.setFlags(IN_DIFF);
1055                containsDiff = true;
1056                continue;
1057            }
1058            // Not start of diff.
1059
line.setFlags(0);
1060        }
1061        if (!containsDiff)
1062            return Utilities.wrap(body, wrapCol, tabWidth);
1063        // Buffer contains diff.
1064
FastStringBuffer out = new FastStringBuffer();
1065        FastStringBuffer in = new FastStringBuffer();
1066        for (Line line = buf.getFirstLine(); line != null; line = line.next()) {
1067            if (line.flags() == IN_DIFF) {
1068                if (in.length() > 0) {
1069                    out.append(Utilities.wrap(in.toString(), wrapCol, tabWidth));
1070                    in.setLength(0);
1071                }
1072                out.append(line.getText());
1073                out.append('\n');
1074            } else {
1075                // Not in diff.
1076
in.append(line.getText());
1077                in.append('\n');
1078            }
1079        }
1080        if (in.length() > 0)
1081            out.append(Utilities.wrap(in.toString(), wrapCol, tabWidth));
1082        return out.toString();
1083    }
1084
1085    protected void appendHeaderLines(String JavaDoc headers)
1086    {
1087        if (headers != null) {
1088            FastStringReader reader = new FastStringReader(headers);
1089            String JavaDoc s;
1090            while ((s = reader.readLine()) != null)
1091                appendHeaderLine(s);
1092        }
1093    }
1094
1095    protected void appendHeaderLine(String JavaDoc s)
1096    {
1097        appendLine(new MessageHeaderLine(s));
1098    }
1099
1100    public String JavaDoc toString()
1101    {
1102        return title;
1103    }
1104
1105    // For the buffer list.
1106
public Icon JavaDoc getIcon()
1107    {
1108        return Utilities.getIconFromFile("message.png");
1109    }
1110
1111    public String JavaDoc getFileNameForDisplay()
1112    {
1113        return "";
1114    }
1115
1116    private static final String JavaDoc SPLIT_KEY = "MessageBuffer.split";
1117
1118    public void saveWindowState(Editor editor)
1119    {
1120        if (editor.getBuffer() != this)
1121            return;
1122        Editor otherEditor = editor.getOtherEditor();
1123        if (otherEditor != null) {
1124            float height = (float) editor.getHeight();
1125            float split =
1126                height / (editor.getFrame().getEditorPane().getHeight());
1127            Editor.getSessionProperties().setFloatProperty(SPLIT_KEY, split);
1128        }
1129    }
1130
1131    public float getSplit()
1132    {
1133        return Editor.getSessionProperties().getFloatProperty(SPLIT_KEY, 0.5F);
1134    }
1135
1136    public void windowClosing()
1137    {
1138        Editor editor = Editor.currentEditor();
1139        if (editor.getBuffer() == this)
1140            saveWindowState(editor);
1141        else {
1142            Editor otherEditor = editor.getOtherEditor();
1143            if (otherEditor != null && otherEditor.getBuffer() == this)
1144                saveWindowState(otherEditor);
1145        }
1146    }
1147
1148    public void dispose()
1149    {
1150        if (mailbox != null && mailbox.getPreviewBuffer() == this)
1151            mailbox.setPreviewBuffer(null);
1152        flushImages();
1153    }
1154
1155    public void empty()
1156    {
1157        flushImages();
1158        super.empty();
1159    }
1160
1161    private void flushImages()
1162    {
1163        for (Line line = getFirstLine(); line != null; line = line.next()) {
1164            if (line instanceof ImageLine)
1165                ((ImageLine)line).flushImage();
1166        }
1167    }
1168}
1169
Popular Tags