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