xref: /haiku/src/apps/mail/Prefs.cpp (revision 5115ca085884f7b604a3d607688f0ca20fb7cf57)
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 CONNECTION
23 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 registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 //--------------------------------------------------------------------
36 //
37 //	Prefs.cpp
38 //
39 //--------------------------------------------------------------------
40 
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <InterfaceKit.h>
45 #include <StorageKit.h>
46 #include <E-mail.h>
47 #include <Application.h>
48 
49 #include <MailSettings.h>
50 #include <mail_encoding.h>
51 #include <MDRLanguage.h>
52 
53 #include <String.h>
54 #include <CharacterSet.h>
55 #include <CharacterSetRoster.h>
56 
57 using namespace BPrivate;
58 
59 #include "Mail.h"
60 #include "Prefs.h"
61 
62 #define BUTTON_WIDTH		70
63 #define BUTTON_HEIGHT		20
64 #define ITEM_SPACE			6
65 
66 #define FONT_TEXT			MDR_DIALECT_CHOICE ("Font:", "フォント:")
67 #define SIZE_TEXT			MDR_DIALECT_CHOICE ("Size:", "サイズ:")
68 #define LEVEL_TEXT			MDR_DIALECT_CHOICE ("User Level:", "ユーザーレベル:")
69 #define WRAP_TEXT			MDR_DIALECT_CHOICE ("Text Wrapping:", "テキスト・ラップ:")
70 #define ATTACH_ATTRIBUTES_TEXT	MDR_DIALECT_CHOICE ("Attach Attributes:", "ファイル属性情報:")
71 #define QUOTES_TEXT			MDR_DIALECT_CHOICE ("Colored Quotes:", "引用部分の着色:")
72 #define ACCOUNT_TEXT		MDR_DIALECT_CHOICE ("Default Account:", "標準アカウント:")
73 #define REPLYTO_TEXT		MDR_DIALECT_CHOICE ("Reply Account:", "返信用アカウント:")
74 #define REPLYTO_USE_DEFAULT_TEXT	MDR_DIALECT_CHOICE ("Use Default Account", "標準アカウントを使う")
75 #define REPLYTO_FROM_MAIL_TEXT		MDR_DIALECT_CHOICE ("Account From Mail", "メールのアカウントを使う")
76 #define REPLY_PREAMBLE_TEXT		MDR_DIALECT_CHOICE ("Reply Preamble:", "返信へ追加:")
77 #define SIGNATURE_TEXT		MDR_DIALECT_CHOICE ("Auto Signature:", "自動署名:")
78 #define ENCODING_TEXT		MDR_DIALECT_CHOICE ("Encoding:", "エンコード形式:")
79 #define WARN_UNENCODABLE_TEXT	MDR_DIALECT_CHOICE ("Warn Unencodable:", "警告: エンコードできません")
80 #define SPELL_CHECK_START_ON_TEXT	MDR_DIALECT_CHOICE ("Initial Spell Check Mode:", "編集時スペルチェック:")
81 
82 #define BUTTONBAR_TEXT		MDR_DIALECT_CHOICE ("Button Bar:", "ボタンバー:")
83 
84 #define OK_BUTTON_X1		(PREF_WIDTH - BUTTON_WIDTH - 6)
85 #define OK_BUTTON_X2		(OK_BUTTON_X1 + BUTTON_WIDTH)
86 #define OK_BUTTON_TEXT		MDR_DIALECT_CHOICE ("OK", "設定")
87 #define CANCEL_BUTTON_TEXT	MDR_DIALECT_CHOICE ("Cancel", "中止")
88 
89 #define REVERT_BUTTON_X1	8
90 #define REVERT_BUTTON_X2	(REVERT_BUTTON_X1 + BUTTON_WIDTH)
91 #define REVERT_BUTTON_TEXT	MDR_DIALECT_CHOICE ("Revert", "復元")
92 
93 enum	P_MESSAGES			{P_OK = 128, P_CANCEL, P_REVERT, P_FONT,
94 							 P_SIZE, P_LEVEL, P_WRAP, P_ATTACH_ATTRIBUTES,
95 							 P_SIG, P_ENC, P_WARN_UNENCODABLE,
96 							 P_SPELL_CHECK_START_ON, P_BUTTON_BAR,
97 							 P_ACCOUNT, P_REPLYTO, P_REPLY_PREAMBLE,
98 							 P_COLORED_QUOTES};
99 
100 #define ICON_LABEL_TEXT MDR_DIALECT_CHOICE ("Show Icons & Labels", "アイコンとラベル")
101 #define ICON_TEXT MDR_DIALECT_CHOICE ("Show Icons Only", "アイコンのみ")
102 #define HIDE_TEXT MDR_DIALECT_CHOICE ("Hide", "隠す")
103 
104 
105 extern BPoint	prefs_window;
106 
107 #define  ATTRIBUTE_ON_TEXT MDR_DIALECT_CHOICE ("Include BeOS Attributes in Attachments", "BeOSの属性を付ける")
108 #define  ATTRIBUTE_OFF_TEXT MDR_DIALECT_CHOICE ("No BeOS Attributes, just Plain Data", "BeOSの属性を付けない(データのみ)")
109 
110 //====================================================================
111 
112 
113 TPrefsWindow::TPrefsWindow(BRect rect, BFont *font, int32 *level, bool *wrap,
114 	bool *attachAttributes, bool *cquotes, uint32 *account, int32 *replyTo,
115 	char **preamble, char **sig, uint32 *encoding, bool *warnUnencodable,
116 	bool *spellCheckStartOn, uint8 *buttonBar)
117 	:	BWindow(rect, MDR_DIALECT_CHOICE ("Mail Preferences","Mailの設定"), B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE)
118 {
119 	BMenuField *menu;
120 
121 	fNewFont = font;			fFont = *fNewFont;
122 	fNewWrap = wrap;			fWrap = *fNewWrap;
123 	fNewAttachAttributes = attachAttributes;	fAttachAttributes = *fNewAttachAttributes;
124 	fNewColoredQuotes = cquotes;	fColoredQuotes = *fNewColoredQuotes;
125 	fNewAccount = account;		fAccount = *fNewAccount;
126 	fNewReplyTo = replyTo;		fReplyTo = *fNewReplyTo;
127 	fNewEncoding = encoding;	fEncoding = *fNewEncoding;
128 	fNewWarnUnencodable = warnUnencodable;	fWarnUnencodable = *fNewWarnUnencodable;
129 	fNewSpellCheckStartOn = spellCheckStartOn;	fSpellCheckStartOn = *fNewSpellCheckStartOn;
130 	fNewButtonBar = buttonBar;	fButtonBar = *fNewButtonBar;
131 
132 	fNewPreamble = preamble;
133 
134 	fNewSignature = sig;
135 	fSignature = (char *)malloc(strlen(*fNewSignature) + 1);
136 	strcpy(fSignature, *fNewSignature);
137 
138 	BRect r = Bounds();
139 	BView *view = new BView(r, NULL, B_FOLLOW_ALL, B_FRAME_EVENTS);
140 	view->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
141 	AddChild(view);
142 
143 	// determine font height
144 	font_height fontHeight;
145 	view->GetFontHeight(&fontHeight);
146 	int32 height = (int32)(fontHeight.ascent + fontHeight.descent + fontHeight.leading) + 6;
147 	int32 labelWidth = (int32)view->StringWidth(SPELL_CHECK_START_ON_TEXT) + SEPARATOR_MARGIN;
148 
149 	// group boxes
150 
151 	r.Set(8,4,Bounds().right - 8,4 + 6 * (height + ITEM_SPACE));
152 	BBox *interfaceBox = new BBox(r,NULL,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
153 	interfaceBox->SetLabel(MDR_DIALECT_CHOICE ("User Interface","ユーザーインターフェース"));
154 	view->AddChild(interfaceBox);
155 
156 	r.top = r.bottom + 8;  r.bottom = r.top + 9 * (height + ITEM_SPACE);
157 	BBox *mailBox = new BBox(r,NULL,B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP);
158 	mailBox->SetLabel(MDR_DIALECT_CHOICE ("Mailing","メール関係"));
159 	view->AddChild(mailBox);
160 
161 	// revert, ok & cancel
162 
163 	r.top = r.bottom + 10;  r.bottom = r.top + height;
164 	r.left = OK_BUTTON_X1;  r.right = OK_BUTTON_X2;
165 	BButton *button = new BButton(r, "ok", OK_BUTTON_TEXT, new BMessage(P_OK));
166 	button->MakeDefault(true);
167 	view->AddChild(button);
168 
169 	r.OffsetBy(-(OK_BUTTON_X2 - OK_BUTTON_X1 + 10), 0);
170 	button = new BButton(r, "cancel", CANCEL_BUTTON_TEXT, new BMessage(P_CANCEL));
171 	view->AddChild(button);
172 
173 	r.left = REVERT_BUTTON_X1;  r.right = REVERT_BUTTON_X2;
174 	fRevert = new BButton(r, "revert", REVERT_BUTTON_TEXT, new BMessage(P_REVERT));
175 	fRevert->SetEnabled(false);
176 	view->AddChild(fRevert);
177 
178 	// User Interface
179 
180 	r = interfaceBox->Bounds();
181 	r.left += 8;  r.right -= 8;  r.top = height;  r.bottom = r.top + height - 3;
182 	fButtonBarMenu = BuildButtonBarMenu(*buttonBar);
183 	menu = new BMenuField(r, "bar", BUTTONBAR_TEXT, fButtonBarMenu,B_FOLLOW_ALL,
184 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
185 	menu->SetDivider(labelWidth);
186 	menu->SetAlignment(B_ALIGN_RIGHT);
187 	interfaceBox->AddChild(menu);
188 
189 	r.OffsetBy(0,height + ITEM_SPACE);
190 	fFontMenu = BuildFontMenu(font);
191 	menu = new BMenuField(r, "font", FONT_TEXT, fFontMenu,B_FOLLOW_ALL,
192 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
193 	menu->SetDivider(labelWidth);
194 	menu->SetAlignment(B_ALIGN_RIGHT);
195 	interfaceBox->AddChild(menu);
196 
197 	r.OffsetBy(0,height + ITEM_SPACE);
198 	fSizeMenu = BuildSizeMenu(font);
199 	menu = new BMenuField(r, "size", SIZE_TEXT, fSizeMenu,B_FOLLOW_ALL,
200 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
201 	menu->SetDivider(labelWidth);
202 	menu->SetAlignment(B_ALIGN_RIGHT);
203 	interfaceBox->AddChild(menu);
204 
205 	r.OffsetBy(0,height + ITEM_SPACE);
206 	fColoredQuotesMenu = BuildColoredQuotesMenu(fColoredQuotes);
207 	menu = new BMenuField(r, "cquotes", QUOTES_TEXT, fColoredQuotesMenu,B_FOLLOW_ALL,
208 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
209 	menu->SetDivider(labelWidth);
210 	menu->SetAlignment(B_ALIGN_RIGHT);
211 	interfaceBox->AddChild(menu);
212 
213 	r.OffsetBy(0,height + ITEM_SPACE);
214 	fSpellCheckStartOnMenu = BuildSpellCheckStartOnMenu(fSpellCheckStartOn);
215 	menu = new BMenuField(r, "spellCheckStartOn", SPELL_CHECK_START_ON_TEXT,
216 		fSpellCheckStartOnMenu, B_FOLLOW_ALL,
217 		B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
218 	menu->SetDivider(labelWidth);
219 	menu->SetAlignment(B_ALIGN_RIGHT);
220 	interfaceBox->AddChild(menu);
221 
222 
223 	// Mail Accounts
224 
225 	r = mailBox->Bounds();
226 	r.left += 8;  r.right -= 8;  r.top = height;  r.bottom = r.top + height - 3;
227 	fAccountMenu = BuildAccountMenu(fAccount);
228 	menu = new BMenuField(r, "account", ACCOUNT_TEXT, fAccountMenu, B_FOLLOW_ALL,
229 		B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
230 	menu->SetDivider(labelWidth);
231 	menu->SetAlignment(B_ALIGN_RIGHT);
232 	mailBox->AddChild(menu);
233 
234 	r.OffsetBy(0,height + ITEM_SPACE);
235 	fReplyToMenu = BuildReplyToMenu(fReplyTo);
236 	menu = new BMenuField(r, "replyTo", REPLYTO_TEXT, fReplyToMenu, B_FOLLOW_ALL,
237 		B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
238 	menu->SetDivider(labelWidth);
239 	menu->SetAlignment(B_ALIGN_RIGHT);
240 	mailBox->AddChild(menu);
241 
242 	// Mail Contents
243 
244 	r.OffsetBy(0, height + ITEM_SPACE);		r.right -= 25;
245 	fReplyPreamble = new BTextControl(r, "replytext", REPLY_PREAMBLE_TEXT, *preamble,
246 		new BMessage(P_REPLY_PREAMBLE), B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE);
247 	fReplyPreamble->SetDivider(labelWidth);
248 	fReplyPreamble->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
249 	mailBox->AddChild(fReplyPreamble);
250 
251 	BRect popRect = r;
252 	popRect.left = r.right + 6;  r.right += 25;  popRect.right = r.right;
253 	fReplyPreambleMenu = BuildReplyPreambleMenu();
254 	menu = new BMenuField(popRect, "replyPreamble", B_EMPTY_STRING, fReplyPreambleMenu,
255 		B_FOLLOW_ALL, B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
256 	menu->SetDivider(0);
257 	mailBox->AddChild(menu);
258 
259 	r.OffsetBy(0, height + ITEM_SPACE);
260 	fSignatureMenu = BuildSignatureMenu(*sig);
261 	menu = new BMenuField(r, "sig", SIGNATURE_TEXT, fSignatureMenu,B_FOLLOW_ALL,
262 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
263 	menu->SetDivider(labelWidth);
264 	menu->SetAlignment(B_ALIGN_RIGHT);
265 	mailBox->AddChild(menu);
266 
267 	r.OffsetBy(0,height + ITEM_SPACE);
268 	fEncodingMenu = BuildEncodingMenu(fEncoding);
269 	menu = new BMenuField(r, "enc", ENCODING_TEXT, fEncodingMenu,B_FOLLOW_ALL,
270 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
271 	menu->SetDivider(labelWidth);
272 	menu->SetAlignment(B_ALIGN_RIGHT);
273 	mailBox->AddChild(menu);
274 
275 	r.OffsetBy(0,height + ITEM_SPACE);
276 	fWarnUnencodableMenu = BuildWarnUnencodableMenu(fWarnUnencodable);
277 	menu = new BMenuField(r, "warnUnencodable", WARN_UNENCODABLE_TEXT,
278 		fWarnUnencodableMenu, B_FOLLOW_ALL,
279 		B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
280 	menu->SetDivider(labelWidth);
281 	menu->SetAlignment(B_ALIGN_RIGHT);
282 	mailBox->AddChild(menu);
283 
284 	r.OffsetBy(0,height + ITEM_SPACE);
285 	fWrapMenu = BuildWrapMenu(*wrap);
286 	menu = new BMenuField(r, "wrap", WRAP_TEXT, fWrapMenu,B_FOLLOW_ALL,
287 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
288 	menu->SetDivider(labelWidth);
289 	menu->SetAlignment(B_ALIGN_RIGHT);
290 	mailBox->AddChild(menu);
291 
292 	r.OffsetBy(0,height + ITEM_SPACE);
293 	fAttachAttributesMenu = BuildAttachAttributesMenu(*attachAttributes);
294 	menu = new BMenuField(r, "attachAttributes", ATTACH_ATTRIBUTES_TEXT, fAttachAttributesMenu, B_FOLLOW_ALL,
295 				B_WILL_DRAW | B_NAVIGABLE | B_NAVIGABLE_JUMP);
296 	menu->SetDivider(labelWidth);
297 	menu->SetAlignment(B_ALIGN_RIGHT);
298 	mailBox->AddChild(menu);
299 
300 	ResizeTo(Frame().Width(), fRevert->Frame().bottom + 8);
301 	Show();
302 }
303 
304 
305 TPrefsWindow::~TPrefsWindow()
306 {
307 	prefs_window = Frame().LeftTop();
308 
309 	BMessage msg(WINDOW_CLOSED);
310 	msg.AddInt32("kind", PREFS_WINDOW);
311 	be_app->PostMessage(&msg);
312 }
313 
314 
315 void
316 TPrefsWindow::MessageReceived(BMessage *msg)
317 {
318 	bool		changed;
319 	bool		revert = true;
320 	const char	*family;
321 	const char	*signature;
322 	const char	*style;
323 	char		label[256];
324 	int32		new_size;
325 	int32		old_size;
326 	font_family	new_family;
327 	font_family	old_family;
328 	font_style	new_style;
329 	font_style	old_style;
330 	BMenuItem	*item;
331 	BMessage	message;
332 
333 	switch (msg->what) {
334 		case P_OK:
335 			if (strcmp(fReplyPreamble->Text(), *fNewPreamble))
336 			{
337 				free(*fNewPreamble);
338 				*fNewPreamble = (char *)malloc(strlen(fReplyPreamble->Text()) + 1);
339 				strcpy(*fNewPreamble, fReplyPreamble->Text());
340 			}
341 			be_app->PostMessage(PREFS_CHANGED);
342 			Quit();
343 			break;
344 
345 		case P_CANCEL:
346 			revert = false;
347 			// supposed to fall through
348 		case P_REVERT:
349 			fFont.GetFamilyAndStyle(&old_family, &old_style);
350 			fNewFont->GetFamilyAndStyle(&new_family, &new_style);
351 			old_size = (int32) fFont.Size();
352 			new_size = (int32) fNewFont->Size();
353 			if (strcmp(old_family, new_family) || strcmp(old_style, new_style)
354 				|| old_size != new_size)
355 			{
356 				fNewFont->SetFamilyAndStyle(old_family, old_style);
357 				if (revert) {
358 					sprintf(label, "%s %s", old_family, old_style);
359 					item = fFontMenu->FindItem(label);
360 					if (item != NULL)
361 						item->SetMarked(true);
362 				}
363 
364 				fNewFont->SetSize(old_size);
365 				if (revert) {
366 					sprintf(label, "%ld", old_size);
367 					item = fSizeMenu->FindItem(label);
368 					if (item != NULL)
369 						item->SetMarked(true);
370 				}
371 				message.what = M_FONT;
372 				be_app->PostMessage(&message);
373 			}
374 			*fNewWrap = fWrap;
375 			*fNewAttachAttributes = fAttachAttributes;
376 
377 			if (strcmp(fSignature, *fNewSignature)) {
378 				free(*fNewSignature);
379 				*fNewSignature = (char *)malloc(strlen(fSignature) + 1);
380 				strcpy(*fNewSignature, fSignature);
381 			}
382 
383 			*fNewEncoding = fEncoding;
384 			*fNewWarnUnencodable = fWarnUnencodable;
385 			*fNewSpellCheckStartOn = fSpellCheckStartOn;
386 			*fNewButtonBar = fButtonBar;
387 
388 			be_app->PostMessage(PREFS_CHANGED);
389 
390 			if (revert) {
391 				for (int i = fAccountMenu->CountItems();i-- > 0;) {
392 					if (BMenuItem *item = fAccountMenu->ItemAt(i))
393 						if (item->Message()->FindInt32("id") == *(int32 *)&fAccount)
394 							item->SetMarked(true);
395 				}
396 
397 				strcpy(label,fReplyTo == ACCOUNT_USE_DEFAULT
398 					? REPLYTO_USE_DEFAULT_TEXT : REPLYTO_FROM_MAIL_TEXT);
399 				if ((item = fReplyToMenu->FindItem(label)) != NULL)
400 					item->SetMarked(true);
401 
402 				strcpy(label, fWrap ? "On" : "Off");
403 				if ((item = fWrapMenu->FindItem(label)) != NULL)
404 					item->SetMarked(true);
405 
406 				strcpy(label, fAttachAttributes
407 					? ATTRIBUTE_ON_TEXT : ATTRIBUTE_OFF_TEXT);
408 				if ((item = fAttachAttributesMenu->FindItem(label)) != NULL)
409 					item->SetMarked(true);
410 
411 				strcpy(label, fColoredQuotes ? "On" : "Off");
412 				if ((item = fColoredQuotesMenu->FindItem(label)) != NULL)
413 					item->SetMarked(true);
414 
415 				if (strcmp(fReplyPreamble->Text(), *fNewPreamble))
416 					fReplyPreamble->SetText(*fNewPreamble);
417 
418 				item = fSignatureMenu->FindItem(fSignature);
419 				if (item)
420 					item->SetMarked(true);
421 
422 				uint32 index = 0;
423 				while ((item = fEncodingMenu->ItemAt(index++)) != NULL) {
424 					BMessage * message = item->Message();
425 					if (message == NULL)
426 						continue;
427 
428 					int32 encoding;
429 					if (message->FindInt32("encoding", &encoding) == B_OK
430 						&& (uint32)encoding == *fNewEncoding) {
431 						item->SetMarked(true);
432 						break;
433 					}
434 				}
435 
436 				strcpy(label, fWarnUnencodable ? "On" : "Off");
437 				if ((item = fWarnUnencodableMenu->FindItem(label)) != NULL)
438 					item->SetMarked(true);
439 
440 				strcpy(label, fSpellCheckStartOn ? "On" : "Off");
441 				if ((item = fSpellCheckStartOnMenu->FindItem(label)) != NULL)
442 					item->SetMarked(true);
443 			} else
444 				Quit();
445 			break;
446 
447 		case P_FONT:
448 			family = NULL;
449 			style = NULL;
450 			int32 family_menu_index;
451 			if (msg->FindString("font", &family) == B_OK) {
452 				msg->FindString("style", &style);
453 				fNewFont->SetFamilyAndStyle(family, style);
454 				message.what = M_FONT;
455 				be_app->PostMessage(&message);
456 			}
457 
458 			/* grab this little tidbit so we can set the correct Family */
459 			if(msg->FindInt32("parent_index", &family_menu_index) == B_OK)
460 				fFontMenu->ItemAt(family_menu_index)->SetMarked(true);
461 			break;
462 
463 		case P_SIZE:
464 			old_size = (int32) fNewFont->Size();
465 			msg->FindInt32("size", &new_size);
466 			if (old_size != new_size) {
467 				fNewFont->SetSize(new_size);
468 				message.what = M_FONT;
469 				be_app->PostMessage(&message);
470 			}
471 			break;
472 
473 		case P_WRAP:
474 			msg->FindBool("wrap", fNewWrap);
475 			break;
476 		case P_ATTACH_ATTRIBUTES:
477 			msg->FindBool("attachAttributes", fNewAttachAttributes);
478 			break;
479 		case P_COLORED_QUOTES:
480 			msg->FindBool("cquotes", fNewColoredQuotes);
481 			break;
482 		case P_ACCOUNT:
483 			msg->FindInt32("id",(int32 *)fNewAccount);
484 			break;
485 		case P_REPLYTO:
486 			msg->FindInt32("replyTo", fNewReplyTo);
487 			break;
488 		case P_REPLY_PREAMBLE:
489 		{
490 			int32 index = -1;
491 			if (msg->FindInt32("index", &index) < B_OK)
492 				break;
493 			BMenuItem *item = fReplyPreambleMenu->ItemAt(index);
494 			if (item == NULL) {
495 				msg->PrintToStream();
496 				break;
497 			}
498 
499 			BTextView *text = fReplyPreamble->TextView();
500 			// To do: insert at selection point rather than at the end.
501 			text->Insert(text->TextLength(), item->Label(), 2);
502 		}
503 		case P_SIG:
504 			free(*fNewSignature);
505 			if (msg->FindString("signature", &signature) == B_NO_ERROR) {
506 				*fNewSignature = (char *)malloc(strlen(signature) + 1);
507 				strcpy(*fNewSignature, signature);
508 			} else {
509 				*fNewSignature = (char *)malloc(strlen(SIG_NONE) + 1);
510 				strcpy(*fNewSignature, SIG_NONE);
511 			}
512 			break;
513 		case P_ENC:
514 			msg->FindInt32("encoding", (int32 *)fNewEncoding);
515 			break;
516 		case P_WARN_UNENCODABLE:
517 			msg->FindBool("warnUnencodable", fNewWarnUnencodable);
518 			break;
519 		case P_SPELL_CHECK_START_ON:
520 			msg->FindBool("spellCheckStartOn", fNewSpellCheckStartOn);
521 			break;
522 		case P_BUTTON_BAR:
523 			msg->FindInt8("bar", (int8 *)fNewButtonBar);
524 			be_app->PostMessage(PREFS_CHANGED);
525 			break;
526 
527 		default:
528 			BWindow::MessageReceived(msg);
529 	}
530 
531 	fFont.GetFamilyAndStyle(&old_family, &old_style);
532 	fNewFont->GetFamilyAndStyle(&new_family, &new_style);
533 	old_size = (int32) fFont.Size();
534 	new_size = (int32) fNewFont->Size();
535 	changed = old_size != new_size
536 		|| fWrap != *fNewWrap
537 		|| fAttachAttributes != *fNewAttachAttributes
538 		|| fColoredQuotes != *fNewColoredQuotes
539 		|| fAccount != *fNewAccount
540 		|| fReplyTo != *fNewReplyTo
541 		|| strcmp(old_family, new_family)
542 		|| strcmp(old_style, new_style)
543 		|| strcmp(fReplyPreamble->Text(), *fNewPreamble)
544 		|| strcmp(fSignature, *fNewSignature)
545 		|| fEncoding != *fNewEncoding
546 		|| fWarnUnencodable != *fNewWarnUnencodable
547 		|| fSpellCheckStartOn != *fNewSpellCheckStartOn
548 		|| fButtonBar != *fNewButtonBar;
549 	fRevert->SetEnabled(changed);
550 }
551 
552 
553 BPopUpMenu *
554 TPrefsWindow::BuildFontMenu(BFont *font)
555 {
556 	font_family	def_family;
557 	font_style	def_style;
558 	font_family	f_family;
559 	font_style	f_style;
560 
561 	BPopUpMenu *menu = new BPopUpMenu("");
562 	font->GetFamilyAndStyle(&def_family, &def_style);
563 
564 	int32 family_menu_index = 0;
565 	int family_count = count_font_families();
566 	for (int family_loop = 0; family_loop < family_count; family_loop++) {
567 		get_font_family(family_loop, &f_family);
568 		BMenu *family_menu = new BMenu(f_family);
569 
570 		int style_count = count_font_styles(f_family);
571 		for (int style_loop = 0; style_loop < style_count; style_loop++) {
572 			get_font_style(f_family, style_loop, &f_style);
573 
574 			BMessage *msg = new BMessage(P_FONT);
575 			msg->AddString("font", f_family);
576 			msg->AddString("style", f_style);
577 			/* we send this to make setting the Family easier when things change */
578 			msg->AddInt32("parent_index", family_menu_index);
579 
580 			BMenuItem *item = new BMenuItem(f_style, msg);
581 			family_menu->AddItem(item);
582 			if ((strcmp(def_family, f_family) == 0) && (strcmp(def_style, f_style) == 0))
583 				item->SetMarked(true);
584 
585 			item->SetTarget(this);
586 		}
587 
588 		menu->AddItem(family_menu);
589 		BMenuItem *item = menu->ItemAt(family_menu_index);
590 		BMessage *msg = new BMessage(P_FONT);
591 		msg->AddString("font", f_family);
592 
593 		item->SetMessage(msg);
594 		item->SetTarget(this);
595 		if (strcmp(def_family, f_family) == 0)
596 			item->SetMarked(true);
597 
598 		family_menu_index++;
599 	}
600 	return menu;
601 }
602 
603 
604 BPopUpMenu *
605 TPrefsWindow::BuildLevelMenu(int32 level)
606 {
607 	BMenuItem *item;
608 	BMessage *msg;
609 	BPopUpMenu *menu;
610 
611 	menu = new BPopUpMenu("");
612 	msg = new BMessage(P_LEVEL);
613 	msg->AddInt32("level", L_BEGINNER);
614 	menu->AddItem(item = new BMenuItem(MDR_DIALECT_CHOICE ("Beginner","初心者"),msg));
615 	if (level == L_BEGINNER)
616 		item->SetMarked(true);
617 
618 	msg = new BMessage(P_LEVEL);
619 	msg->AddInt32("level", L_EXPERT);
620 	menu->AddItem(item = new BMenuItem(MDR_DIALECT_CHOICE ("Expert","上級者"),msg));
621 	if (level == L_EXPERT)
622 		item->SetMarked(true);
623 
624 	return menu;
625 }
626 
627 
628 BPopUpMenu *
629 TPrefsWindow::BuildAccountMenu(uint32 account)
630 {
631 	BPopUpMenu *menu = new BPopUpMenu("");
632 	BMenuItem *item;
633 
634 	//menu->SetRadioMode(true);
635 	BList chains;
636 	if (GetOutboundMailChains(&chains) < B_OK) {
637 		menu->AddItem(item = new BMenuItem("<no account found>", NULL));
638 		item->SetEnabled(false);
639 		return menu;
640 	}
641 
642 	BMessage *msg;
643 	for (int32 i = 0; i < chains.CountItems(); i++) {
644 		BMailChain *chain = (BMailChain *)chains.ItemAt(i);
645 		item = new BMenuItem(chain->Name(), msg = new BMessage(P_ACCOUNT));
646 
647 		msg->AddInt32("id",chain->ID());
648 
649 		if (account == chain->ID())
650 			item->SetMarked(true);
651 
652 		menu->AddItem(item);
653 		delete chain;
654 	}
655 	return menu;
656 }
657 
658 
659 BPopUpMenu *
660 TPrefsWindow::BuildReplyToMenu(int32 account)
661 {
662 	BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING);
663 
664 	BMenuItem *item;
665 	BMessage *msg;
666 	menu->AddItem(item = new BMenuItem(REPLYTO_USE_DEFAULT_TEXT, msg = new BMessage(P_REPLYTO)));
667 	msg->AddInt32("replyTo", ACCOUNT_USE_DEFAULT);
668 	if (account == ACCOUNT_USE_DEFAULT)
669 		item->SetMarked(true);
670 
671 	menu->AddItem(item = new BMenuItem(REPLYTO_FROM_MAIL_TEXT, msg = new BMessage(P_REPLYTO)));
672 	msg->AddInt32("replyTo", ACCOUNT_FROM_MAIL);
673 	if (account == ACCOUNT_FROM_MAIL)
674 		item->SetMarked(true);
675 
676 	return menu;
677 }
678 
679 
680 BMenu *
681 TPrefsWindow::BuildReplyPreambleMenu()
682 {
683 	const char *substitutes[] = {
684 /* To do: Not yet working, leave out for 2.0.0 beta 4:
685 		"%f - First name",
686 		"%l - Last name",
687 */
688 		MDR_DIALECT_CHOICE ("%n - Full name", "%n - フルネーム"),
689 		MDR_DIALECT_CHOICE ("%e - E-mail address", "%e - E-mailアドレス"),
690 		MDR_DIALECT_CHOICE ("%d - Date", "%d - 日付"),
691 		"",
692 		MDR_DIALECT_CHOICE ("\\n - Newline", "\\n - 空行"),
693 		NULL
694 	};
695 
696 	BMenu *menu = new BMenu(B_EMPTY_STRING);
697 
698 	for (int32 i = 0; substitutes[i]; i++)
699 	{
700 		if (*substitutes[i] == '\0')
701 			menu->AddSeparatorItem();
702 		else
703 			menu->AddItem(new BMenuItem(substitutes[i], new BMessage(P_REPLY_PREAMBLE)));
704 	}
705 
706 	return menu;
707 }
708 
709 
710 BPopUpMenu *
711 TPrefsWindow::BuildSignatureMenu(char *sig)
712 {
713 	char			name[B_FILE_NAME_LENGTH];
714 	BEntry			entry;
715 	BFile			file;
716 	BMenuItem		*item;
717 	BMessage		*msg;
718 	BPopUpMenu		*menu;
719 	BQuery			query;
720 	BVolume			vol;
721 	BVolumeRoster	volume;
722 
723 	menu = new BPopUpMenu("");
724 
725 	msg = new BMessage(P_SIG);
726 	msg->AddString("signature", SIG_NONE);
727 	menu->AddItem(item = new BMenuItem(SIG_NONE, msg));
728 	if (!strcmp(sig, SIG_NONE))
729 		item->SetMarked(true);
730 
731 	msg = new BMessage(P_SIG);
732 	msg->AddString("signature", SIG_RANDOM);
733 	menu->AddItem(item = new BMenuItem(SIG_RANDOM, msg));
734 	if (!strcmp(sig, SIG_RANDOM))
735 		item->SetMarked(true);
736 	menu->AddSeparatorItem();
737 
738 	volume.GetBootVolume(&vol);
739 	query.SetVolume(&vol);
740 	query.SetPredicate("_signature = *");
741 	query.Fetch();
742 
743 	while (query.GetNextEntry(&entry) == B_NO_ERROR) {
744 		file.SetTo(&entry, O_RDONLY);
745 		if (file.InitCheck() == B_NO_ERROR) {
746 			msg = new BMessage(P_SIG);
747 			file.ReadAttr("_signature", B_STRING_TYPE, 0, name, sizeof(name));
748 			msg->AddString("signature", name);
749 			menu->AddItem(item = new BMenuItem(name, msg));
750 			if (!strcmp(sig, name))
751 				item->SetMarked(true);
752 		}
753 	}
754 	return menu;
755 }
756 
757 
758 BPopUpMenu *
759 TPrefsWindow::BuildSizeMenu(BFont *font)
760 {
761 	char		label[16];
762 	uint32		loop;
763 	int32		sizes[] = {9, 10, 11, 12, 14, 18, 24};
764 	float		size;
765 	BMenuItem	*item;
766 	BMessage	*msg;
767 	BPopUpMenu	*menu;
768 
769 	menu = new BPopUpMenu("");
770 	size = font->Size();
771 	for (loop = 0; loop < sizeof(sizes) / sizeof(int32); loop++) {
772 		msg = new BMessage(P_SIZE);
773 		msg->AddInt32("size", sizes[loop]);
774 		sprintf(label, "%ld", sizes[loop]);
775 		menu->AddItem(item = new BMenuItem(label, msg));
776 		if (sizes[loop] == (int32)size)
777 			item->SetMarked(true);
778 	}
779 	return menu;
780 }
781 
782 
783 BPopUpMenu *
784 TPrefsWindow::BuildBoolMenu(uint32 what,const char *boolItem,bool isTrue)
785 {
786 	BMenuItem	*item;
787 	BMessage	*msg;
788 	BPopUpMenu	*menu;
789 
790 	menu = new BPopUpMenu("");
791 	msg = new BMessage(what);
792 	msg->AddBool(boolItem, true);
793 	menu->AddItem(item = new BMenuItem("On", msg));
794 	if (isTrue)
795 		item->SetMarked(true);
796 
797 	msg = new BMessage(what);
798 	msg->AddInt32(boolItem, false);
799 	menu->AddItem(item = new BMenuItem("Off", msg));
800 	if (!isTrue)
801 		item->SetMarked(true);
802 
803 	return menu;
804 }
805 
806 
807 BPopUpMenu *
808 TPrefsWindow::BuildWrapMenu(bool wrap)
809 {
810 	return BuildBoolMenu(P_WRAP,"wrap",wrap);
811 }
812 
813 
814 BPopUpMenu *
815 TPrefsWindow::BuildAttachAttributesMenu(bool attachAttributes)
816 {
817 	BMenuItem	*item;
818 	BMessage	*msg;
819 	BPopUpMenu	*menu;
820 
821 	menu = new BPopUpMenu("");
822 	msg = new BMessage(P_ATTACH_ATTRIBUTES);
823 	msg->AddBool("attachAttributes", true);
824 	menu->AddItem(item = new BMenuItem(ATTRIBUTE_ON_TEXT, msg));
825 	if (attachAttributes)
826 		item->SetMarked(true);
827 
828 	msg = new BMessage(P_ATTACH_ATTRIBUTES);
829 	msg->AddInt32("attachAttributes", false);
830 	menu->AddItem(item = new BMenuItem(ATTRIBUTE_OFF_TEXT, msg));
831 	if (!attachAttributes)
832 		item->SetMarked(true);
833 
834 	return menu;
835 }
836 
837 
838 BPopUpMenu *
839 TPrefsWindow::BuildColoredQuotesMenu(bool quote)
840 {
841 	return BuildBoolMenu(P_COLORED_QUOTES,"cquotes",quote);
842 }
843 
844 
845 BPopUpMenu *
846 TPrefsWindow::BuildEncodingMenu(uint32 encoding)
847 {
848 	BMenuItem	*item;
849 	BMessage	*msg;
850 	BPopUpMenu	*menu;
851 
852 	menu = new BPopUpMenu("");
853 
854 	BCharacterSetRoster roster;
855 	BCharacterSet charset;
856 	while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) {
857 		BString name(charset.GetPrintName());
858 		const char * mime = charset.GetMIMEName();
859 		if (mime) {
860 			name << " (" << mime << ")";
861 		}
862 		msg = new BMessage(P_ENC);
863 		uint32 convert_id;
864 		if ((mime == 0) || (strcasecmp(mime, "UTF-8") != 0)) {
865 			convert_id = charset.GetConversionID();
866 		} else {
867 			convert_id = B_MAIL_UTF8_CONVERSION;
868 		}
869 		msg->AddInt32("encoding", convert_id);
870 		menu->AddItem(item = new BMenuItem(name.String(), msg));
871 		if (convert_id == encoding) {
872 			item->SetMarked(true);
873 		}
874 	}
875 
876 	msg = new BMessage(P_ENC);
877 	msg->AddInt32("encoding", B_MAIL_US_ASCII_CONVERSION);
878 	menu->AddItem(item = new BMenuItem("US-ASCII", msg));
879 	if (encoding == B_MAIL_US_ASCII_CONVERSION) {
880 		item->SetMarked(true);
881 	}
882 
883 	return menu;
884 }
885 
886 
887 BPopUpMenu *
888 TPrefsWindow::BuildWarnUnencodableMenu(bool warnUnencodable)
889 {
890 	return BuildBoolMenu(P_WARN_UNENCODABLE,"warnUnencodable",warnUnencodable);
891 }
892 
893 
894 BPopUpMenu *
895 TPrefsWindow::BuildSpellCheckStartOnMenu(bool spellCheckStartOn)
896 {
897 	return BuildBoolMenu(P_SPELL_CHECK_START_ON, "spellCheckStartOn", spellCheckStartOn);
898 }
899 
900 
901 BPopUpMenu *
902 TPrefsWindow::BuildButtonBarMenu(uint8 show)
903 {
904 	BMenuItem	*item;
905 	BMessage	*msg;
906 	BPopUpMenu	*menu;
907 
908 	menu = new BPopUpMenu("");
909 
910 	msg = new BMessage(P_BUTTON_BAR);
911 	msg->AddInt8("bar", 1);
912 	menu->AddItem(item = new BMenuItem(ICON_LABEL_TEXT, msg));
913 	if (show & 1)
914 		item->SetMarked(true);
915 
916 	msg = new BMessage(P_BUTTON_BAR);
917 	msg->AddInt8("bar", 2);
918 	menu->AddItem(item = new BMenuItem(ICON_TEXT, msg));
919 	if (show & 2)
920 		item->SetMarked(true);
921 
922 	msg = new BMessage(P_BUTTON_BAR);
923 	msg->AddInt8("bar", 0);
924 	menu->AddItem(item = new BMenuItem(HIDE_TEXT, msg));
925 	if (!show)
926 		item->SetMarked(true);
927 
928 	return menu;
929 }
930