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