Imported MDR. Some code still not entirely functional -- I haven't been able to figure out how to detect SSL, so IMAP and POP have it turned off. PPP auto-detect is also not functional at the moment. Other than that, it seems to work beautifully. Packaging will come later.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@9016 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Nathan Whitehorn
2004-09-20 22:31:50 +00:00
parent 48061f2026
commit f7215ac853
154 changed files with 75670 additions and 0 deletions
+1
View File
@@ -2,6 +2,7 @@ SubDir OBOS_TOP src servers ;
SubInclude OBOS_TOP src servers app ;
SubInclude OBOS_TOP src servers input ;
SubInclude OBOS_TOP src servers mail ;
SubInclude OBOS_TOP src servers media ;
SubInclude OBOS_TOP src servers media_addon ;
SubInclude OBOS_TOP src servers midi ;
+20
View File
@@ -0,0 +1,20 @@
SubDir OBOS_TOP src servers mail ;
UsePrivateHeaders mail ;
SubDirHdrs [ FDirName $(OBOS_TOP) headers os add-ons mail_daemon ] ;
AddResources E-mail : <$(SOURCE_GRIST)>mail_daemon.rsrc ;
Server mail_daemon :
deskbarview.cpp
LEDAnimation.cpp
main.cpp
;
LinkSharedOSLibs mail_daemon :
be
mail
tracker
stdc++.r4
;
+100
View File
@@ -0,0 +1,100 @@
#include "LEDAnimation.h"
#include <InterfaceDefs.h>
#define SNOOZE_TIME 150000
#include <stdio.h>
/***********************************************************
* Constructor
***********************************************************/
LEDAnimation::LEDAnimation()
:fThread(-1)
,fRunning(false)
,fOrigModifiers(::modifiers())
{
}
/***********************************************************
* Destructor
***********************************************************/
LEDAnimation::~LEDAnimation()
{
Stop();
}
/***********************************************************
* Start
***********************************************************/
void
LEDAnimation::Start()
{
// don't do anything if the thread is already running
if (fThread >= 0)
return;
fOrigModifiers = ::modifiers();
::set_keyboard_locks(0);
fRunning = true;
fThread = ::spawn_thread(AnimationThread,"LED thread",B_NORMAL_PRIORITY,this);
::resume_thread(fThread);
}
/***********************************************************
* Stop
***********************************************************/
void
LEDAnimation::Stop()
{
// don't do anything if the thread doesn't run
if (fThread < 0)
return;
fRunning = false;
status_t result;
::wait_for_thread(fThread,&result);
::set_keyboard_locks(fOrigModifiers);
}
/***********************************************************
* AnimationThread
***********************************************************/
int32
LEDAnimation::AnimationThread(void* data)
{
LEDAnimation *anim = (LEDAnimation*)data;
while (anim->fRunning)
{
LED(B_NUM_LOCK,true);
LED(B_NUM_LOCK,false);
LED(B_CAPS_LOCK,true);
LED(B_CAPS_LOCK,false);
LED(B_SCROLL_LOCK,true);
LED(B_SCROLL_LOCK,false);
LED(B_CAPS_LOCK,true);
LED(B_CAPS_LOCK,false);
}
anim->fThread = -1;
return 0;
}
/***********************************************************
* LED
***********************************************************/
void
LEDAnimation::LED(uint32 mod,bool on)
{
uint32 current_modifiers = ::modifiers();
if(on)
current_modifiers |= mod;
else
current_modifiers &= ~mod;
::set_keyboard_locks(current_modifiers);
if(on)
::snooze(SNOOZE_TIME);
}
+33
View File
@@ -0,0 +1,33 @@
#ifndef __LEDANIMATION_H__
#define __LEDANIMATION_H__
//! Keyboard LED Animation class.
#include <SupportDefs.h>
#include <OS.h>
class LEDAnimation {
public:
//! Constructor
LEDAnimation();
//! Destructor
~LEDAnimation();
//!Start LED animation.
void Start();
//!Stop LED animation.
void Stop();
//! Check animation thread is running.
bool IsRunning() const {return fRunning;}
private:
//!Anination thread.
static int32 AnimationThread(void *data);
//!Set LED on or off.
static void LED(uint32 mod/*!Modifier key*/,bool on/*!If LED on, value is true*/);
//!Animation thread ID.
thread_id fThread;
//!Thread running flag.
volatile bool fRunning;
uint32 fOrigModifiers;
};
#endif
+164
View File
@@ -0,0 +1,164 @@
/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, 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.
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.
*/
// NavMenu is a hierarchical menu of volumes, folders, files and queries
// displays icons, uses the SlowMenu API for full interruptability
#ifndef NAV_MENU_H
#define NAV_MENU_H
#include <Messenger.h>
#include <StorageDefs.h>
#include <Entry.h>
#include "SlowMenu.h"
template<class T> class BObjectList;
class BMenuItem;
namespace BPrivate {
class Model;
class BContainerWindow;
class ModelMenuItem;
class EntryListBase;
class TrackingHookData {
public:
TrackingHookData()
: fTrackingHook(NULL),
fDragMessage(NULL)
{}
bool (*fTrackingHook)(BMenu *, void *);
BMessenger fTarget;
const BMessage *fDragMessage;
};
class BNavMenu : public BSlowMenu {
public:
BNavMenu(const char* title, uint32 message, const BHandler *,
BWindow *parentWindow = NULL, const BObjectList<BString> *list = NULL);
BNavMenu(const char* title, uint32 message, const BMessenger &,
BWindow *parentWindow = NULL, const BObjectList<BString> *list = NULL);
// parentWindow, if specified, will be closed if nav menu item invoked
// with option held down
virtual ~BNavMenu();
virtual void AttachedToWindow();
virtual void DetachedFromWindow();
void SetNavDir(const entry_ref *);
void ForceRebuild();
bool NeedsToRebuild() const;
// will cause menu to get rebuilt next time it is shown
virtual void ResetTargets();
void SetTarget(const BMessenger &);
BMessenger Target();
void SetTypesList(const BObjectList<BString> *list);
const BObjectList<BString> *TypesList() const;
void AddNavDir(const Model *mode, uint32 what, BHandler *target,
bool populateSubmenu);
static int32 GetMaxMenuWidth();
static int CompareFolderNamesFirstOne(const BMenuItem *, const BMenuItem *);
static int CompareOne(const BMenuItem *, const BMenuItem *);
static ModelMenuItem *NewModelItem(Model *, const BMessage *, const BMessenger &,
bool suppressFolderHierarchy=false, BContainerWindow * = NULL,
const BObjectList<BString> *typeslist = NULL,
TrackingHookData *hook = NULL);
TrackingHookData *InitTrackingHook(bool (*hookfunction)(BMenu *, void *),
const BMessenger *target, const BMessage *dragMessage);
protected:
virtual bool StartBuildingItemList();
virtual bool AddNextItem();
virtual void DoneBuildingItemList();
virtual void ClearMenuBuildingState();
void BuildVolumeMenu();
void AddOneItem(Model *);
void AddRootItemsIfNeeded();
static void SetTrackingHookDeep(BMenu *, bool (*)(BMenu *, void *), void *);
entry_ref fNavDir;
BMessage fMessage;
BMessenger fMessenger;
BWindow *fParentWindow;
// menu building state
bool fVolsOnly;
BObjectList<BMenuItem> *fItemList;
EntryListBase *fContainer;
bool fIteratingDesktop;
const BObjectList<BString> *fTypesList;
TrackingHookData fTrackingHook;
};
// Spring Loaded Folder convenience routines
// used in both Tracker and Deskbar
#if B_BEOS_VERSION_DANO
#define _IMPEXP_TRACKER
#endif
_IMPEXP_TRACKER bool SpringLoadedFolderCompareMessages(const BMessage *incoming,
const BMessage *dragmessage);
_IMPEXP_TRACKER void SpringLoadedFolderSetMenuStates(const BMenu *menu,
const BObjectList<BString> *typeslist);
_IMPEXP_TRACKER void SpringLoadedFolderAddUniqueTypeToList(entry_ref *ref,
BObjectList<BString> *typeslist);
_IMPEXP_TRACKER void SpringLoadedFolderCacheDragData(const BMessage *incoming,
BMessage **, BObjectList<BString> **typeslist);
#if B_BEOS_VERSION_DANO
#undef _IMPEXP_TRACKER
#endif
} // namespace BPrivate
using namespace BPrivate;
#endif
+76
View File
@@ -0,0 +1,76 @@
/*
Open Tracker License
Terms and Conditions
Copyright (c) 1991-2000, 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.
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.
*/
#ifndef __SLOW_MENU__
#define __SLOW_MENU__
#include <Menu.h>
#include <MenuItem.h>
#include <Debug.h>
// SlowMenu is a convenience class that makes it easier to
// use the AddDynamicItem callback to implement a menu that can
// checks periodically between creating new items and quits
// early if needed
namespace BPrivate {
class BSlowMenu : public BMenu {
public:
BSlowMenu(const char *title, menu_layout layout = B_ITEMS_IN_COLUMN);
protected:
virtual bool StartBuildingItemList();
// set up state to start building the item list
// returns false if setup failed
virtual bool AddNextItem() = 0;
// returns false if done
virtual void DoneBuildingItemList() = 0;
// default version adds items from itemList to menu and deletes
// the list; override to sort items first, etc.
virtual void ClearMenuBuildingState() = 0;
protected:
virtual bool AddDynamicItem(add_state state);
// this is the callback from BMenu, you shouldn't need to override this
bool fMenuBuilt;
};
} // namespace BPrivate
using namespace BPrivate;
#endif
+560
View File
@@ -0,0 +1,560 @@
/* DeskbarView - main_daemon's deskbar menu and view
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
#include <PopUpMenu.h>
#include <Bitmap.h>
#include <Rect.h>
#include <MenuItem.h>
#include <Window.h>
#include <Messenger.h>
#include <Roster.h>
#include <Resources.h>
#include <Entry.h>
#include <Path.h>
#include <NodeMonitor.h>
#include <VolumeRoster.h>
#include <Directory.h>
#include <FindDirectory.h>
#include <Query.h>
#include <SymLink.h>
#include <NodeInfo.h>
#include <kernel/fs_info.h>
#include <kernel/fs_index.h>
#include <Deskbar.h>
#include <String.h>
#include <stdio.h>
#include <malloc.h>
#include <E-mail.h>
#include <MailSettings.h>
#include <MailDaemon.h>
#include <MDRLanguage.h>
#include "deskbarview.h"
const char *kTrackerSignature = "application/x-vnd.Be-TRAK";
//-----The following #defines get around a bug in get_image_info on ppc---
#if __INTEL__
#define text_part text
#define text_part_size text_size
#else
#define text_part data
#define text_part_size data_size
#endif
extern "C" _EXPORT BView* instantiate_deskbar_item();
status_t our_image(image_info* image)
{
int32 cookie = 0;
status_t ret;
while ((ret = get_next_image_info(0,&cookie,image)) == B_OK)
{
if ((char*)our_image >= (char*)image->text_part &&
(char*)our_image <= (char*)image->text_part + image->text_part_size)
break;
}
return ret;
}
BView* instantiate_deskbar_item(void)
{
return new DeskbarView(BRect(0, 0, 15, 15));
}
//-------------------------------------------------------------------------------
// #pragma mark -
DeskbarView::DeskbarView(BRect frame)
: BView(frame, "mail_daemon", B_FOLLOW_NONE, B_WILL_DRAW | B_PULSE_NEEDED)
, fIcon(NULL)
, fCurrentIconState(NEW_MAIL)
{
}
DeskbarView::DeskbarView(BMessage *message)
: BView(message)
, fIcon(NULL)
, fCurrentIconState(NEW_MAIL)
{
ChangeIcon(NO_MAIL);
}
DeskbarView::~DeskbarView()
{
delete fIcon;
for (int32 i = 0; i < fNewMailQueries.CountItems(); i++)
delete ((BQuery *)(fNewMailQueries.ItemAt(i)));
}
void DeskbarView::AttachedToWindow()
{
if (be_roster->IsRunning("application/x-vnd.Be-POST"))
{
BVolumeRoster volumes;
BVolume volume;
fNewMessages = 0;
while (volumes.GetNextVolume(&volume) == B_OK) {
BQuery *fNewMailQuery = new BQuery;
fNewMailQuery->SetTarget(this);
fNewMailQuery->SetVolume(&volume);
fNewMailQuery->PushAttr(B_MAIL_ATTR_STATUS);
fNewMailQuery->PushString("New");
fNewMailQuery->PushOp(B_EQ);
fNewMailQuery->PushAttr("BEOS:TYPE");
fNewMailQuery->PushString("text/x-email");
fNewMailQuery->PushOp(B_EQ);
fNewMailQuery->PushAttr("BEOS:TYPE");
fNewMailQuery->PushString("text/x-partial-email");
fNewMailQuery->PushOp(B_EQ);
fNewMailQuery->PushOp(B_OR);
fNewMailQuery->PushOp(B_AND);
fNewMailQuery->Fetch();
BEntry entry;
while (fNewMailQuery->GetNextEntry(&entry) == B_OK)
if (entry.InitCheck() == B_OK)
fNewMessages++;
fNewMailQueries.AddItem(fNewMailQuery);
}
ChangeIcon((fNewMessages > 0) ? NEW_MAIL : NO_MAIL);
}
else
{
BDeskbar deskbar;
deskbar.RemoveItem("mail_daemon");
}
}
DeskbarView* DeskbarView::Instantiate(BMessage *data)
{
if (!validate_instantiation(data, "DeskbarView"))
return NULL;
return new DeskbarView(data);
}
status_t DeskbarView::Archive(BMessage *data,bool deep) const
{
BView::Archive(data, deep);
data->AddString("add_on", "application/x-vnd.Be-POST");
return B_NO_ERROR;
}
void DeskbarView::Draw(BRect /*updateRect*/)
{
PushState();
SetHighColor(Parent()->ViewColor());
FillRect(BRect(0.0,0.0,15.0,15.0));
if(fIcon)
{
SetDrawingMode(B_OP_OVER);
DrawBitmap(fIcon,BRect(0.0,0.0,15.0,15.0));
}
PopState();
Sync();
}
status_t OpenFolder(const char* end)
{
BPath path;
find_directory(B_USER_DIRECTORY, &path);
path.Append(end);
entry_ref ref;
if (get_ref_for_path(path.Path(),&ref) != B_OK) return B_NAME_NOT_FOUND;
if (!BEntry(&ref).Exists()) return B_NAME_NOT_FOUND;
BMessage open_mbox(B_REFS_RECEIVED);
open_mbox.AddRef("refs",&ref);
BMessenger tracker("application/x-vnd.Be-TRAK");
tracker.SendMessage(&open_mbox);
return B_OK;
}
void
DeskbarView::MessageReceived(BMessage *message)
{
switch(message->what)
{
case MD_CHECK_SEND_NOW:
// also happens in DeskbarView::MouseUp() with
// B_TERTIARY_MOUSE_BUTTON pressed
BMailDaemon::CheckMail(true);
break;
case MD_CHECK_FOR_MAILS:
BMailDaemon::CheckMail(false,message->FindString("account"));
break;
case MD_SEND_MAILS:
BMailDaemon::SendQueuedMail();
break;
case MD_OPEN_NEW:
{
char *argv[] = {"New Message", "mailto:"};
be_roster->Launch("text/x-email",2,argv);
break;
}
case MD_OPEN_PREFS:
be_roster->Launch("application/x-vnd.Be-mprf");
break;
case B_QUERY_UPDATE:
{
int32 what;
message->FindInt32("opcode",&what);
switch (what) {
case B_ENTRY_CREATED:
fNewMessages++;
break;
case B_ENTRY_REMOVED:
fNewMessages--;
break;
}
ChangeIcon((fNewMessages > 0) ? NEW_MAIL : NO_MAIL);
break;
}
case B_QUIT_REQUESTED:
BMailDaemon::Quit();
break;
case B_REFS_RECEIVED: // open received files in the standard mail application
{
BMessage argv(B_ARGV_RECEIVED);
argv.AddString("argv", "E-mail");
entry_ref ref;
BPath path;
int i = 0;
while (message->FindRef("refs",i++,&ref) == B_OK && path.SetTo(&ref) == B_OK)
{
//fprintf(stderr,"got %s\n", path.Path());
argv.AddString("argv", path.Path());
}
if (i > 1)
{
argv.AddInt32("argc", i);
be_roster->Launch("text/x-email", &argv);
}
break;
}
default:
BView::MessageReceived(message);
}
}
void DeskbarView::ChangeIcon(int32 icon)
{
if(fCurrentIconState == icon)
return;
BBitmap *newIcon(NULL);
image_info info;
if (our_image(&info) == B_OK)
{
BFile file(info.name,B_READ_ONLY);
if (file.InitCheck() < B_OK)
goto err;
BResources rsrc(&file);
size_t len;
const void *data = rsrc.LoadResource('BBMP',icon == NEW_MAIL ? "New" : "Read",&len);
if (len == 0)
goto err;
BMemoryIO stream(data, len);
stream.Seek(0, SEEK_SET);
BMessage archive;
if (archive.Unflatten(&stream) != B_OK)
goto err;
newIcon = new BBitmap(&archive);
}
else
fputs("no image!", stderr);
err:
fCurrentIconState = icon;
delete fIcon;
fIcon = newIcon;
Invalidate();
}
void DeskbarView::Pulse()
{
// Check if mail_daemon is still running
}
void DeskbarView::MouseUp(BPoint pos)
{
if (fLastButtons & B_PRIMARY_MOUSE_BUTTON) {
if (OpenFolder("mail/mailbox") != B_OK)
if (OpenFolder("mail/in") != B_OK)
if (OpenFolder("mail/INBOX") != B_OK)
OpenFolder("mail");
}
if (fLastButtons & B_TERTIARY_MOUSE_BUTTON)
BMailDaemon::CheckMail(true);
}
void DeskbarView::MouseDown(BPoint pos)
{
Looper()->CurrentMessage()->FindInt32("buttons",&fLastButtons);
Looper()->CurrentMessage()->PrintToStream();
if (fLastButtons & B_SECONDARY_MOUSE_BUTTON)
{
ConvertToScreen(&pos);
BPopUpMenu *menu = BuildMenu();
if (menu)
menu->Go(pos,true,true,BRect(pos.x - 2, pos.y - 2, pos.x + 2, pos.y + 2),true);
}
}
bool DeskbarView::CreateMenuLinks(BDirectory &directory,BPath &path)
{
status_t status = directory.SetTo(path.Path());
if (status == B_OK)
return true;
// Check if the directory has to be created (and do it in this case,
// filling it with some standard links). Normally the installer will
// create the directory and fill it with links, so normally this doesn't
// get used.
BEntry entry(path.Path());
if (status != B_ENTRY_NOT_FOUND
|| entry.GetParent(&directory) < B_OK
|| directory.CreateDirectory(path.Leaf(), NULL) < B_OK
|| directory.SetTo(path.Path()) < B_OK)
return false;
BPath targetPath;
find_directory(B_USER_DIRECTORY, &targetPath);
targetPath.Append("mail/in");
directory.CreateSymLink("Open Inbox Folder",targetPath.Path(),NULL);
targetPath.GetParent(&targetPath);
directory.CreateSymLink("Open Mail Folder",targetPath.Path(),NULL);
// create the draft query
BFile file;
if (directory.CreateFile("Open Draft",&file) < B_OK)
return true;
BString string("MAIL:draft==1");
file.WriteAttrString("_trk/qrystr",&string);
string = "E-mail";
file.WriteAttrString("_trk/qryinitmime", &string);
BNodeInfo(&file).SetType("application/x-vnd.Be-query");
return true;
}
void DeskbarView::CreateNewMailQuery(BEntry &query)
{
BFile file(&query, B_READ_WRITE | B_CREATE_FILE);
if(file.InitCheck() != B_OK)
return;
BString string("((" B_MAIL_ATTR_STATUS "==\"[nN][eE][wW]\")&&((BEOS:TYPE==\"text/x-email\")||(BEOS:TYPE==\"text/x-partial-email\")))");
file.WriteAttrString("_trk/qrystr",&string);
string = "E-mail";
file.WriteAttrString("_trk/qryinitmime", &string);
BNodeInfo(&file).SetType("application/x-vnd.Be-query");
}
BPopUpMenu *
DeskbarView::BuildMenu()
{
BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING,false,false);
menu->SetFont(be_plain_font);
menu->AddItem(new BMenuItem(MDR_DIALECT_CHOICE (
"Create New Message","N) 新規メッセージ作成")B_UTF8_ELLIPSIS,
new BMessage(MD_OPEN_NEW)));
menu->AddSeparatorItem();
BMessenger tracker(kTrackerSignature);
BNavMenu *navMenu;
BMenuItem *item;
BMessage *msg;
entry_ref ref;
BPath path;
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
path.Append("Mail/Menu Links");
BDirectory directory;
if (CreateMenuLinks(directory,path))
{
int32 count = 0;
while (directory.GetNextRef(&ref) == B_OK)
{
count++;
path.SetTo(&ref);
// the true here dereferences the symlinks all the way :)
BEntry entry(&ref, true);
// do we want to use the NavMenu, or just an ordinary BMenuItem?
// we are using the NavMenu only for directories and queries
bool useNavMenu = false;
if (entry.InitCheck() == B_OK)
{
if (entry.IsDirectory())
useNavMenu = true;
else if (entry.IsFile())
{
// Files should use the BMenuItem unless they are queries
char mimeString[B_MIME_TYPE_LENGTH];
BNode node(&entry);
BNodeInfo info(&node);
if (info.GetType(mimeString) == B_OK
&& strcmp(mimeString, "application/x-vnd.Be-query") == 0)
useNavMenu = true;
}
//clobber the existing ref only if the symlink derefernces completely,
//otherwise we'll stick with what we have
entry.GetRef(&ref);
}
msg = new BMessage(B_REFS_RECEIVED);
msg->AddRef("refs", &ref);
if (useNavMenu)
{
item = new BMenuItem(navMenu = new BNavMenu(path.Leaf(),B_REFS_RECEIVED,tracker), msg);
navMenu->SetNavDir(&ref);
}
else
item = new BMenuItem(path.Leaf(), msg);
menu->AddItem(item);
if(entry.InitCheck() != B_OK)
item->SetEnabled(false);
}
if (count > 0)
menu->AddSeparatorItem();
}
// The New E-mail query
if (fNewMessages > 0)
{
BString string;
MDR_DIALECT_CHOICE (
string << fNewMessages << " new message" << ((fNewMessages != 1) ? "s" : B_EMPTY_STRING),
string << fNewMessages << " 通の未読メッセージ");
find_directory(B_USER_SETTINGS_DIRECTORY, &path);
path.Append("Mail/New E-mail");
BEntry query(path.Path());
if (!query.Exists())
CreateNewMailQuery(query);
query.GetRef(&ref);
item = new BMenuItem(
navMenu = new BNavMenu(string.String(),B_REFS_RECEIVED,BMessenger(kTrackerSignature)),
msg = new BMessage(B_REFS_RECEIVED));
msg->AddRef("refs", &ref);
navMenu->SetNavDir(&ref);
menu->AddItem(item);
}
else
{
menu->AddItem(item = new BMenuItem(
MDR_DIALECT_CHOICE ("No new messages","未読メッセージなし"), NULL));
item->SetEnabled(false);
}
if (modifiers() & B_SHIFT_KEY)
{
BList list;
GetInboundMailChains(&list);
BMenu *chainMenu = new BMenu(
MDR_DIALECT_CHOICE ("Check For Mails Only","R) メール受信のみ"));
BFont font;
menu->GetFont(&font);
chainMenu->SetFont(&font);
for (int32 i = 0;i < list.CountItems();i++) {
BMailChain *chain = (BMailChain *)list.ItemAt(i);
BMessage *message = new BMessage(MD_CHECK_FOR_MAILS);
message->AddString("account",chain->Name());
chainMenu->AddItem(new BMenuItem(chain->Name(),message));
delete chain;
}
chainMenu->SetTargetForItems(this);
menu->AddItem(new BMenuItem(chainMenu,new BMessage(MD_CHECK_FOR_MAILS)));
// Not used:
// menu->AddItem(new BMenuItem(MDR_DIALECT_CHOICE (
// "Check For Mails Only","メール受信のみ"), new BMessage(MD_CHECK_FOR_MAILS)));
menu->AddItem(new BMenuItem(
MDR_DIALECT_CHOICE ("Send Pending Mails","M) 保留メールを送信"),
new BMessage(MD_SEND_MAILS)));
}
else
menu->AddItem(new BMenuItem(
MDR_DIALECT_CHOICE ("Check For Mail Now","C) メールチェック"),
new BMessage(MD_CHECK_SEND_NOW)));
menu->AddSeparatorItem();
menu->AddItem(new BMenuItem(
MDR_DIALECT_CHOICE ("Edit Preferences","P) メール環境設定") B_UTF8_ELLIPSIS,
new BMessage(MD_OPEN_PREFS)));
menu->AddItem(new BMenuItem(
MDR_DIALECT_CHOICE ("Quit","Q) 終了"),
new BMessage(B_QUIT_REQUESTED)));
// Reset Item Targets (only those which aren't already set)
for (int32 i = menu->CountItems();i-- > 0;)
{
item = menu->ItemAt(i);
if (item && (msg = item->Message()) != NULL)
{
if (msg->what == B_REFS_RECEIVED)
item->SetTarget(tracker);
else
item->SetTarget(this);
}
}
return menu;
}
+64
View File
@@ -0,0 +1,64 @@
#ifndef DESKBAR_VIEW_H
#define DESKBAR_VIEW_H
/* DeskbarView - main_daemon's deskbar menu and view
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
#include <View.h>
#include "NavMenu.h"
enum MDDeskbarIcon {
NO_MAIL = 0,
NEW_MAIL,
};
enum MDDeskbarMessages {
MD_CHECK_SEND_NOW = 'MDra',
MD_CHECK_FOR_MAILS,
MD_SEND_MAILS,
MD_OPEN_NEW,
MD_OPEN_PREFS
};
class BPopUpMenu;
class BQuery;
class BDirectory;
class BEntry;
class BPath;
class _EXPORT DeskbarView : public BView {
public:
DeskbarView (BRect frame);
DeskbarView (BMessage *data);
virtual ~DeskbarView();
virtual void Draw(BRect updateRect);
virtual void AttachedToWindow();
static DeskbarView *Instantiate(BMessage *data);
virtual status_t Archive(BMessage *data, bool deep = true) const;
virtual void MouseDown(BPoint);
virtual void MouseUp(BPoint);
virtual void MessageReceived(BMessage *message);
virtual void Pulse();
void ChangeIcon(int32 icon);
private:
bool CreateMenuLinks(BDirectory &,BPath &);
void CreateNewMailQuery(BEntry &);
BPopUpMenu *BuildMenu();
BBitmap *fIcon;
int32 fCurrentIconState;
BList fNewMailQueries;
int32 fNewMessages;
int32 fLastButtons;
};
#endif /* DESKBAR_VIEW_H */
Binary file not shown.
+736
View File
@@ -0,0 +1,736 @@
/* main - the daemon's inner workings
**
** Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
*/
#include <Application.h>
#include <Message.h>
#include <File.h>
#include <MessageRunner.h>
#include <Deskbar.h>
#include <Roster.h>
#include <Button.h>
#include <StringView.h>
#include <Mime.h>
#include <Beep.h>
#include <fs_index.h>
#include <fs_info.h>
#include <String.h>
#include <VolumeRoster.h>
#include <Query.h>
#include <ChainRunner.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <map>
#include <E-mail.h>
#include <MailSettings.h>
#include <MailMessage.h>
#include <status.h>
#include <StringList.h>
#include "deskbarview.h"
#include "LEDAnimation.h"
#include <MDRLanguage.h>
#ifdef BONE
#include <sys/socket.h>
#include <bone_serial_ppp.h>
#include <unistd.h>
#endif
typedef struct glorbal {
size_t bytes;
BStringList msgs;
} snuzzwut;
BMailStatusWindow *status;
class MailDaemonApp : public BApplication {
public:
MailDaemonApp(void);
virtual ~MailDaemonApp();
virtual void MessageReceived(BMessage *msg);
virtual void RefsReceived(BMessage *a_message);
virtual void Pulse();
virtual bool QuitRequested();
virtual void ReadyToRun();
void InstallDeskbarIcon();
void RemoveDeskbarIcon();
void RunChains(BList &list,BMessage *msg);
void SendPendingMessages(BMessage *msg);
void GetNewMessages(BMessage *msg);
private:
void UpdateAutoCheck(bigtime_t interval);
BMessageRunner *auto_check;
BMailSettings settings_file;
int32 new_messages;
bool central_beep;
// TRUE to do a beep when the status window closes. This happens
// when all mail has been received, so you get one beep for
// everything rather than individual beeps for each mail account.
// Set to TRUE by the 'mcbp' message that the mail Notification
// filter sends us, cleared when the beep is done.
BList fetch_done_respondents;
BList queries;
LEDAnimation *led;
BString alert_string;
};
MailDaemonApp::MailDaemonApp(void)
: BApplication("application/x-vnd.Be-POST")
{
status = new BMailStatusWindow(BRect(40, 400, 360, 400), "Mail Status",
settings_file.ShowStatusWindow());
auto_check = NULL;
}
MailDaemonApp::~MailDaemonApp()
{
delete auto_check;
for (int32 i = 0; i < queries.CountItems(); i++)
delete ((BQuery *)(queries.ItemAt(i)));
delete led;
}
void
MailDaemonApp::ReadyToRun()
{
InstallDeskbarIcon();
UpdateAutoCheck(settings_file.AutoCheckInterval());
BVolume volume;
BVolumeRoster roster;
new_messages = 0;
while (roster.GetNextVolume(&volume) == B_OK) {
//{char name[255];volume.GetName(name);printf("Volume: %s\n",name);}
BQuery *query = new BQuery;
query->SetTarget(this);
query->SetVolume(&volume);
query->PushAttr(B_MAIL_ATTR_STATUS);
query->PushString("New");
query->PushOp(B_EQ);
query->PushAttr("BEOS:TYPE");
query->PushString("text/x-email");
query->PushOp(B_EQ);
query->PushAttr("BEOS:TYPE");
query->PushString("text/x-partial-email");
query->PushOp(B_EQ);
query->PushOp(B_OR);
query->PushOp(B_AND);
query->Fetch();
BEntry entry;
for (; query->GetNextEntry(&entry) == B_OK; new_messages++);
queries.AddItem(query);
}
BString string;
MDR_DIALECT_CHOICE(
if (new_messages > 0)
string << new_messages;
else
string << "No";
if (new_messages != 1)
string << " new messages.";
else
string << " new message.";,
if (new_messages > 0)
string << new_messages << " 通の未読メッセージがあります ";
else
string << "未読メッセージはありません";
);
central_beep = false;
status->SetDefaultMessage(string);
led = new LEDAnimation;
SetPulseRate(1000000);
}
void
MailDaemonApp::RefsReceived(BMessage *message)
{
status->Activate(true);
entry_ref ref;
for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) {
BNode node(&ref);
if (node.InitCheck() < B_OK)
continue;
BString uid;
if (node.ReadAttrString("MAIL:unique_id", &uid) < 0)
continue;
int32 id;
if (node.ReadAttr("MAIL:chain", B_INT32_TYPE, 0, &id, sizeof(id)) < 0)
continue;
int32 size;
if (node.ReadAttr("MAIL:fullsize", B_SIZE_T_TYPE, 0, &size, sizeof(size)) < 0)
size = -1;
BPath path(&ref);
BMailChainRunner *runner = GetMailChainRunner(id, status);
runner->GetSingleMessage(uid.String(), size, &path);
}
}
void
MailDaemonApp::UpdateAutoCheck(bigtime_t interval)
{
if (interval > 0) {
if (auto_check != NULL) {
auto_check->SetInterval(interval);
auto_check->SetCount(-1);
} else
auto_check = new BMessageRunner(be_app_messenger,new BMessage('moto'),interval);
} else {
delete auto_check;
auto_check = NULL;
}
}
void
MailDaemonApp::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case 'moto':
if (settings_file.CheckOnlyIfPPPUp()) {
#ifdef BONE
int s = socket(AF_INET, SOCK_DGRAM, 0);
bsppp_status_t status;
strcpy(status.if_name, "ppp0");
if (ioctl(s, BONE_SERIAL_PPP_GET_STATUS, &status, sizeof(status)) != 0) {
close(s);
break;
} else {
if (status.connection_status != BSPPP_CONNECTED) {
close(s);
break;
}
}
close (s);
#else
if (find_thread("tty_thread") <= 0)
break;
#endif
}
// supposed to fall through
case 'mbth': // check & send messages
msg->what = 'msnd';
PostMessage(msg); //'msnd');
// supposed to fall trough
case 'mnow': // check messages
GetNewMessages(msg);
break;
case 'msnd': // send messages
SendPendingMessages(msg);
break;
case 'mrrs':
settings_file.Reload();
UpdateAutoCheck(settings_file.AutoCheckInterval());
status->SetShowCriterion(settings_file.ShowStatusWindow());
break;
case 'shst': // when to show the status window
{
int32 mode;
if (msg->FindInt32("ShowStatusWindow",&mode) == B_OK)
status->SetShowCriterion(mode);
break;
}
case 'lkch': // status window look changed
case 'wsch': // workspace changed
status->PostMessage(msg);
break;
case 'stwg': //----StaT Window Gone
{
BMessage *msg, reply('mnuc');
reply.AddInt32("num_new_messages",new_messages);
while(msg = (BMessage *)fetch_done_respondents.RemoveItem(0L)) {
msg->SendReply(&reply);
delete msg;
}
}
if (alert_string != B_EMPTY_STRING) {
alert_string.Truncate(alert_string.Length()-1);
BAlert *alert = new BAlert(MDR_DIALECT_CHOICE ("New Messages","新着メッセージ"), alert_string.String(), "OK", NULL, NULL, B_WIDTH_AS_USUAL);
alert->SetFeel(B_NORMAL_WINDOW_FEEL);
alert->Go(NULL);
alert_string = B_EMPTY_STRING;
}
if (central_beep) {
system_beep("New E-mail");
central_beep = false;
}
break;
case 'mcbp':
if (new_messages > 0) {
central_beep = true;
}
break;
case 'mnum': //----Number of new messages
{
BMessage reply('mnuc' /* Mail NU message Count */);
if (msg->FindBool("wait_for_fetch_done")) {
fetch_done_respondents.AddItem(DetachCurrentMessage());
break;
}
reply.AddInt32("num_new_messages",new_messages);
msg->SendReply(&reply);
}
break;
case 'mblk': //-----Mail BLinK
if (new_messages > 0)
led->Start();
break;
case 'enda': //-----End Auto Check
delete auto_check;
auto_check = NULL;
break;
case 'numg':
{
int32 num_messages = msg->FindInt32("num_messages");
MDR_DIALECT_CHOICE (
alert_string << num_messages << " new message";
if (num_messages > 1)
alert_string << 's';
alert_string << " for " << msg->FindString("chain_name") << '\n';,
alert_string << msg->FindString("chain_name") << "より\n" << num_messages
<< " 通のメッセージが届きました  ";
);
}
break;
case B_QUERY_UPDATE:
{
int32 what;
msg->FindInt32("opcode",&what);
switch (what) {
case B_ENTRY_CREATED:
new_messages++;
break;
case B_ENTRY_REMOVED:
new_messages--;
break;
}
BString string;
MDR_DIALECT_CHOICE (
if (new_messages > 0)
string << new_messages;
else
string << "No";
if (new_messages != 1)
string << " new messages.";
else
string << " new message.";,
if (new_messages > 0)
string << new_messages << " 通の未読メッセージがあります";
else
string << "未読メッセージはありません";
);
status->SetDefaultMessage(string.String());
}
break;
}
BApplication::MessageReceived(msg);
}
void
MailDaemonApp::InstallDeskbarIcon()
{
BDeskbar deskbar;
if (!deskbar.HasItem("mail_daemon")) {
BRoster roster;
entry_ref ref;
status_t status = roster.FindApp("application/x-vnd.Be-POST", &ref);
if (status < B_OK) {
fprintf(stderr, "Can't find application to tell deskbar: %s\n", strerror(status));
return;
}
status = deskbar.AddItem(&ref);
if (status < B_OK) {
fprintf(stderr, "Can't add deskbar replicant: %s\n", strerror(status));
return;
}
}
}
void
MailDaemonApp::RemoveDeskbarIcon()
{
BDeskbar deskbar;
if (deskbar.HasItem("mail_daemon"))
deskbar.RemoveItem("mail_daemon");
}
bool
MailDaemonApp::QuitRequested()
{
RemoveDeskbarIcon();
return true;
}
void
MailDaemonApp::RunChains(BList &list, BMessage *msg)
{
BMailChain *chain;
int32 index = 0, id;
for (; msg->FindInt32("chain", index, &id) == B_OK; index++) {
for (int32 i = 0; i < list.CountItems(); i++) {
chain = (BMailChain *)list.ItemAt(i);
if (chain->ID() == id) {
chain->RunChain(status, true, false, true);
list.RemoveItem(i); // the chain runner deletes the chain
break;
}
}
}
if (index == 0) {
// invoke all chains
for (int32 i = 0; i < list.CountItems(); i++) {
chain = (BMailChain *)list.ItemAt(i);
chain->RunChain(status, true, false, true);
}
} else {
// delete unused chains
for (int32 i = list.CountItems(); i-- > 0;)
delete (BMailChain *)list.RemoveItem(i);
}
}
void
MailDaemonApp::GetNewMessages(BMessage *msg)
{
BList list;
GetInboundMailChains(&list);
RunChains(list,msg);
}
void
MailDaemonApp::SendPendingMessages(BMessage *msg)
{
BVolumeRoster roster;
BVolume volume;
while (roster.GetNextVolume(&volume) == B_OK) {
BQuery query;
query.SetVolume(&volume);
query.PushAttr(B_MAIL_ATTR_FLAGS);
query.PushInt32(B_MAIL_PENDING);
query.PushOp(B_EQ);
query.PushAttr(B_MAIL_ATTR_FLAGS);
query.PushInt32(B_MAIL_PENDING | B_MAIL_SAVE);
query.PushOp(B_EQ);
query.PushOp(B_OR);
int32 chain_id = -1;
if (msg->FindInt32("chain",&chain_id) == B_OK) {
query.PushAttr("MAIL:chain");
query.PushInt32(chain_id);
query.PushOp(B_EQ);
query.PushOp(B_AND);
} else {
chain_id = -1;
}
if (!msg->HasString("message_path")) {
if (chain_id == -1) {
map <int32, snuzzwut *> messages;
query.Fetch();
BEntry entry;
BPath path;
BNode node;
int32 chain, default_chain(BMailSettings().DefaultOutboundChainID());
off_t size;
while (query.GetNextEntry(&entry) == B_OK) {
while (node.SetTo(&entry) == B_BUSY) snooze(100);
if (node.ReadAttr("MAIL:chain",B_INT32_TYPE,0,&chain,4) < B_OK)
chain = default_chain;
entry.GetPath(&path);
node.GetSize(&size);
if (messages[chain] == NULL) {
messages[chain] = new snuzzwut;
messages[chain]->bytes = 0;
}
messages[chain]->msgs += path.Path();
messages[chain]->bytes += size;
}
map<int32,snuzzwut *>::iterator iter = messages.begin();
map<int32,snuzzwut *>::iterator end = messages.end();
while (iter != end) {
if ((iter->first > 0) && (BMailChain(iter->first).ChainDirection() == outbound)) {
BMailChainRunner *runner = GetMailChainRunner(iter->first,status);
runner->GetMessages(&messages[iter->first]->msgs,messages[iter->first]->bytes);
delete messages[iter->first];
runner->Stop();
}
iter++;
}
} else {
BStringList ids;
size_t bytes = 0;
query.Fetch();
BEntry entry;
BPath path;
BNode node;
off_t size;
while (query.GetNextEntry(&entry) == B_OK) {
node.SetTo(&entry);
entry.GetPath(&path);
node.GetSize(&size);
ids += path.Path();
bytes += size;
}
BMailChainRunner *runner = GetMailChainRunner(chain_id,status);
runner->GetMessages(&ids,bytes);
runner->Stop();
}
} else {
const char *path;
msg->FindString("message_path",&path);
BStringList ids;
ids += path;
off_t size;
BNode(path).GetSize(&size);
BMailChainRunner *runner = GetMailChainRunner(chain_id,status);
runner->GetMessages(&ids,size);
runner->Stop();
}
}
}
void
MailDaemonApp::Pulse()
{
bigtime_t idle = idle_time();
if (led->IsRunning() && (idle < 100000))
led->Stop();
}
// #pragma mark -
void
makeIndices()
{
const char *stringIndices[] = { B_MAIL_ATTR_ACCOUNT,B_MAIL_ATTR_CC,
B_MAIL_ATTR_FROM,B_MAIL_ATTR_NAME,
B_MAIL_ATTR_PRIORITY,B_MAIL_ATTR_REPLY,
B_MAIL_ATTR_STATUS,B_MAIL_ATTR_SUBJECT,
B_MAIL_ATTR_TO,B_MAIL_ATTR_THREAD, NULL};
// add mail indices for all devices capable of querying
int32 cookie = 0;
dev_t device;
while ((device = next_dev(&cookie)) >= B_OK) {
fs_info info;
if (fs_stat_dev(device,&info) < 0 || (info.flags & B_FS_HAS_QUERY) == 0)
continue;
// Work-around for misbehaviour of earlier versions - should be
// kept in for some time.
// It removes the B_MAIL_ATTR_FLAGS if it is of B_STRING_TYPE,
// because that's what the MDR created before...
index_info indexInfo;
if (fs_stat_index(device, B_MAIL_ATTR_FLAGS, &indexInfo) == 0
&& indexInfo.type == B_STRING_TYPE)
fs_remove_index(device, B_MAIL_ATTR_FLAGS);
for (int32 i = 0;stringIndices[i];i++)
fs_create_index(device,stringIndices[i],B_STRING_TYPE,0);
fs_create_index(device,"MAIL:draft", B_INT32_TYPE, 0);
fs_create_index(device,B_MAIL_ATTR_WHEN,B_INT32_TYPE,0);
fs_create_index(device,B_MAIL_ATTR_FLAGS,B_INT32_TYPE,0);
fs_create_index(device,"MAIL:chain",B_INT32_TYPE,0);
//fs_create_index(device,"MAIL:fullsize",B_UINT32_TYPE,0);
}
}
void
addAttribute(BMessage &msg,char *name,char *publicName,int32 type = B_STRING_TYPE,bool viewable = true,bool editable = false,int32 width = 200)
{
msg.AddString("attr:name",name);
msg.AddString("attr:public_name",publicName);
msg.AddInt32("attr:type",type);
msg.AddBool("attr:viewable",viewable);
msg.AddBool("attr:editable",editable);
msg.AddInt32("attr:width",width);
msg.AddInt32("attr:alignment",B_ALIGN_LEFT);
}
void
makeMimeType(bool remakeMIMETypes)
{
// Add MIME database entries for the e-mail file types we handle. Either
// do a full rebuild from nothing, or just add on the new attributes that
// we support which the regular BeOS mail daemon didn't have.
const char *types[2] = {"text/x-email","text/x-partial-email"};
BMimeType mime;
BMessage info;
for (int i = 0; i < 2; i++) {
info.MakeEmpty();
mime.SetTo(types[i]);
if (mime.InitCheck() != B_OK) {
fputs("could not init mime type.\n",stderr);
return;
}
if (!mime.IsInstalled() || remakeMIMETypes) {
// install the full mime type
mime.Delete ();
mime.Install();
// Set up the list of e-mail related attributes that Tracker will
// let you display in columns for e-mail messages.
addAttribute(info,B_MAIL_ATTR_NAME,"Name");
addAttribute(info,B_MAIL_ATTR_SUBJECT,"Subject");
addAttribute(info,B_MAIL_ATTR_TO,"To");
addAttribute(info,B_MAIL_ATTR_CC,"Cc");
addAttribute(info,B_MAIL_ATTR_FROM,"From");
addAttribute(info,B_MAIL_ATTR_REPLY,"Reply To");
addAttribute(info,B_MAIL_ATTR_STATUS,"Status");
addAttribute(info,B_MAIL_ATTR_PRIORITY,"Priority",B_STRING_TYPE,true,true,40);
addAttribute(info,B_MAIL_ATTR_WHEN,"When",B_TIME_TYPE,true,false,150);
addAttribute(info,B_MAIL_ATTR_THREAD,"Thread");
addAttribute(info,B_MAIL_ATTR_ACCOUNT,"Account",B_STRING_TYPE,true,false,100);
mime.SetAttrInfo(&info);
if (i == 0) {
mime.SetShortDescription("E-mail");
mime.SetLongDescription("Electronic Mail Message");
mime.SetPreferredApp("application/x-vnd.Be-MAIL");
} else {
mime.SetShortDescription("Partial E-mail");
mime.SetLongDescription("A Partially Downloaded E-mail");
mime.SetPreferredApp("application/x-vnd.Be-POST");
}
} else {
// Just add the e-mail related attribute types we use to the MIME system.
mime.GetAttrInfo(&info);
bool hasAccount = false, hasThread = false, hasSize = false;
const char *result;
for (int32 index = 0;info.FindString("attr:name",index,&result) == B_OK;index++) {
if (!strcmp(result,B_MAIL_ATTR_ACCOUNT))
hasAccount = true;
if (!strcmp(result,B_MAIL_ATTR_THREAD))
hasThread = true;
if (!strcmp(result,"MAIL:fullsize"))
hasSize = true;
}
if (!hasAccount)
addAttribute(info,B_MAIL_ATTR_ACCOUNT,"Account",B_STRING_TYPE,true,false,100);
if (!hasThread)
addAttribute(info,B_MAIL_ATTR_THREAD,"Thread");
/*if (!hasSize)
addAttribute(info,"MAIL:fullsize","Message Size",B_SIZE_T_TYPE,true,false,100);*/
//--- Tracker can't display SIZT attributes. What a pain.
if (!hasAccount || !hasThread/* || !hasSize*/)
mime.SetAttrInfo(&info);
}
mime.Unset();
}
}
int
main(int argc, const char **argv)
{
bool remakeMIMETypes = false;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-E") == 0) {
if (!BMailSettings().DaemonAutoStarts())
return 0;
}
if (strcmp(argv[i], "-M") == 0) {
remakeMIMETypes = true;
}
}
MailDaemonApp app;
// install MimeTypes, attributes, indices, and the
// system beep add startup
makeMimeType(remakeMIMETypes);
makeIndices();
add_system_beep_event("New E-mail");
be_app->Run();
return 0;
}