#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 "LabelWindow.h"
#include "MailSupport.h"
#include "MailWindow.h"
#include "Messages.h"
#include "Prefs.h"
#include "QueryMenu.h"
#include "Signature.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(), 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;
}