xref: /haiku/src/apps/mail/Prefs.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2001, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN
23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 BeMail(TM), Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or
30 registered trademarks of Be Incorporated in the United States and other
31 countries. Other brand product names are registered trademarks or trademarks
32 of their respective holders. All rights reserved.
33 */
34 
35 
36 #include "Prefs.h"
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <strings.h>
41 
42 #include <Application.h>
43 #include <CharacterSet.h>
44 #include <CharacterSetRoster.h>
45 #include <E-mail.h>
46 #include <GridView.h>
47 #include <LayoutBuilder.h>
48 #include <InterfaceKit.h>
49 #include <Locale.h>
50 #include <MailSettings.h>
51 #include <mail_encoding.h>
52 #include <StorageKit.h>
53 #include <String.h>
54 
55 using namespace BPrivate;
56 
57 #include "MailApp.h"
58 #include "MailSupport.h"
59 #include "MailWindow.h"
60 #include "Messages.h"
61 #include "Settings.h"
62 #include "Signature.h"
63 
64 
65 #define B_TRANSLATION_CONTEXT "Mail"
66 
67 enum P_MESSAGES {
68 	P_OK = 128, P_CANCEL, P_REVERT, P_FONT,
69 	P_SIZE, P_LEVEL, P_WRAP, P_ATTACH_ATTRIBUTES,
70 	P_SIG, P_ENC, P_WARN_UNENCODABLE,
71 	P_SPELL_CHECK_START_ON, P_BUTTON_BAR,
72 	P_ACCOUNT, P_REPLYTO, P_REPLY_PREAMBLE,
73 	P_COLORED_QUOTES, P_MARK_READ
74 };
75 
76 
77 static inline void
78 add_menu_to_layout(BMenuField* menu, BGridLayout* layout, int32& row)
79 {
80 	menu->SetAlignment(B_ALIGN_RIGHT);
81 	layout->AddItem(menu->CreateLabelLayoutItem(), 0, row);
82 	layout->AddItem(menu->CreateMenuBarLayoutItem(), 1, row, 2);
83 	row++;
84 }
85 
86 
87 // #pragma mark -
88 
89 
90 TPrefsWindow::TPrefsWindow(BPoint leftTop, BFont* font, int32* level,
91 	bool* wrap, bool* attachAttributes, bool* cquotes, int32* account,
92 	int32* replyTo, char** preamble, char** sig, uint32* encoding,
93 	bool* warnUnencodable, bool* spellCheckStartOn, bool* autoMarkRead,
94 	uint8* buttonBar)
95 	:
96 	BWindow(BRect(leftTop.x, leftTop.y, leftTop.x + 100, leftTop.y + 100),
97 		B_TRANSLATE("Mail settings"),
98 		B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE
99 			| B_AUTO_UPDATE_SIZE_LIMITS),
100 
101 	fNewWrap(wrap),
102 	fWrap(*fNewWrap),
103 
104 	fNewAttachAttributes(attachAttributes),
105 	fAttachAttributes(*fNewAttachAttributes),
106 
107 	fNewButtonBar(buttonBar),
108 	fButtonBar(*fNewButtonBar),
109 
110 	fNewColoredQuotes(cquotes),
111 	fColoredQuotes(*fNewColoredQuotes),
112 
113 	fNewAccount(account),
114 	fAccount(*fNewAccount),
115 
116 	fNewReplyTo(replyTo),
117 	fReplyTo(*fNewReplyTo),
118 
119 	fNewPreamble(preamble),
120 
121 	fNewSignature(sig),
122 	fSignature((char*)malloc(strlen(*fNewSignature) + 1)),
123 
124 	fNewFont(font),
125 	fFont(*fNewFont),
126 
127 	fNewEncoding(encoding),
128 	fEncoding(*fNewEncoding),
129 
130 	fNewWarnUnencodable(warnUnencodable),
131 	fWarnUnencodable(*fNewWarnUnencodable),
132 
133 	fNewSpellCheckStartOn(spellCheckStartOn),
134 	fSpellCheckStartOn(*fNewSpellCheckStartOn),
135 
136 	fNewAutoMarkRead(autoMarkRead),
137 	fAutoMarkRead(*autoMarkRead)
138 {
139 	strcpy(fSignature, *fNewSignature);
140 
141 	BMenuField* menu;
142 
143 	// group boxes
144 
145 	BGridView* interfaceView = new BGridView();
146 	BGridLayout* interfaceLayout = interfaceView->GridLayout();
147 	BGridView* mailView = new BGridView();
148 	BGridLayout* mailLayout = mailView->GridLayout();
149 
150 	interfaceLayout->SetInsets(B_USE_DEFAULT_SPACING);
151 	interfaceLayout->AlignLayoutWith(mailLayout, B_HORIZONTAL);
152 	mailLayout->SetInsets(B_USE_DEFAULT_SPACING);
153 
154 	BBox* interfaceBox = new BBox(B_FANCY_BORDER, interfaceView);
155 	interfaceBox->SetLabel(B_TRANSLATE("User interface"));
156 	BBox* mailBox = new BBox(B_FANCY_BORDER, mailView);
157 	mailBox->SetLabel(B_TRANSLATE("Mailing"));
158 
159 	// revert, ok & cancel
160 
161 	BButton* okButton = new BButton("ok", B_TRANSLATE("OK"),
162 		new BMessage(P_OK));
163 	okButton->MakeDefault(true);
164 
165 	BButton* cancelButton = new BButton("cancel", B_TRANSLATE("Cancel"),
166 		new BMessage(P_CANCEL));
167 
168 	fRevert = new BButton("revert", B_TRANSLATE("Revert"),
169 		new BMessage(P_REVERT));
170 	fRevert->SetEnabled(false);
171 
172 	// User Interface
173 	int32 layoutRow = 0;
174 
175 	fButtonBarMenu = _BuildButtonBarMenu(*buttonBar);
176 	menu = new BMenuField("bar", B_TRANSLATE("Button bar:"), fButtonBarMenu);
177 	add_menu_to_layout(menu, interfaceLayout, layoutRow);
178 
179 	fFontMenu = _BuildFontMenu(font);
180 	menu = new BMenuField("font", B_TRANSLATE("Font:"), fFontMenu);
181 	add_menu_to_layout(menu, interfaceLayout, layoutRow);
182 
183 	fSizeMenu = _BuildSizeMenu(font);
184 	menu = new BMenuField("size", B_TRANSLATE("Size:"), fSizeMenu);
185 	add_menu_to_layout(menu, interfaceLayout, layoutRow);
186 
187 	fColoredQuotesMenu = _BuildColoredQuotesMenu(fColoredQuotes);
188 	menu = new BMenuField("cquotes", B_TRANSLATE("Colored quotes:"),
189 		fColoredQuotesMenu);
190 	add_menu_to_layout(menu, interfaceLayout, layoutRow);
191 
192 	fSpellCheckStartOnMenu = _BuildSpellCheckStartOnMenu(fSpellCheckStartOn);
193 	menu = new BMenuField("spellCheckStartOn",
194 		B_TRANSLATE("Initial spell check mode:"),
195 		fSpellCheckStartOnMenu);
196 	add_menu_to_layout(menu, interfaceLayout, layoutRow);
197 
198 	fAutoMarkReadMenu = _BuildAutoMarkReadMenu(fAutoMarkRead);
199 	menu = new BMenuField("autoMarkRead",
200 		B_TRANSLATE("Automatically mark mail as read:"),
201 		fAutoMarkReadMenu);
202 	add_menu_to_layout(menu, interfaceLayout, layoutRow);
203 	// Mail Accounts
204 
205 	layoutRow = 0;
206 
207 	fAccountMenu = _BuildAccountMenu(fAccount);
208 	menu = new BMenuField("account", B_TRANSLATE("Default account:"),
209 		fAccountMenu);
210 	add_menu_to_layout(menu, mailLayout, layoutRow);
211 
212 	fReplyToMenu = _BuildReplyToMenu(fReplyTo);
213 	menu = new BMenuField("replyTo", B_TRANSLATE("Reply account:"),
214 		fReplyToMenu);
215 	add_menu_to_layout(menu, mailLayout, layoutRow);
216 
217 	// Mail Contents
218 
219 	fReplyPreamble = new BTextControl("replytext",
220 		B_TRANSLATE("Reply preamble:"),
221 		*preamble, new BMessage(P_REPLY_PREAMBLE));
222 	fReplyPreamble->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
223 
224 	fReplyPreambleMenu = _BuildReplyPreambleMenu();
225 	menu = new BMenuField("replyPreamble", NULL, fReplyPreambleMenu);
226 	menu->SetExplicitMaxSize(BSize(menu->MinSize().width, B_SIZE_UNSET));
227 
228 	mailLayout->AddItem(fReplyPreamble->CreateLabelLayoutItem(), 0, layoutRow);
229 	mailLayout->AddItem(fReplyPreamble->CreateTextViewLayoutItem(), 1,
230 		layoutRow);
231 	mailLayout->AddView(menu, 2, layoutRow);
232 	layoutRow++;
233 
234 	fSignatureMenu = _BuildSignatureMenu(*sig);
235 	menu = new BMenuField("sig", B_TRANSLATE("Auto signature:"),
236 		fSignatureMenu);
237 	add_menu_to_layout(menu, mailLayout, layoutRow);
238 
239 	fEncodingMenu = _BuildEncodingMenu(fEncoding);
240 	menu = new BMenuField("enc", B_TRANSLATE("Encoding:"), fEncodingMenu);
241 	add_menu_to_layout(menu, mailLayout, layoutRow);
242 
243 	fWarnUnencodableMenu = _BuildWarnUnencodableMenu(fWarnUnencodable);
244 	menu = new BMenuField("warnUnencodable", B_TRANSLATE("Warn unencodable:"),
245 		fWarnUnencodableMenu);
246 	add_menu_to_layout(menu, mailLayout, layoutRow);
247 
248 	fWrapMenu = _BuildWrapMenu(*wrap);
249 	menu = new BMenuField("wrap", B_TRANSLATE("Text wrapping:"), fWrapMenu);
250 	add_menu_to_layout(menu, mailLayout, layoutRow);
251 
252 	fAttachAttributesMenu = _BuildAttachAttributesMenu(*attachAttributes);
253 	menu = new BMenuField("attachAttributes", B_TRANSLATE("Attach attributes:"),
254 		fAttachAttributesMenu);
255 	add_menu_to_layout(menu, mailLayout, layoutRow);
256 
257 	BLayoutBuilder::Group<>(this, B_VERTICAL)
258 		.Add(interfaceBox)
259 		.Add(mailBox)
260 		.AddGroup(B_HORIZONTAL)
261 			.Add(fRevert)
262 			.AddGlue()
263 			.Add(cancelButton)
264 			.Add(okButton)
265 		.End()
266 		.SetInsets(B_USE_WINDOW_SPACING);
267 
268 	Show();
269 }
270 
271 
272 TPrefsWindow::~TPrefsWindow()
273 {
274 	BMessage msg(WINDOW_CLOSED);
275 	msg.AddInt32("kind", PREFS_WINDOW);
276 	msg.AddPoint("window pos", Frame().LeftTop());
277 	be_app->PostMessage(&msg);
278 }
279 
280 
281 void
282 TPrefsWindow::MessageReceived(BMessage* msg)
283 {
284 	bool revert = true;
285 	const char* family;
286 	const char* signature;
287 	const char* style;
288 	char label[256];
289 	int32 new_size;
290 	int32 old_size;
291 	font_family new_family;
292 	font_family old_family;
293 	font_style new_style;
294 	font_style old_style;
295 	BMenuItem* item;
296 	BMessage message;
297 
298 	switch (msg->what) {
299 		case P_OK:
300 			if (strcmp(fReplyPreamble->Text(), *fNewPreamble)) {
301 				free(*fNewPreamble);
302 				*fNewPreamble
303 					= (char *)malloc(strlen(fReplyPreamble->Text()) + 1);
304 				strcpy(*fNewPreamble, fReplyPreamble->Text());
305 			}
306 			be_app->PostMessage(PREFS_CHANGED);
307 			Quit();
308 			break;
309 
310 		case P_CANCEL:
311 			revert = false;
312 			// supposed to fall through
313 		case P_REVERT:
314 			fFont.GetFamilyAndStyle(&old_family, &old_style);
315 			fNewFont->GetFamilyAndStyle(&new_family, &new_style);
316 			old_size = (int32)fFont.Size();
317 			new_size = (int32)fNewFont->Size();
318 			if (strcmp(old_family, new_family) || strcmp(old_style, new_style)
319 				|| old_size != new_size) {
320 				fNewFont->SetFamilyAndStyle(old_family, old_style);
321 				if (revert) {
322 					sprintf(label, "%s %s", old_family, old_style);
323 					item = fFontMenu->FindItem(label);
324 					if (item != NULL)
325 						item->SetMarked(true);
326 				}
327 
328 				fNewFont->SetSize(old_size);
329 				if (revert) {
330 					sprintf(label, "%" B_PRId32, old_size);
331 					item = fSizeMenu->FindItem(label);
332 					if (item != NULL)
333 						item->SetMarked(true);
334 				}
335 				message.what = M_FONT;
336 				be_app->PostMessage(&message);
337 			}
338 			*fNewWrap = fWrap;
339 			*fNewAttachAttributes = fAttachAttributes;
340 
341 			if (strcmp(fSignature, *fNewSignature)) {
342 				free(*fNewSignature);
343 				*fNewSignature = (char*)malloc(strlen(fSignature) + 1);
344 				strcpy(*fNewSignature, fSignature);
345 			}
346 
347 			*fNewEncoding = fEncoding;
348 			*fNewWarnUnencodable = fWarnUnencodable;
349 			*fNewSpellCheckStartOn = fSpellCheckStartOn;
350 			*fNewAutoMarkRead = fAutoMarkRead;
351 			*fNewButtonBar = fButtonBar;
352 
353 			be_app->PostMessage(PREFS_CHANGED);
354 
355 			if (revert) {
356 				for (int i = fAccountMenu->CountItems(); --i > 0;) {
357 					BMenuItem *item = fAccountMenu->ItemAt(i);
358 					BMessage* itemMessage = item->Message();
359 					if (itemMessage != NULL
360 						&& itemMessage->FindInt32("id") == *(int32 *)&fAccount) {
361 						item->SetMarked(true);
362 						break;
363 					}
364 				}
365 
366 				strcpy(label,fReplyTo == ACCOUNT_USE_DEFAULT
367 					? B_TRANSLATE("Use default account")
368 					: B_TRANSLATE("Account from mail"));
369 				if ((item = fReplyToMenu->FindItem(label)) != NULL)
370 					item->SetMarked(true);
371 
372 				strcpy(label, fWrap ? B_TRANSLATE("On") : B_TRANSLATE("Off"));
373 				if ((item = fWrapMenu->FindItem(label)) != NULL)
374 					item->SetMarked(true);
375 
376 				strcpy(label, fAttachAttributes
377 					? B_TRANSLATE("Include file attributes in attachments")
378 					: B_TRANSLATE("No file attributes, just plain data"));
379 				if ((item = fAttachAttributesMenu->FindItem(label)) != NULL)
380 					item->SetMarked(true);
381 
382 				strcpy(label, fColoredQuotes ? B_TRANSLATE("On") : B_TRANSLATE("Off"));
383 				if ((item = fColoredQuotesMenu->FindItem(label)) != NULL)
384 					item->SetMarked(true);
385 
386 				if (strcmp(fReplyPreamble->Text(), *fNewPreamble))
387 					fReplyPreamble->SetText(*fNewPreamble);
388 
389 				item = fSignatureMenu->FindItem(fSignature);
390 				if (item)
391 					item->SetMarked(true);
392 
393 				uint32 index = 0;
394 				while ((item = fEncodingMenu->ItemAt(index++)) != NULL) {
395 					BMessage* itemMessage = item->Message();
396 					if (itemMessage == NULL)
397 						continue;
398 
399 					int32 encoding;
400 					if (itemMessage->FindInt32("encoding", &encoding) == B_OK
401 						&& (uint32)encoding == *fNewEncoding) {
402 						item->SetMarked(true);
403 						break;
404 					}
405 				}
406 
407 				strcpy(label, fWarnUnencodable ? B_TRANSLATE("On") : B_TRANSLATE("Off"));
408 				if ((item = fWarnUnencodableMenu->FindItem(label)) != NULL)
409 					item->SetMarked(true);
410 
411 				strcpy(label, fSpellCheckStartOn ? B_TRANSLATE("On") : B_TRANSLATE("Off"));
412 				if ((item = fSpellCheckStartOnMenu->FindItem(label)) != NULL)
413 					item->SetMarked(true);
414 			} else
415 				Quit();
416 			break;
417 
418 		case P_FONT:
419 			family = NULL;
420 			style = NULL;
421 			int32 family_menu_index;
422 			if (msg->FindString("font", &family) == B_OK) {
423 				msg->FindString("style", &style);
424 				fNewFont->SetFamilyAndStyle(family, style);
425 				message.what = M_FONT;
426 				be_app->PostMessage(&message);
427 			}
428 
429 			/* grab this little tidbit so we can set the correct Family */
430 			if (msg->FindInt32("parent_index", &family_menu_index) == B_OK)
431 				fFontMenu->ItemAt(family_menu_index)->SetMarked(true);
432 			break;
433 
434 		case P_SIZE:
435 			old_size = (int32) fNewFont->Size();
436 			msg->FindInt32("size", &new_size);
437 			if (old_size != new_size) {
438 				fNewFont->SetSize(new_size);
439 				message.what = M_FONT;
440 				be_app->PostMessage(&message);
441 			}
442 			break;
443 
444 		case P_WRAP:
445 			msg->FindBool("wrap", fNewWrap);
446 			break;
447 		case P_ATTACH_ATTRIBUTES:
448 			msg->FindBool("attachAttributes", fNewAttachAttributes);
449 			break;
450 		case P_COLORED_QUOTES:
451 			msg->FindBool("cquotes", fNewColoredQuotes);
452 			break;
453 		case P_ACCOUNT:
454 			msg->FindInt32("id",(int32*)fNewAccount);
455 			break;
456 		case P_REPLYTO:
457 			msg->FindInt32("replyTo", fNewReplyTo);
458 			break;
459 		case P_REPLY_PREAMBLE:
460 		{
461 			int32 index = -1;
462 			if (msg->FindInt32("index", &index) < B_OK)
463 				break;
464 			BMenuItem *item = fReplyPreambleMenu->ItemAt(index);
465 			if (item == NULL) {
466 				msg->PrintToStream();
467 				break;
468 			}
469 
470 			BTextView *text = fReplyPreamble->TextView();
471 			int32 selectionStart;
472 			int32 selectionEnd;
473 			text->GetSelection(&selectionStart, &selectionEnd);
474 			if (selectionStart != selectionEnd)
475 				text->Delete(selectionStart, selectionEnd);
476 			text->Insert(item->Label(), 2);
477 		}
478 		case P_SIG:
479 			free(*fNewSignature);
480 			if (msg->FindString("signature", &signature) == B_NO_ERROR) {
481 				*fNewSignature = (char*)malloc(strlen(signature) + 1);
482 				strcpy(*fNewSignature, signature);
483 			} else {
484 				*fNewSignature = (char*)malloc(
485 					strlen(B_TRANSLATE("None")) + 1);
486 				strcpy(*fNewSignature, B_TRANSLATE("None"));
487 			}
488 			break;
489 		case P_ENC:
490 			msg->FindInt32("encoding", (int32*)fNewEncoding);
491 			break;
492 		case P_WARN_UNENCODABLE:
493 			msg->FindBool("warnUnencodable", fNewWarnUnencodable);
494 			break;
495 		case P_SPELL_CHECK_START_ON:
496 			msg->FindBool("spellCheckStartOn", fNewSpellCheckStartOn);
497 			break;
498 		case P_MARK_READ:
499 			msg->FindBool("autoMarkRead", fNewAutoMarkRead);
500 			be_app->PostMessage(PREFS_CHANGED);
501 			break;
502 		case P_BUTTON_BAR:
503 			msg->FindInt8("bar", (int8*)fNewButtonBar);
504 			be_app->PostMessage(PREFS_CHANGED);
505 			break;
506 
507 		default:
508 			BWindow::MessageReceived(msg);
509 	}
510 
511 	fFont.GetFamilyAndStyle(&old_family, &old_style);
512 	fNewFont->GetFamilyAndStyle(&new_family, &new_style);
513 	old_size = (int32) fFont.Size();
514 	new_size = (int32) fNewFont->Size();
515 	bool changed = old_size != new_size
516 		|| fWrap != *fNewWrap
517 		|| fAttachAttributes != *fNewAttachAttributes
518 		|| fColoredQuotes != *fNewColoredQuotes
519 		|| fAccount != *fNewAccount
520 		|| fReplyTo != *fNewReplyTo
521 		|| strcmp(old_family, new_family)
522 		|| strcmp(old_style, new_style)
523 		|| strcmp(fReplyPreamble->Text(), *fNewPreamble)
524 		|| strcmp(fSignature, *fNewSignature)
525 		|| fEncoding != *fNewEncoding
526 		|| fWarnUnencodable != *fNewWarnUnencodable
527 		|| fSpellCheckStartOn != *fNewSpellCheckStartOn
528 		|| fAutoMarkRead != *fNewAutoMarkRead
529 		|| fButtonBar != *fNewButtonBar;
530 	fRevert->SetEnabled(changed);
531 }
532 
533 
534 BPopUpMenu*
535 TPrefsWindow::_BuildFontMenu(BFont* font)
536 {
537 	font_family	def_family;
538 	font_style	def_style;
539 	font_family	f_family;
540 	font_style	f_style;
541 
542 	BPopUpMenu *menu = new BPopUpMenu("");
543 	font->GetFamilyAndStyle(&def_family, &def_style);
544 
545 	int32 family_menu_index = 0;
546 	int family_count = count_font_families();
547 	for (int family_loop = 0; family_loop < family_count; family_loop++) {
548 		get_font_family(family_loop, &f_family);
549 		BMenu *family_menu = new BMenu(f_family);
550 
551 		int style_count = count_font_styles(f_family);
552 		for (int style_loop = 0; style_loop < style_count; style_loop++) {
553 			get_font_style(f_family, style_loop, &f_style);
554 
555 			BMessage *msg = new BMessage(P_FONT);
556 			msg->AddString("font", f_family);
557 			msg->AddString("style", f_style);
558 			// we send this to make setting the Family easier when things
559 			// change
560 			msg->AddInt32("parent_index", family_menu_index);
561 
562 			BMenuItem *item = new BMenuItem(f_style, msg);
563 			family_menu->AddItem(item);
564 			if ((strcmp(def_family, f_family) == 0)
565 				&& (strcmp(def_style, f_style) == 0)) {
566 				item->SetMarked(true);
567 			}
568 
569 			item->SetTarget(this);
570 		}
571 
572 		menu->AddItem(family_menu);
573 		BMenuItem *item = menu->ItemAt(family_menu_index);
574 		BMessage *msg = new BMessage(P_FONT);
575 		msg->AddString("font", f_family);
576 
577 		item->SetMessage(msg);
578 		item->SetTarget(this);
579 		if (strcmp(def_family, f_family) == 0)
580 			item->SetMarked(true);
581 
582 		family_menu_index++;
583 	}
584 	return menu;
585 }
586 
587 
588 BPopUpMenu*
589 TPrefsWindow::_BuildLevelMenu(int32 level)
590 {
591 	BMenuItem* item;
592 	BMessage* msg;
593 	BPopUpMenu* menu;
594 
595 	menu = new BPopUpMenu("");
596 	msg = new BMessage(P_LEVEL);
597 	msg->AddInt32("level", L_BEGINNER);
598 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Beginner"), msg));
599 	if (level == L_BEGINNER)
600 		item->SetMarked(true);
601 
602 	msg = new BMessage(P_LEVEL);
603 	msg->AddInt32("level", L_EXPERT);
604 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Expert"), msg));
605 	if (level == L_EXPERT)
606 		item->SetMarked(true);
607 
608 	return menu;
609 }
610 
611 
612 BPopUpMenu*
613 TPrefsWindow::_BuildAccountMenu(int32 account)
614 {
615 	BPopUpMenu* menu = new BPopUpMenu("");
616 	BMenuItem* item;
617 
618 	//menu->SetRadioMode(true);
619 	BMailAccounts accounts;
620 	if (accounts.CountAccounts() == 0) {
621 		menu->AddItem(item = new BMenuItem(B_TRANSLATE("<no account found>"), NULL));
622 		item->SetEnabled(false);
623 		return menu;
624 	}
625 
626 	BMessage* msg;
627 	for (int32 i = 0; i < accounts.CountAccounts(); i++) {
628 		BMailAccountSettings* settings = accounts.AccountAt(i);
629 		item = new BMenuItem(settings->Name(), msg = new BMessage(P_ACCOUNT));
630 
631 		msg->AddInt32("id", settings->AccountID());
632 
633 		if (account == settings->AccountID())
634 			item->SetMarked(true);
635 
636 		menu->AddItem(item);
637 	}
638 	return menu;
639 }
640 
641 
642 BPopUpMenu*
643 TPrefsWindow::_BuildReplyToMenu(int32 account)
644 {
645 	BPopUpMenu* menu = new BPopUpMenu(B_EMPTY_STRING);
646 
647 	BMenuItem* item;
648 	BMessage* msg;
649 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Use default account"),
650 		msg = new BMessage(P_REPLYTO)));
651 	msg->AddInt32("replyTo", ACCOUNT_USE_DEFAULT);
652 	if (account == ACCOUNT_USE_DEFAULT)
653 		item->SetMarked(true);
654 
655 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Account from mail"),
656 		msg = new BMessage(P_REPLYTO)));
657 	msg->AddInt32("replyTo", ACCOUNT_FROM_MAIL);
658 	if (account == ACCOUNT_FROM_MAIL)
659 		item->SetMarked(true);
660 
661 	return menu;
662 }
663 
664 
665 BMenu*
666 TPrefsWindow::_BuildReplyPreambleMenu()
667 {
668 	BMenu *menu = new BMenu(B_EMPTY_STRING);
669 
670 	menu->AddItem(new BMenuItem(B_TRANSLATE("%n - Full name"),
671 		new BMessage(P_REPLY_PREAMBLE)));
672 
673 	menu->AddItem(new BMenuItem(B_TRANSLATE("%e - E-mail address"),
674 		new BMessage(P_REPLY_PREAMBLE)));
675 
676 	menu->AddItem(new BMenuItem(B_TRANSLATE("%d - Date"),
677 		new BMessage(P_REPLY_PREAMBLE)));
678 
679 	menu->AddSeparatorItem();
680 
681 	menu->AddItem(new BMenuItem(B_TRANSLATE("\\n - Newline"),
682 		new BMessage(P_REPLY_PREAMBLE)));
683 
684 	return menu;
685 }
686 
687 
688 BPopUpMenu*
689 TPrefsWindow::_BuildSignatureMenu(char* sig)
690 {
691 	char name[B_FILE_NAME_LENGTH];
692 	BEntry entry;
693 	BFile file;
694 	BMenuItem* item;
695 	BMessage* msg;
696 	BQuery query;
697 	BVolume vol;
698 	BVolumeRoster volume;
699 
700 	BPopUpMenu* menu = new BPopUpMenu("");
701 
702 	msg = new BMessage(P_SIG);
703 	msg->AddString("signature", B_TRANSLATE("None"));
704 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("None"), msg));
705 	if (!strcmp(sig, B_TRANSLATE("None")))
706 		item->SetMarked(true);
707 
708 	msg = new BMessage(P_SIG);
709 	msg->AddString("signature", B_TRANSLATE("Random"));
710 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Random"), msg));
711 	if (!strcmp(sig, B_TRANSLATE("Random")))
712 		item->SetMarked(true);
713 	menu->AddSeparatorItem();
714 
715 	volume.GetBootVolume(&vol);
716 	query.SetVolume(&vol);
717 	query.SetPredicate("_signature = *");
718 	query.Fetch();
719 
720 	while (query.GetNextEntry(&entry) == B_NO_ERROR) {
721 		file.SetTo(&entry, O_RDONLY);
722 		if (file.InitCheck() == B_NO_ERROR) {
723 			msg = new BMessage(P_SIG);
724 			file.ReadAttr("_signature", B_STRING_TYPE, 0, name, sizeof(name));
725 			msg->AddString("signature", name);
726 			menu->AddItem(item = new BMenuItem(name, msg));
727 			if (!strcmp(sig, name))
728 				item->SetMarked(true);
729 		}
730 	}
731 	return menu;
732 }
733 
734 
735 BPopUpMenu*
736 TPrefsWindow::_BuildSizeMenu(BFont* font)
737 {
738 	char label[16];
739 	uint32 loop;
740 	int32 sizes[] = {9, 10, 11, 12, 14, 18, 24};
741 	float size;
742 	BMenuItem* item;
743 	BMessage* msg;
744 	BPopUpMenu* menu;
745 
746 	menu = new BPopUpMenu("");
747 	size = font->Size();
748 	for (loop = 0; loop < sizeof(sizes) / sizeof(int32); loop++) {
749 		msg = new BMessage(P_SIZE);
750 		msg->AddInt32("size", sizes[loop]);
751 		sprintf(label, "%" B_PRId32, sizes[loop]);
752 		menu->AddItem(item = new BMenuItem(label, msg));
753 		if (sizes[loop] == (int32)size)
754 			item->SetMarked(true);
755 	}
756 	return menu;
757 }
758 
759 
760 BPopUpMenu*
761 TPrefsWindow::_BuildBoolMenu(uint32 what, const char* boolItem, bool isTrue)
762 {
763 	BMenuItem* item;
764 	BMessage* msg;
765 	BPopUpMenu* menu;
766 
767 	menu = new BPopUpMenu("");
768 	msg = new BMessage(what);
769 	msg->AddBool(boolItem, true);
770 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("On"), msg));
771 	if (isTrue)
772 		item->SetMarked(true);
773 
774 	msg = new BMessage(what);
775 	msg->AddInt32(boolItem, false);
776 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Off"), msg));
777 	if (!isTrue)
778 		item->SetMarked(true);
779 
780 	return menu;
781 }
782 
783 
784 BPopUpMenu*
785 TPrefsWindow::_BuildWrapMenu(bool wrap)
786 {
787 	return _BuildBoolMenu(P_WRAP, "wrap", wrap);
788 }
789 
790 
791 BPopUpMenu*
792 TPrefsWindow::_BuildAttachAttributesMenu(bool attachAttributes)
793 {
794 	BMenuItem* item;
795 	BMessage* msg;
796 	BPopUpMenu* menu;
797 
798 	menu = new BPopUpMenu("");
799 	msg = new BMessage(P_ATTACH_ATTRIBUTES);
800 	msg->AddBool("attachAttributes", true);
801 	menu->AddItem(item = new BMenuItem(
802 		B_TRANSLATE("Include file attributes in attachments"), msg));
803 	if (attachAttributes)
804 		item->SetMarked(true);
805 
806 	msg = new BMessage(P_ATTACH_ATTRIBUTES);
807 	msg->AddInt32("attachAttributes", false);
808 	menu->AddItem(item = new BMenuItem(
809 		B_TRANSLATE("No file attributes, just plain data"), msg));
810 	if (!attachAttributes)
811 		item->SetMarked(true);
812 
813 	return menu;
814 }
815 
816 
817 BPopUpMenu*
818 TPrefsWindow::_BuildColoredQuotesMenu(bool quote)
819 {
820 	return _BuildBoolMenu(P_COLORED_QUOTES, "cquotes", quote);
821 }
822 
823 
824 BPopUpMenu*
825 TPrefsWindow::_BuildEncodingMenu(uint32 encoding)
826 {
827 	BMenuItem* item;
828 	BMessage* msg;
829 	BPopUpMenu* menu;
830 
831 	menu = new BPopUpMenu("");
832 
833 	BCharacterSetRoster roster;
834 	BCharacterSet charset;
835 	while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) {
836 		BString name(charset.GetPrintName());
837 		const char* mime = charset.GetMIMEName();
838 		if (mime)
839 			name << " (" << mime << ")";
840 		msg = new BMessage(P_ENC);
841 		uint32 convert_id;
842 		if ((mime == 0) || (strcasecmp(mime, "UTF-8") != 0))
843 			convert_id = charset.GetConversionID();
844 		else
845 			convert_id = B_MAIL_UTF8_CONVERSION;
846 		msg->AddInt32("encoding", convert_id);
847 		menu->AddItem(item = new BMenuItem(name.String(), msg));
848 		if (convert_id == encoding)
849 			item->SetMarked(true);
850 	}
851 
852 	msg = new BMessage(P_ENC);
853 	msg->AddInt32("encoding", B_MAIL_US_ASCII_CONVERSION);
854 	menu->AddItem(item = new BMenuItem("US-ASCII", msg));
855 	if (encoding == B_MAIL_US_ASCII_CONVERSION)
856 		item->SetMarked(true);
857 
858 	return menu;
859 }
860 
861 
862 BPopUpMenu*
863 TPrefsWindow::_BuildWarnUnencodableMenu(bool warnUnencodable)
864 {
865 	return _BuildBoolMenu(P_WARN_UNENCODABLE, "warnUnencodable",
866 		warnUnencodable);
867 }
868 
869 
870 BPopUpMenu*
871 TPrefsWindow::_BuildSpellCheckStartOnMenu(bool spellCheckStartOn)
872 {
873 	return _BuildBoolMenu(P_SPELL_CHECK_START_ON, "spellCheckStartOn",
874 		spellCheckStartOn);
875 }
876 
877 
878 BPopUpMenu*
879 TPrefsWindow::_BuildAutoMarkReadMenu(bool autoMarkRead)
880 {
881 	return _BuildBoolMenu(P_MARK_READ, "autoMarkRead",
882 		autoMarkRead);
883 }
884 
885 
886 BPopUpMenu*
887 TPrefsWindow::_BuildButtonBarMenu(uint8 show)
888 {
889 	BMenuItem* item;
890 	BMessage* msg;
891 	BPopUpMenu* menu = new BPopUpMenu("");
892 
893 	msg = new BMessage(P_BUTTON_BAR);
894 	msg->AddInt8("bar", kShowToolBar);
895 	menu->AddItem(item = new BMenuItem(
896 		B_TRANSLATE("Show icons & labels"), msg));
897 	if (show & 1)
898 		item->SetMarked(true);
899 
900 	msg = new BMessage(P_BUTTON_BAR);
901 	msg->AddInt8("bar", kShowToolBarIconsOnly);
902 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Show icons only"), msg));
903 	if (show & 2)
904 		item->SetMarked(true);
905 
906 	msg = new BMessage(P_BUTTON_BAR);
907 	msg->AddInt8("bar", kHideToolBar);
908 	menu->AddItem(item = new BMenuItem(B_TRANSLATE("Hide"), msg));
909 	if (!show)
910 		item->SetMarked(true);
911 
912 	return menu;
913 }
914 
915