Open Tracker License
Terms and Conditions
Copyright (c) 1991-2001, Be Incorporated. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice applies to all licensees
and shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Be Incorporated shall not be
used in advertising or otherwise to promote the sale, use or other dealings in
this Software without prior written authorization from Be Incorporated.
BeMail(TM), Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or
registered trademarks of Be Incorporated in the United States and other
countries. Other brand product names are registered trademarks or trademarks
of their respective holders. All rights reserved.
*/
#include "MailApp.h"
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <Autolock.h>
#include <Catalog.h>
#include <CharacterSet.h>
#include <CharacterSetRoster.h>
#include <Clipboard.h>
#include <Debug.h>
#include <E-mail.h>
#include <InterfaceKit.h>
#include <Locale.h>
#include <Roster.h>
#include <Screen.h>
#include <StorageKit.h>
#include <String.h>
#include <TextView.h>
#include <UTF8.h>
#include <fs_index.h>
#include <fs_info.h>
#include <MailMessage.h>
#include <MailSettings.h>
#include <MailDaemon.h>
#include <mail_util.h>
#include <CharacterSetRoster.h>
using namespace BPrivate ;
#include "Content.h"
#include "Enclosures.h"
#include "FieldMsg.h"
#include "FindWindow.h"
#include "Header.h"
#include "MailSupport.h"
#include "MailWindow.h"
#include "Messages.h"
#include "Prefs.h"
#include "QueryMenu.h"
#include "Signature.h"
#include "Status.h"
#include "String.h"
#include "Utilities.h"
#include "Words.h"
#define B_TRANSLATION_CONTEXT "Mail"
static const char *kDictDirectory = "word_dictionary";
static const char *kIndexDirectory = "word_index";
static const char *kWordsPath = "/boot/optional/goodies/words";
static const char *kExact = ".exact";
static const char *kMetaphone = ".metaphone";
TMailApp::TMailApp()
:
BApplication("application/x-vnd.Be-MAIL"),
fWindowCount(0),
fPrefsWindow(NULL),
fSigWindow(NULL),
fPrintSettings(NULL),
fPrintHelpAndExit(false),
fWrapMode(true),
fAttachAttributes(true),
fColoredQuotes(true),
fShowToolBar(true),
fWarnAboutUnencodableCharacters(true),
fStartWithSpellCheckOn(false),
fShowSpamGUI(true),
fMailCharacterSet(B_MAIL_UTF8_CONVERSION),
fContentFont(be_fixed_font),
fPeople(fPeopleQueryList),
fPeopleGroups(fPeopleQueryList)
{
fAutoMarkRead = true;
fSignature = (char*)malloc(strlen(B_TRANSLATE("None")) + 1);
strcpy(fSignature, B_TRANSLATE("None"));
fReplyPreamble = strdup(B_TRANSLATE("%e wrote:\\n"));
fMailWindowFrame.Set(0, 0, 0, 0);
const BCharacterSet* defaultComposeEncoding
= BCharacterSetRoster::FindCharacterSetByName(B_TRANSLATE_COMMENT(
"UTF-8", "This string is used as a key to set default message "
"compose encoding. It must be correct IANA name from "
"http://cgit.haiku-os.org/haiku/tree/src/kits/textencoding"
"/character_sets.cpp Translate it only if you want to change "
"default message compose encoding for your locale. If you don't "
"know what is it and why it may needs changing, just leave "
"\"UTF-8\"."));
if (defaultComposeEncoding != NULL)
fMailCharacterSet = defaultComposeEncoding->GetConversionID();
LoadSettings();
_CheckForSpamFilterExistence();
fContentFont.SetSpacing(B_BITMAP_SPACING);
fLastMailWindowFrame = fMailWindowFrame;
}
TMailApp::~TMailApp()
{
}
void
TMailApp::ArgvReceived(int32 argc, char **argv)
{
BEntry entry;
BString names;
BString ccNames;
BString bccNames;
BString subject;
BString body;
BMessage enclosure(B_REFS_RECEIVED);
bool gotmailto = false;
for (int32 loop = 1; loop < argc; loop++)
{
if (strcmp(argv[loop], "-h") == 0
|| strcmp(argv[loop], "--help") == 0)
{
printf(" usage: %s [ mailto:<address> ] [ -subject \"<text>\" ] [ ccto:<address> ] [ bccto:<address> ] "
"[ -body \"<body text>\" ] [ enclosure:<path> ] [ <message to read> ...] \n",
argv[0]);
fPrintHelpAndExit = true;
be_app->PostMessage(B_QUIT_REQUESTED);
return;
}
else if (strncmp(argv[loop], "mailto:", 7) == 0)
{
if (names.Length())
names += ", ";
char *options;
if ((options = strchr(argv[loop],'?')) != NULL)
{
names.Append(argv[loop] + 7, options - argv[loop] - 7);
if (!strncmp(++options,"subject=",8))
subject = options + 8;
}
else
names += argv[loop] + 7;
gotmailto = true;
}
else if (strncmp(argv[loop], "ccto:", 5) == 0)
{
if (ccNames.Length())
ccNames += ", ";
ccNames += argv[loop] + 5;
}
else if (strncmp(argv[loop], "bccto:", 6) == 0)
{
if (bccNames.Length())
bccNames += ", ";
bccNames += argv[loop] + 6;
}
else if (strcmp(argv[loop], "-subject") == 0)
subject = argv[++loop];
else if (strcmp(argv[loop], "-body") == 0 && argv[loop + 1])
body = argv[++loop];
else if (strncmp(argv[loop], "enclosure:", 10) == 0)
{
BEntry tmp(argv[loop] + 10, true);
if (tmp.InitCheck() == B_OK && tmp.Exists())
{
entry_ref ref;
tmp.GetRef(&ref);
enclosure.AddRef("refs", &ref);
}
}
else if (entry.SetTo(argv[loop]) == B_NO_ERROR)
{
BMessage msg(B_REFS_RECEIVED);
entry_ref ref;
entry.GetRef(&ref);
msg.AddRef("refs", &ref);
RefsReceived(&msg);
}
}
if (gotmailto || names.Length() || ccNames.Length() || bccNames.Length() || subject.Length()
|| body.Length() || enclosure.HasRef("refs"))
{
TMailWindow *window = NewWindow(NULL, names.String());
window->SetTo(names.String(), subject.String(), ccNames.String(), bccNames.String(),
&body, &enclosure);
window->Show();
}
}
void
TMailApp::MessageReceived(BMessage *msg)
{
TMailWindow *window = NULL;
entry_ref ref;
switch (msg->what) {
case M_NEW:
{
int32 type;
msg->FindInt32("type", &type);
switch (type) {
case M_NEW:
window = NewWindow();
break;
case M_RESEND:
{
msg->FindRef("ref", &ref);
BNode file(&ref);
BString string;
if (file.InitCheck() == B_OK)
file.ReadAttrString(B_MAIL_ATTR_TO, &string);
window = NewWindow(&ref, string.String(), true);
break;
}
case M_FORWARD:
case M_FORWARD_WITHOUT_ATTACHMENTS:
{
TMailWindow *sourceWindow;
if (msg->FindPointer("window", (void **)&sourceWindow) < B_OK
|| !sourceWindow->Lock())
break;
msg->FindRef("ref", &ref);
window = NewWindow();
if (window->Lock()) {
window->Forward(&ref, sourceWindow, type == M_FORWARD);
window->Unlock();
}
sourceWindow->Unlock();
break;
}
case M_REPLY:
case M_REPLY_TO_SENDER:
case M_REPLY_ALL:
case M_COPY_TO_NEW:
{
TMailWindow *sourceWindow;
if (msg->FindPointer("window", (void **)&sourceWindow) < B_OK
|| !sourceWindow->Lock())
break;
msg->FindRef("ref", &ref);
window = NewWindow();
if (window->Lock()) {
if (type == M_COPY_TO_NEW)
window->CopyMessage(&ref, sourceWindow);
else
window->Reply(&ref, sourceWindow, type);
window->Unlock();
}
sourceWindow->Unlock();
break;
}
}
if (window)
window->Show();
break;
}
case M_PREFS:
if (fPrefsWindow)
fPrefsWindow->Activate(true);
else {
fPrefsWindow = new TPrefsWindow(fPrefsWindowPos,
&fContentFont, NULL, &fWrapMode, &fAttachAttributes,
&fColoredQuotes, &fDefaultAccount, &fUseAccountFrom,
&fReplyPreamble, &fSignature, &fMailCharacterSet,
&fWarnAboutUnencodableCharacters,
&fStartWithSpellCheckOn, &fAutoMarkRead,
&fShowToolBar);
if (fPrefsWindowPos.x <= 0 || fPrefsWindowPos.y <= 0) {
TMailWindow* window = _ActiveWindow();
if (window != NULL)
fPrefsWindow->CenterIn(window->Frame());
else
fPrefsWindow->CenterOnScreen();
}
fPrefsWindow->MoveOnScreen();
fPrefsWindow->Show();
}
break;
case PREFS_CHANGED:
{
for (int32 i = 0; i < fWindowList.CountItems(); i++) {
TMailWindow* window = (TMailWindow*)fWindowList.ItemAt(i);
window->Lock();
window->UpdatePreferences();
window->UpdateViews();
window->Unlock();
}
break;
}
case M_ACCOUNTS:
be_roster->Launch("application/x-vnd.Haiku-Mail");
break;
case M_EDIT_SIGNATURE:
if (fSigWindow != NULL)
fSigWindow->Activate(true);
else {
fSigWindow = new TSignatureWindow(fSignatureWindowFrame);
if (!fSignatureWindowFrame.IsValid()) {
TMailWindow* window = _ActiveWindow();
if (window != NULL)
fSigWindow->CenterIn(window->Frame());
else
fSigWindow->CenterOnScreen();
}
fSigWindow->MoveOnScreen();
fSigWindow->Show();
}
break;
case M_FONT:
FontChange();
break;
case REFS_RECEIVED:
if (msg->HasPointer("window")) {
msg->FindPointer("window", (void**)&window);
BMessage message(*msg);
window->PostMessage(&message, window);
}
break;
case WINDOW_CLOSED:
switch (msg->FindInt32("kind")) {
case MAIL_WINDOW:
{
TMailWindow* window;
if (msg->FindPointer("window", (void**)&window) == B_OK)
fWindowList.RemoveItem(window);
fWindowCount--;
break;
}
case PREFS_WINDOW:
fPrefsWindow = NULL;
msg->FindPoint("window pos", &fPrefsWindowPos);
break;
case SIG_WINDOW:
fSigWindow = NULL;
msg->FindRect("window frame", &fSignatureWindowFrame);
break;
}
if (!fWindowCount && !fSigWindow && !fPrefsWindow)
be_app->PostMessage(B_QUIT_REQUESTED);
break;
case kMsgQuitAndKeepAllStatus:
{
for (int32 i = 0; i < fWindowList.CountItems(); i++) {
TMailWindow* window = (TMailWindow*)fWindowList.ItemAt(i);
window->PostMessage(new BMessage(kMsgCloseAndKeepAllStatus));
}
break;
}
case B_REFS_RECEIVED:
RefsReceived(msg);
break;
case B_PRINTER_CHANGED:
_ClearPrintSettings();
break;
default:
BApplication::MessageReceived(msg);
break;
}
}
bool
TMailApp::QuitRequested()
{
if (!BApplication::QuitRequested())
return false;
fMailWindowFrame = fLastMailWindowFrame;
if (be_roster->IsRunning(kSpamServerSignature)) {
team_id serverTeam = be_roster->TeamFor(kSpamServerSignature);
if (serverTeam >= 0) {
int32 errorCode = B_SERVER_NOT_FOUND;
BMessenger messengerToSpamServer(kSpamServerSignature, serverTeam, &errorCode);
if (messengerToSpamServer.IsValid()) {
BMessage quitMessage(B_QUIT_REQUESTED);
messengerToSpamServer.SendMessage(&quitMessage);
}
}
}
SaveSettings();
return true;
}
void
TMailApp::ReadyToRun()
{
BVolume volume;
BVolumeRoster().GetBootVolume(&volume);
fs_create_index(volume.Device(), "META:group", B_STRING_TYPE, 0);
fs_create_index(volume.Device(), "META:email", B_STRING_TYPE, 0);
fs_create_index(volume.Device(), "MAIL:draft", B_INT32_TYPE, 0);
fs_create_index(volume.Device(), INDEX_SIGNATURE, B_STRING_TYPE, 0);
fs_create_index(volume.Device(), INDEX_STATUS, B_STRING_TYPE, 0);
fs_create_index(volume.Device(), B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0);
fPeopleQueryList.Init("META:email=**");
BPath indexDir;
BPath dictionaryDir;
BPath userDictionaryDir;
BPath userIndexDir;
BPath dataPath;
BPath indexPath;
BDirectory directory;
BEntry entry;
find_directory(B_SYSTEM_DATA_DIRECTORY, &indexDir, true);
indexDir.Append("spell_check");
dictionaryDir = indexDir;
find_directory(B_USER_CONFIG_DIRECTORY, &userIndexDir, true);
userIndexDir.Append("data/spell_check");
userDictionaryDir = userIndexDir;
directory.CreateDirectory(userIndexDir.Path(), NULL);
indexDir.Append(kIndexDirectory);
dictionaryDir.Append(kDictDirectory);
userIndexDir.Append(kIndexDirectory);
userDictionaryDir.Append(kDictDirectory);
directory.CreateDirectory(indexDir.Path(), NULL);
directory.CreateDirectory(dictionaryDir.Path(), NULL);
directory.CreateDirectory(userIndexDir.Path(), NULL);
directory.CreateDirectory(userDictionaryDir.Path(), NULL);
dataPath = dictionaryDir;
dataPath.Append("words");
if (BEntry(kWordsPath).Exists() || BEntry(dataPath.Path()).Exists()) {
if (!BEntry(dataPath.Path()).Exists() && BEntry(kWordsPath).Exists()) {
BFile words(kWordsPath, B_READ_ONLY);
BFile copy(dataPath.Path(), B_WRITE_ONLY | B_CREATE_FILE);
char buffer[4096];
ssize_t size;
while ((size = words.Read( buffer, 4096)) > 0)
copy.Write(buffer, size);
BNodeInfo(©).SetType("text/plain");
}
directory.SetTo(dictionaryDir.Path());
BString leafName;
gUserDict = -1;
while (gDictCount < MAX_DICTIONARIES
&& directory.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) {
dataPath.SetTo(&entry);
indexPath = indexDir;
leafName.SetTo(dataPath.Leaf());
leafName.Append(kMetaphone);
indexPath.Append(leafName.String());
gWords[gDictCount] = new Words(dataPath.Path(), indexPath.Path(), true);
indexPath = indexDir;
leafName.SetTo(dataPath.Leaf());
leafName.Append(kExact);
indexPath.Append(leafName.String());
gExactWords[gDictCount] = new Words(dataPath.Path(), indexPath.Path(), false);
gDictCount++;
}
dataPath = userDictionaryDir;
dataPath.Append("user");
if (!BEntry(dataPath.Path()).Exists()) {
BFile user(dataPath.Path(), B_WRITE_ONLY | B_CREATE_FILE);
BNodeInfo(&user).SetType("text/plain");
}
if (BEntry(userDictionaryDir.Path()).Exists()) {
gUserDictFile = new BFile(dataPath.Path(), B_WRITE_ONLY | B_OPEN_AT_END);
gUserDict = gDictCount;
indexPath = userIndexDir;
leafName.SetTo(dataPath.Leaf());
leafName.Append(kMetaphone);
indexPath.Append(leafName.String());
gWords[gDictCount] = new Words(dataPath.Path(), indexPath.Path(), true);
indexPath = userIndexDir;
leafName.SetTo(dataPath.Leaf());
leafName.Append(kExact);
indexPath.Append(leafName.String());
gExactWords[gDictCount] = new Words(dataPath.Path(), indexPath.Path(), false);
gDictCount++;
}
}
if (!fPrintHelpAndExit && !fWindowCount) {
TMailWindow *window;
window = NewWindow();
window->Show();
}
}
void
TMailApp::RefsReceived(BMessage *msg)
{
bool have_names = false;
BString names;
char type[B_FILE_NAME_LENGTH];
int32 item = 0;
BFile file;
TMailWindow *window;
entry_ref ref;
BMessenger messenger;
if (msg->HasMessenger("TrackerViewToken"))
msg->FindMessenger("TrackerViewToken", &messenger);
while (msg->HasRef("refs", item)) {
msg->FindRef("refs", item++, &ref);
if ((window = FindWindow(ref)) != NULL)
window->Activate(true);
else {
file.SetTo(&ref, O_RDONLY);
if (file.InitCheck() == B_NO_ERROR) {
BNodeInfo node(&file);
node.GetType(type);
if (strcmp(type, B_MAIL_TYPE) == 0
|| strcmp(type, B_PARTIAL_MAIL_TYPE) == 0) {
window = NewWindow(&ref, NULL, false, &messenger);
window->Show();
} else if (strcmp(type, "application/x-person") == 0) {
BString name;
BString email;
attr_info info;
char *attrib;
if (file.GetAttrInfo("META:email", &info) == B_NO_ERROR) {
attrib = (char *) malloc(info.size + 1);
file.ReadAttr("META:email", B_STRING_TYPE, 0, attrib, info.size);
attrib[info.size] = 0;
email << attrib;
free(attrib);
if (email.Length() > 0) {
if (file.GetAttrInfo("META:name", &info) == B_NO_ERROR) {
attrib = (char *) malloc(info.size + 1);
file.ReadAttr("META:name", B_STRING_TYPE, 0, attrib, info.size);
attrib[info.size] = 0;
name << "\"" << attrib << "\" ";
email.Prepend("<");
email.Append(">");
free(attrib);
}
if (names.Length() == 0) {
names << name << email;
} else {
names << ", " << name << email;
}
have_names = true;
email.SetTo("");
name.SetTo("");
}
}
}
else if (strcmp(type, kDraftType) == 0) {
window = NewWindow();
window->OpenMessage(&ref);
window->Show();
}
}
}
}
if (have_names) {
window = NewWindow(NULL, names.String());
window->Show();
}
}
TMailWindow *
TMailApp::FindWindow(const entry_ref &ref)
{
BEntry entry(&ref);
if (entry.InitCheck() < B_OK)
return NULL;
node_ref nodeRef;
if (entry.GetNodeRef(&nodeRef) < B_OK)
return NULL;
BWindow *window;
int32 index = 0;
while ((window = WindowAt(index++)) != NULL) {
TMailWindow *mailWindow = dynamic_cast<TMailWindow *>(window);
if (mailWindow == NULL)
continue;
node_ref mailNodeRef;
if (mailWindow->GetMailNodeRef(mailNodeRef) == B_OK
&& mailNodeRef == nodeRef)
return mailWindow;
}
return NULL;
}
void
TMailApp::_CheckForSpamFilterExistence()
{
int32 addonNameIndex;
const char *addonNamePntr;
BDirectory inChainDir;
BPath path;
BEntry settingsEntry;
BFile settingsFile;
BMessage settingsMessage;
fShowSpamGUI = false;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
return;
path.Append("Mail/chains/inbound");
if (inChainDir.SetTo(path.Path()) != B_OK)
return;
while (inChainDir.GetNextEntry (&settingsEntry, true ) == B_OK) {
if (!settingsEntry.IsFile())
continue;
if (settingsFile.SetTo (&settingsEntry, B_READ_ONLY) != B_OK)
continue;
if (settingsMessage.Unflatten (&settingsFile) != B_OK)
continue;
for (addonNameIndex = 0; B_OK == settingsMessage.FindString (
"filter_addons", addonNameIndex, &addonNamePntr);
addonNameIndex++) {
if (strstr (addonNamePntr, "Spam Filter") != NULL) {
fShowSpamGUI = true;
return;
}
}
}
}
TMailWindow*
TMailApp::_ActiveWindow()
{
for (int32 i = 0; i < fWindowList.CountItems(); i++) {
TMailWindow* window = (TMailWindow*)fWindowList.ItemAt(i);
if (window->IsActive())
return window;
}
return NULL;
}
void
TMailApp::SetPrintSettings(const BMessage* printSettings)
{
BAutolock _(this);
if (printSettings == fPrintSettings)
return;
delete fPrintSettings;
if (printSettings)
fPrintSettings = new BMessage(*printSettings);
else
fPrintSettings = NULL;
}
bool
TMailApp::HasPrintSettings()
{
BAutolock _(this);
return fPrintSettings != NULL;
}
BMessage
TMailApp::PrintSettings()
{
BAutolock _(this);
return BMessage(*fPrintSettings);
}
void
TMailApp::_ClearPrintSettings()
{
delete fPrintSettings;
fPrintSettings = NULL;
}
void
TMailApp::SetLastWindowFrame(BRect frame)
{
BAutolock _(this);
fLastMailWindowFrame = frame;
}
status_t
TMailApp::GetSettingsPath(BPath &path)
{
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
if (status != B_OK)
return status;
path.Append("Mail");
return create_directory(path.Path(), 0755);
}
status_t
TMailApp::LoadOldSettings()
{
BPath path;
status_t status = find_directory(B_USER_SETTINGS_DIRECTORY, &path);
if (status != B_OK)
return status;
path.Append("Mail_data");
BFile file;
status = file.SetTo(path.Path(), B_READ_ONLY);
if (status != B_OK)
return status;
file.Read(&fMailWindowFrame, sizeof(BRect));
font_family fontFamily;
font_style fontStyle;
float size;
file.Read(&fontFamily, sizeof(font_family));
file.Read(&fontStyle, sizeof(font_style));
file.Read(&size, sizeof(float));
if (size >= 9)
fContentFont.SetSize(size);
if (fontFamily[0] && fontStyle[0])
fContentFont.SetFamilyAndStyle(fontFamily, fontStyle);
file.Read(&fSignatureWindowFrame, sizeof(BRect));
file.Seek(1, SEEK_CUR);
file.Read(&fWrapMode, sizeof(bool));
file.Read(&fPrefsWindowPos, sizeof(BPoint));
int32 length;
if (file.Read(&length, sizeof(int32)) < (ssize_t)sizeof(int32))
return B_IO_ERROR;
free(fSignature);
fSignature = NULL;
if (length > 0) {
fSignature = (char *)malloc(length);
if (fSignature == NULL)
return B_NO_MEMORY;
file.Read(fSignature, length);
}
file.Read(&fMailCharacterSet, sizeof(int32));
if (fMailCharacterSet != B_MAIL_UTF8_CONVERSION
&& fMailCharacterSet != B_MAIL_US_ASCII_CONVERSION
&& BCharacterSetRoster::GetCharacterSetByConversionID(fMailCharacterSet) == NULL)
fMailCharacterSet = B_MS_WINDOWS_CONVERSION;
if (file.Read(&length, sizeof(int32)) == (ssize_t)sizeof(int32)) {
char *findString = (char *)malloc(length + 1);
if (findString == NULL)
return B_NO_MEMORY;
file.Read(findString, length);
findString[length] = '\0';
FindWindow::SetFindString(findString);
free(findString);
}
if (file.Read(&fShowToolBar, sizeof(uint8)) < (ssize_t)sizeof(uint8))
fShowToolBar = true;
if (file.Read(&fUseAccountFrom, sizeof(int32)) < (ssize_t)sizeof(int32)
|| fUseAccountFrom < ACCOUNT_USE_DEFAULT
|| fUseAccountFrom > ACCOUNT_FROM_MAIL)
fUseAccountFrom = ACCOUNT_USE_DEFAULT;
if (file.Read(&fColoredQuotes, sizeof(bool)) < (ssize_t)sizeof(bool))
fColoredQuotes = true;
if (file.Read(&length, sizeof(int32)) == (ssize_t)sizeof(int32)) {
free(fReplyPreamble);
fReplyPreamble = (char *)malloc(length + 1);
if (fReplyPreamble == NULL)
return B_NO_MEMORY;
file.Read(fReplyPreamble, length);
fReplyPreamble[length] = '\0';
}
file.Read(&fAttachAttributes, sizeof(bool));
file.Read(&fWarnAboutUnencodableCharacters, sizeof(bool));
return B_OK;
}
status_t
TMailApp::SaveSettings()
{
BMailSettings accountSettings;
if (fDefaultAccount != ~0L) {
accountSettings.SetDefaultOutboundAccount(fDefaultAccount);
accountSettings.Save();
}
BPath path;
status_t status = GetSettingsPath(path);
if (status != B_OK)
return status;
path.Append("BeMail Settings~");
BFile file;
status = file.SetTo(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
if (status != B_OK)
return status;
BMessage settings('BeMl');
settings.AddRect("MailWindowSize", fMailWindowFrame);
font_family fontFamily;
font_style fontStyle;
fContentFont.GetFamilyAndStyle(&fontFamily, &fontStyle);
settings.AddString("FontFamily", fontFamily);
settings.AddString("FontStyle", fontStyle);
settings.AddFloat("FontSize", fContentFont.Size());
settings.AddRect("SignatureWindowSize", fSignatureWindowFrame);
settings.AddBool("WordWrapMode", fWrapMode);
settings.AddPoint("PreferencesWindowLocation", fPrefsWindowPos);
settings.AddBool("AutoMarkRead", fAutoMarkRead);
settings.AddString("SignatureText", fSignature);
settings.AddInt32("CharacterSet", fMailCharacterSet);
settings.AddString("FindString", FindWindow::GetFindString());
settings.AddInt8("ShowButtonBar", fShowToolBar);
settings.AddInt32("UseAccountFrom", fUseAccountFrom);
settings.AddBool("ColoredQuotes", fColoredQuotes);
settings.AddString("ReplyPreamble", fReplyPreamble);
settings.AddBool("AttachAttributes", fAttachAttributes);
settings.AddBool("WarnAboutUnencodableCharacters", fWarnAboutUnencodableCharacters);
settings.AddBool("StartWithSpellCheck", fStartWithSpellCheckOn);
BEntry entry;
status = entry.SetTo(path.Path());
if (status != B_OK)
return status;
status = settings.Flatten(&file);
if (status == B_OK) {
status = entry.Rename("BeMail Settings", true);
} else
entry.Remove();
return status;
}
status_t
TMailApp::LoadSettings()
{
BMailSettings accountSettings;
fDefaultAccount = accountSettings.DefaultOutboundAccount();
BPath path;
status_t status = GetSettingsPath(path);
if (status != B_OK)
return status;
path.Append("BeMail Settings");
BFile file;
status = file.SetTo(path.Path(), B_READ_ONLY);
if (status != B_OK)
return LoadOldSettings();
BMessage settings;
status = settings.Unflatten(&file);
if (status < B_OK || settings.what != 'BeMl') {
return LoadOldSettings();
}
BRect rect;
if (settings.FindRect("MailWindowSize", &rect) == B_OK)
fMailWindowFrame = rect;
int32 int32Value;
const char *fontFamily;
if (settings.FindString("FontFamily", &fontFamily) == B_OK) {
const char *fontStyle;
if (settings.FindString("FontStyle", &fontStyle) == B_OK) {
float size;
if (settings.FindFloat("FontSize", &size) == B_OK) {
if (size >= 7)
fContentFont.SetSize(size);
if (fontFamily[0] && fontStyle[0]) {
fContentFont.SetFamilyAndStyle(fontFamily[0] ? fontFamily : NULL,
fontStyle[0] ? fontStyle : NULL);
}
}
}
}
if (settings.FindRect("SignatureWindowSize", &rect) == B_OK)
fSignatureWindowFrame = rect;
bool boolValue;
if (settings.FindBool("WordWrapMode", &boolValue) == B_OK)
fWrapMode = boolValue;
BPoint point;
if (settings.FindPoint("PreferencesWindowLocation", &point) == B_OK)
fPrefsWindowPos = point;
if (settings.FindBool("AutoMarkRead", &boolValue) == B_OK)
fAutoMarkRead = boolValue;
const char *string;
if (settings.FindString("SignatureText", &string) == B_OK) {
free(fSignature);
fSignature = strdup(string);
}
if (settings.FindInt32("CharacterSet", &int32Value) == B_OK)
fMailCharacterSet = int32Value;
if (fMailCharacterSet != B_MAIL_UTF8_CONVERSION
&& fMailCharacterSet != B_MAIL_US_ASCII_CONVERSION
&& BCharacterSetRoster::GetCharacterSetByConversionID(fMailCharacterSet) == NULL)
fMailCharacterSet = B_MS_WINDOWS_CONVERSION;
if (settings.FindString("FindString", &string) == B_OK)
FindWindow::SetFindString(string);
int8 int8Value;
if (settings.FindInt8("ShowButtonBar", &int8Value) == B_OK)
fShowToolBar = int8Value;
if (settings.FindInt32("UseAccountFrom", &int32Value) == B_OK)
fUseAccountFrom = int32Value;
if (fUseAccountFrom < ACCOUNT_USE_DEFAULT
|| fUseAccountFrom > ACCOUNT_FROM_MAIL)
fUseAccountFrom = ACCOUNT_USE_DEFAULT;
if (settings.FindBool("ColoredQuotes", &boolValue) == B_OK)
fColoredQuotes = boolValue;
if (settings.FindString("ReplyPreamble", &string) == B_OK) {
free(fReplyPreamble);
fReplyPreamble = strdup(string);
}
if (settings.FindBool("AttachAttributes", &boolValue) == B_OK)
fAttachAttributes = boolValue;
if (settings.FindBool("WarnAboutUnencodableCharacters", &boolValue) == B_OK)
fWarnAboutUnencodableCharacters = boolValue;
if (settings.FindBool("StartWithSpellCheck", &boolValue) == B_OK)
fStartWithSpellCheckOn = boolValue;
return B_OK;
}
void
TMailApp::FontChange()
{
int32 index = 0;
BMessage msg;
BWindow *window;
msg.what = CHANGE_FONT;
msg.AddPointer("font", &fContentFont);
for (;;) {
window = WindowAt(index++);
if (!window)
break;
window->PostMessage(&msg);
}
}
TMailWindow*
TMailApp::NewWindow(const entry_ref* ref, const char* to, bool resend,
BMessenger* trackerMessenger)
{
float fontFactor = be_plain_font->Size() / 12.0f;
BRect r;
if (fMailWindowFrame.Width() < 64 || fMailWindowFrame.Height() < 20) {
r.Set(40 * fontFactor, 40 * fontFactor, fontFactor * (40 + WIND_WIDTH),
fontFactor * (40 + WIND_HEIGHT));
} else
r = fMailWindowFrame;
r.OffsetBy(fontFactor * (((fWindowCount + 5) % 10) * 15 - 75),
fontFactor * (((fWindowCount + 5) % 10) * 15 - 75));
fWindowCount++;
BString title;
BFile file;
if (!resend && ref && file.SetTo(ref, O_RDONLY) == B_OK) {
BString name;
if (file.ReadAttrString(B_MAIL_ATTR_NAME, &name) == B_OK) {
title << name;
BString subject;
if (file.ReadAttrString(B_MAIL_ATTR_SUBJECT, &subject) == B_OK)
title << " -> " << subject;
}
}
if (title == "")
title = B_TRANSLATE_SYSTEM_NAME("Mail");
TMailWindow* window = new TMailWindow(r, title.String(), this, ref, to,
&fContentFont, resend, trackerMessenger);
fWindowList.AddItem(window);
window->MoveOnScreen();
return window;
}
bool
TMailApp::AutoMarkRead()
{
BAutolock _(this);
return fAutoMarkRead;
}
BString
TMailApp::Signature()
{
BAutolock _(this);
return BString(fSignature);
}
BString
TMailApp::ReplyPreamble()
{
BAutolock _(this);
return BString(fReplyPreamble);
}
bool
TMailApp::WrapMode()
{
BAutolock _(this);
return fWrapMode;
}
bool
TMailApp::AttachAttributes()
{
BAutolock _(this);
return fAttachAttributes;
}
bool
TMailApp::ColoredQuotes()
{
BAutolock _(this);
return fColoredQuotes;
}
uint8
TMailApp::ShowToolBar()
{
BAutolock _(this);
return fShowToolBar;
}
bool
TMailApp::WarnAboutUnencodableCharacters()
{
BAutolock _(this);
return fWarnAboutUnencodableCharacters;
}
bool
TMailApp::StartWithSpellCheckOn()
{
BAutolock _(this);
return fStartWithSpellCheckOn;
}
void
TMailApp::SetDefaultAccount(int32 account)
{
BAutolock _(this);
fDefaultAccount = account;
}
int32
TMailApp::DefaultAccount()
{
BAutolock _(this);
return fDefaultAccount;
}
int32
TMailApp::UseAccountFrom()
{
BAutolock _(this);
return fUseAccountFrom;
}
uint32
TMailApp::MailCharacterSet()
{
BAutolock _(this);
return fMailCharacterSet;
}
BFont
TMailApp::ContentFont()
{
BAutolock _(this);
return fContentFont;
}
int
main()
{
tzset();
TMailApp().Run();
return B_OK;
}