xref: /haiku/src/apps/mail/Prefs.cpp (revision 0c93c0a807b27096abbfad677436afb7d1712d4a)
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 	BMessage	msg(WINDOW_CLOSED);
308 
309 	prefs_window = Frame().LeftTop();
310 
311 	msg.AddInt32("kind", PREFS_WINDOW);
312 	be_app->PostMessage(&msg);
313 }
314 
315 
316 void
317 TPrefsWindow::MessageReceived(BMessage *msg)
318 {
319 	bool		changed;
320 	bool		revert = true;
321 	const char	*family;
322 	const char	*signature;
323 	const char	*style;
324 	char		label[256];
325 	int32		new_size;
326 	int32		old_size;
327 	font_family	new_family;
328 	font_family	old_family;
329 	font_style	new_style;
330 	font_style	old_style;
331 	BMenuItem	*item;
332 	BMessage	message;
333 
334 	switch (msg->what)
335 	{
336 		case P_OK:
337 			if (strcmp(fReplyPreamble->Text(), *fNewPreamble))
338 			{
339 				free(*fNewPreamble);
340 				*fNewPreamble = (char *)malloc(strlen(fReplyPreamble->Text()) + 1);
341 				strcpy(*fNewPreamble, fReplyPreamble->Text());
342 			}
343 			be_app->PostMessage(PREFS_CHANGED);
344 			Quit();
345 			break;
346 
347 		case P_CANCEL:
348 			revert = false;
349 			// supposed to fall through
350 		case P_REVERT:
351 			fFont.GetFamilyAndStyle(&old_family, &old_style);
352 			fNewFont->GetFamilyAndStyle(&new_family, &new_style);
353 			old_size = (int32) fFont.Size();
354 			new_size = (int32) fNewFont->Size();
355 			if (strcmp(old_family, new_family) || strcmp(old_style, new_style)
356 				|| old_size != new_size)
357 			{
358 				fNewFont->SetFamilyAndStyle(old_family, old_style);
359 				if (revert)
360 				{
361 					sprintf(label, "%s %s", old_family, old_style);
362 					item = fFontMenu->FindItem(label);
363 					item->SetMarked(true);
364 				}
365 
366 				fNewFont->SetSize(old_size);
367 				if (revert)
368 				{
369 					sprintf(label, "%ld", old_size);
370 					item = fSizeMenu->FindItem(label);
371 					item->SetMarked(true);
372 				}
373 				message.what = M_FONT;
374 				be_app->PostMessage(&message);
375 			}
376 			*fNewWrap = fWrap;
377 			*fNewAttachAttributes = fAttachAttributes;
378 
379 			if (strcmp(fSignature, *fNewSignature))
380 			{
381 				free(*fNewSignature);
382 				*fNewSignature = (char *)malloc(strlen(fSignature) + 1);
383 				strcpy(*fNewSignature, fSignature);
384 			}
385 
386 			*fNewEncoding = fEncoding;
387 			*fNewWarnUnencodable = fWarnUnencodable;
388 			*fNewSpellCheckStartOn = fSpellCheckStartOn;
389 			*fNewButtonBar = fButtonBar;
390 
391 			be_app->PostMessage(PREFS_CHANGED);
392 
393 			if (revert)
394 			{
395 				for (int i = fAccountMenu->CountItems();i-- > 0;)
396 				{
397 					if (BMenuItem *item = fAccountMenu->ItemAt(i))
398 						if (item->Message()->FindInt32("id") == *(int32 *)&fAccount)
399 							item->SetMarked(true);
400 				}
401 
402 				strcpy(label,fReplyTo == ACCOUNT_USE_DEFAULT ? REPLYTO_USE_DEFAULT_TEXT
403 															 : REPLYTO_FROM_MAIL_TEXT);
404 				if ((item = fReplyToMenu->FindItem(label)) != NULL)
405 					item->SetMarked(true);
406 
407 				strcpy(label, fWrap ? "On" : "Off");
408 				if ((item = fWrapMenu->FindItem(label)) != NULL)
409 					item->SetMarked(true);
410 
411 				strcpy(label, fAttachAttributes ? ATTRIBUTE_ON_TEXT : ATTRIBUTE_OFF_TEXT);
412 				if ((item = fAttachAttributesMenu->FindItem(label)) != NULL)
413 					item->SetMarked(true);
414 
415 				strcpy(label, fColoredQuotes ? "On" : "Off");
416 				if ((item = fColoredQuotesMenu->FindItem(label)) != NULL)
417 					item->SetMarked(true);
418 
419 				if (strcmp(fReplyPreamble->Text(), *fNewPreamble))
420 					fReplyPreamble->SetText(*fNewPreamble);
421 
422 				item = fSignatureMenu->FindItem(fSignature);
423 				if (item)
424 					item->SetMarked(true);
425 
426 				uint32 index = 0;
427 				while ((item = fEncodingMenu->ItemAt(index++)) != NULL) {
428 					BMessage * message = item->Message();
429 					if (message == NULL) {
430 						continue;
431 					}
432 					int32 encoding;
433 					if ((message->FindInt32("encoding", &encoding) == B_OK) &&
434 					    ((uint32)encoding == *fNewEncoding)) {
435 						item->SetMarked(true);
436 						break;
437 					}
438 				}
439 
440 				strcpy(label, fWarnUnencodable ? "On" : "Off");
441 				if ((item = fWarnUnencodableMenu->FindItem(label)) != NULL)
442 					item->SetMarked(true);
443 
444 				strcpy(label, fSpellCheckStartOn ? "On" : "Off");
445 				if ((item = fSpellCheckStartOnMenu->FindItem(label)) != NULL)
446 					item->SetMarked(true);
447 			}
448 			else
449 				Quit();
450 			break;
451 
452 		case P_FONT:
453 			family = NULL;
454 			style = NULL;
455 			int32 family_menu_index;
456 			if (msg->FindString("font", &family) == B_OK)
457 			{
458 				msg->FindString("style", &style);
459 				fNewFont->SetFamilyAndStyle(family, style);
460 				message.what = M_FONT;
461 				be_app->PostMessage(&message);
462 			}
463 
464 			/* grab this little tidbit so we can set the correct Family */
465 			if(msg->FindInt32("parent_index", &family_menu_index) == B_OK)
466 				fFontMenu->ItemAt(family_menu_index)->SetMarked(true);
467 			break;
468 
469 		case P_SIZE:
470 			old_size = (int32) fNewFont->Size();
471 			msg->FindInt32("size", &new_size);
472 			if (old_size != new_size)
473 			{
474 				fNewFont->SetSize(new_size);
475 				message.what = M_FONT;
476 				be_app->PostMessage(&message);
477 			}
478 			break;
479 
480 		case P_WRAP:
481 			msg->FindBool("wrap", fNewWrap);
482 			break;
483 		case P_ATTACH_ATTRIBUTES:
484 			msg->FindBool("attachAttributes", fNewAttachAttributes);
485 			break;
486 		case P_COLORED_QUOTES:
487 			msg->FindBool("cquotes", fNewColoredQuotes);
488 			break;
489 		case P_ACCOUNT:
490 			msg->FindInt32("id",(int32 *)fNewAccount);
491 			break;
492 		case P_REPLYTO:
493 			msg->FindInt32("replyTo", fNewReplyTo);
494 			break;
495 		case P_REPLY_PREAMBLE:
496 		{
497 			int32 index = -1;
498 			if (msg->FindInt32("index", &index) < B_OK)
499 				break;
500 			BMenuItem *item = fReplyPreambleMenu->ItemAt(index);
501 			if (item == NULL) {
502 				msg->PrintToStream();
503 				break;
504 			}
505 
506 			BTextView *text = fReplyPreamble->TextView();
507 			// To do: insert at selection point rather than at the end.
508 			text->Insert(text->TextLength(), item->Label(), 2);
509 		}
510 		case P_SIG:
511 			free(*fNewSignature);
512 			if (msg->FindString("signature", &signature) == B_NO_ERROR) {
513 				*fNewSignature = (char *)malloc(strlen(signature) + 1);
514 				strcpy(*fNewSignature, signature);
515 			} else {
516 				*fNewSignature = (char *)malloc(strlen(SIG_NONE) + 1);
517 				strcpy(*fNewSignature, SIG_NONE);
518 			}
519 			break;
520 		case P_ENC:
521 			msg->FindInt32("encoding", (int32 *)fNewEncoding);
522 			break;
523 		case P_WARN_UNENCODABLE:
524 			msg->FindBool("warnUnencodable", fNewWarnUnencodable);
525 			break;
526 		case P_SPELL_CHECK_START_ON:
527 			msg->FindBool("spellCheckStartOn", fNewSpellCheckStartOn);
528 			break;
529 		case P_BUTTON_BAR:
530 			msg->FindInt8("bar", (int8 *)fNewButtonBar);
531 			be_app->PostMessage(PREFS_CHANGED);
532 			break;
533 
534 		default:
535 			BWindow::MessageReceived(msg);
536 	}
537 
538 	fFont.GetFamilyAndStyle(&old_family, &old_style);
539 	fNewFont->GetFamilyAndStyle(&new_family, &new_style);
540 	old_size = (int32) fFont.Size();
541 	new_size = (int32) fNewFont->Size();
542 	changed = old_size != new_size
543 		|| fWrap != *fNewWrap
544 		|| fAttachAttributes != *fNewAttachAttributes
545 		|| fColoredQuotes != *fNewColoredQuotes
546 		|| fAccount != *fNewAccount
547 		|| fReplyTo != *fNewReplyTo
548 		|| strcmp(old_family, new_family)
549 		|| strcmp(old_style, new_style)
550 		|| strcmp(fReplyPreamble->Text(), *fNewPreamble)
551 		|| strcmp(fSignature, *fNewSignature)
552 		|| fEncoding != *fNewEncoding
553 		|| fWarnUnencodable != *fNewWarnUnencodable
554 		|| fSpellCheckStartOn != *fNewSpellCheckStartOn
555 		|| fButtonBar != *fNewButtonBar;
556 	fRevert->SetEnabled(changed);
557 }
558 
559 
560 BPopUpMenu *
561 TPrefsWindow::BuildFontMenu(BFont *font)
562 {
563 	font_family	def_family;
564 	font_style	def_style;
565 	font_family	f_family;
566 	font_style	f_style;
567 
568 	BPopUpMenu *menu = new BPopUpMenu("");
569 	font->GetFamilyAndStyle(&def_family, &def_style);
570 
571 	int32 family_menu_index = 0;
572 	int family_count = count_font_families();
573 	for (int family_loop = 0; family_loop < family_count; family_loop++) {
574 		get_font_family(family_loop, &f_family);
575 		BMenu *family_menu = new BMenu(f_family);
576 
577 		int style_count = count_font_styles(f_family);
578 		for (int style_loop = 0; style_loop < style_count; style_loop++) {
579 			get_font_style(f_family, style_loop, &f_style);
580 
581 			BMessage *msg = new BMessage(P_FONT);
582 			msg->AddString("font", f_family);
583 			msg->AddString("style", f_style);
584 			/* we send this to make setting the Family easier when things change */
585 			msg->AddInt32("parent_index", family_menu_index);
586 
587 			BMenuItem *item = new BMenuItem(f_style, msg);
588 			family_menu->AddItem(item);
589 			if ((strcmp(def_family, f_family) == 0) && (strcmp(def_style, f_style) == 0))
590 				item->SetMarked(true);
591 
592 			item->SetTarget(this);
593 		}
594 
595 		menu->AddItem(family_menu);
596 		BMenuItem *item = menu->ItemAt(family_menu_index);
597 		BMessage *msg = new BMessage(P_FONT);
598 		msg->AddString("font", f_family);
599 
600 		item->SetMessage(msg);
601 		item->SetTarget(this);
602 		if (strcmp(def_family, f_family) == 0)
603 			item->SetMarked(true);
604 
605 		family_menu_index++;
606 	}
607 	return menu;
608 }
609 
610 
611 BPopUpMenu *
612 TPrefsWindow::BuildLevelMenu(int32 level)
613 {
614 	BMenuItem *item;
615 	BMessage *msg;
616 	BPopUpMenu *menu;
617 
618 	menu = new BPopUpMenu("");
619 	msg = new BMessage(P_LEVEL);
620 	msg->AddInt32("level", L_BEGINNER);
621 	menu->AddItem(item = new BMenuItem(MDR_DIALECT_CHOICE ("Beginner","初心者"),msg));
622 	if (level == L_BEGINNER)
623 		item->SetMarked(true);
624 
625 	msg = new BMessage(P_LEVEL);
626 	msg->AddInt32("level", L_EXPERT);
627 	menu->AddItem(item = new BMenuItem(MDR_DIALECT_CHOICE ("Expert","上級者"),msg));
628 	if (level == L_EXPERT)
629 		item->SetMarked(true);
630 
631 	return menu;
632 }
633 
634 
635 BPopUpMenu *
636 TPrefsWindow::BuildAccountMenu(uint32 account)
637 {
638 	BPopUpMenu *menu = new BPopUpMenu("");
639 	BMenuItem *item;
640 
641 	//menu->SetRadioMode(true);
642 	BList chains;
643 	if (GetOutboundMailChains(&chains) < B_OK) {
644 		menu->AddItem(item = new BMenuItem("<no account found>", NULL));
645 		item->SetEnabled(false);
646 		return menu;
647 	}
648 
649 	BMessage *msg;
650 	for (int32 i = 0; i < chains.CountItems(); i++) {
651 		BMailChain *chain = (BMailChain *)chains.ItemAt(i);
652 		item = new BMenuItem(chain->Name(), msg = new BMessage(P_ACCOUNT));
653 
654 		msg->AddInt32("id",chain->ID());
655 
656 		if (account == chain->ID())
657 			item->SetMarked(true);
658 
659 		menu->AddItem(item);
660 		delete chain;
661 	}
662 	return menu;
663 }
664 
665 
666 BPopUpMenu *
667 TPrefsWindow::BuildReplyToMenu(int32 account)
668 {
669 	BPopUpMenu *menu = new BPopUpMenu(B_EMPTY_STRING);
670 
671 	BMenuItem *item;
672 	BMessage *msg;
673 	menu->AddItem(item = new BMenuItem(REPLYTO_USE_DEFAULT_TEXT, msg = new BMessage(P_REPLYTO)));
674 	msg->AddInt32("replyTo", ACCOUNT_USE_DEFAULT);
675 	if (account == ACCOUNT_USE_DEFAULT)
676 		item->SetMarked(true);
677 
678 	menu->AddItem(item = new BMenuItem(REPLYTO_FROM_MAIL_TEXT, msg = new BMessage(P_REPLYTO)));
679 	msg->AddInt32("replyTo", ACCOUNT_FROM_MAIL);
680 	if (account == ACCOUNT_FROM_MAIL)
681 		item->SetMarked(true);
682 
683 	return menu;
684 }
685 
686 
687 BMenu *
688 TPrefsWindow::BuildReplyPreambleMenu()
689 {
690 	const char *substitutes[] = {
691 /* To do: Not yet working, leave out for 2.0.0 beta 4:
692 		"%f - First name",
693 		"%l - Last name",
694 */
695 		MDR_DIALECT_CHOICE ("%n - Full name", "%n - フルネーム"),
696 		MDR_DIALECT_CHOICE ("%e - E-mail address", "%e - E-mailアドレス"),
697 		MDR_DIALECT_CHOICE ("%d - Date", "%d - 日付"),
698 		"",
699 		MDR_DIALECT_CHOICE ("\\n - Newline", "\\n - 空行"),
700 		NULL
701 	};
702 
703 	BMenu *menu = new BMenu(B_EMPTY_STRING);
704 
705 	for (int32 i = 0; substitutes[i]; i++)
706 	{
707 		if (*substitutes[i] == '\0')
708 			menu->AddSeparatorItem();
709 		else
710 			menu->AddItem(new BMenuItem(substitutes[i], new BMessage(P_REPLY_PREAMBLE)));
711 	}
712 
713 	return menu;
714 }
715 
716 
717 BPopUpMenu *
718 TPrefsWindow::BuildSignatureMenu(char *sig)
719 {
720 	char			name[B_FILE_NAME_LENGTH];
721 	BEntry			entry;
722 	BFile			file;
723 	BMenuItem		*item;
724 	BMessage		*msg;
725 	BPopUpMenu		*menu;
726 	BQuery			query;
727 	BVolume			vol;
728 	BVolumeRoster	volume;
729 
730 	menu = new BPopUpMenu("");
731 
732 	msg = new BMessage(P_SIG);
733 	msg->AddString("signature", SIG_NONE);
734 	menu->AddItem(item = new BMenuItem(SIG_NONE, msg));
735 	if (!strcmp(sig, SIG_NONE))
736 		item->SetMarked(true);
737 
738 	msg = new BMessage(P_SIG);
739 	msg->AddString("signature", SIG_RANDOM);
740 	menu->AddItem(item = new BMenuItem(SIG_RANDOM, msg));
741 	if (!strcmp(sig, SIG_RANDOM))
742 		item->SetMarked(true);
743 	menu->AddSeparatorItem();
744 
745 	volume.GetBootVolume(&vol);
746 	query.SetVolume(&vol);
747 	query.SetPredicate("_signature = *");
748 	query.Fetch();
749 
750 	while (query.GetNextEntry(&entry) == B_NO_ERROR) {
751 		file.SetTo(&entry, O_RDONLY);
752 		if (file.InitCheck() == B_NO_ERROR) {
753 			msg = new BMessage(P_SIG);
754 			file.ReadAttr("_signature", B_STRING_TYPE, 0, name, sizeof(name));
755 			msg->AddString("signature", name);
756 			menu->AddItem(item = new BMenuItem(name, msg));
757 			if (!strcmp(sig, name))
758 				item->SetMarked(true);
759 		}
760 	}
761 	return menu;
762 }
763 
764 
765 BPopUpMenu *
766 TPrefsWindow::BuildSizeMenu(BFont *font)
767 {
768 	char		label[16];
769 	uint32		loop;
770 	int32		sizes[] = {9, 10, 11, 12, 14, 18, 24};
771 	float		size;
772 	BMenuItem	*item;
773 	BMessage	*msg;
774 	BPopUpMenu	*menu;
775 
776 	menu = new BPopUpMenu("");
777 	size = font->Size();
778 	for (loop = 0; loop < sizeof(sizes) / sizeof(int32); loop++) {
779 		msg = new BMessage(P_SIZE);
780 		msg->AddInt32("size", sizes[loop]);
781 		sprintf(label, "%ld", sizes[loop]);
782 		menu->AddItem(item = new BMenuItem(label, msg));
783 		if (sizes[loop] == (int32)size)
784 			item->SetMarked(true);
785 	}
786 	return menu;
787 }
788 
789 
790 BPopUpMenu *
791 TPrefsWindow::BuildBoolMenu(uint32 what,const char *boolItem,bool isTrue)
792 {
793 	BMenuItem	*item;
794 	BMessage	*msg;
795 	BPopUpMenu	*menu;
796 
797 	menu = new BPopUpMenu("");
798 	msg = new BMessage(what);
799 	msg->AddBool(boolItem, true);
800 	menu->AddItem(item = new BMenuItem("On", msg));
801 	if (isTrue)
802 		item->SetMarked(true);
803 
804 	msg = new BMessage(what);
805 	msg->AddInt32(boolItem, false);
806 	menu->AddItem(item = new BMenuItem("Off", msg));
807 	if (!isTrue)
808 		item->SetMarked(true);
809 
810 	return menu;
811 }
812 
813 
814 BPopUpMenu *
815 TPrefsWindow::BuildWrapMenu(bool wrap)
816 {
817 	return BuildBoolMenu(P_WRAP,"wrap",wrap);
818 }
819 
820 
821 BPopUpMenu *
822 TPrefsWindow::BuildAttachAttributesMenu(bool attachAttributes)
823 {
824 	BMenuItem	*item;
825 	BMessage	*msg;
826 	BPopUpMenu	*menu;
827 
828 	menu = new BPopUpMenu("");
829 	msg = new BMessage(P_ATTACH_ATTRIBUTES);
830 	msg->AddBool("attachAttributes", true);
831 	menu->AddItem(item = new BMenuItem(ATTRIBUTE_ON_TEXT, msg));
832 	if (attachAttributes)
833 		item->SetMarked(true);
834 
835 	msg = new BMessage(P_ATTACH_ATTRIBUTES);
836 	msg->AddInt32("attachAttributes", false);
837 	menu->AddItem(item = new BMenuItem(ATTRIBUTE_OFF_TEXT, msg));
838 	if (!attachAttributes)
839 		item->SetMarked(true);
840 
841 	return menu;
842 }
843 
844 
845 BPopUpMenu *
846 TPrefsWindow::BuildColoredQuotesMenu(bool quote)
847 {
848 	return BuildBoolMenu(P_COLORED_QUOTES,"cquotes",quote);
849 }
850 
851 
852 BPopUpMenu *
853 TPrefsWindow::BuildEncodingMenu(uint32 encoding)
854 {
855 	BMenuItem	*item;
856 	BMessage	*msg;
857 	BPopUpMenu	*menu;
858 
859 	menu = new BPopUpMenu("");
860 
861 	BCharacterSetRoster roster;
862 	BCharacterSet charset;
863 	while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) {
864 		BString name(charset.GetPrintName());
865 		const char * mime = charset.GetMIMEName();
866 		if (mime) {
867 			name << " (" << mime << ")";
868 		}
869 		msg = new BMessage(P_ENC);
870 		uint32 convert_id;
871 		if ((mime == 0) || (strcasecmp(mime, "UTF-8") != 0)) {
872 			convert_id = charset.GetConversionID();
873 		} else {
874 			convert_id = B_MAIL_UTF8_CONVERSION;
875 		}
876 		msg->AddInt32("encoding", convert_id);
877 		menu->AddItem(item = new BMenuItem(name.String(), msg));
878 		if (convert_id == encoding) {
879 			item->SetMarked(true);
880 		}
881 	}
882 
883 	msg = new BMessage(P_ENC);
884 	msg->AddInt32("encoding", B_MAIL_US_ASCII_CONVERSION);
885 	menu->AddItem(item = new BMenuItem("US-ASCII", msg));
886 	if (encoding == B_MAIL_US_ASCII_CONVERSION) {
887 		item->SetMarked(true);
888 	}
889 
890 	return menu;
891 }
892 
893 
894 BPopUpMenu *
895 TPrefsWindow::BuildWarnUnencodableMenu(bool warnUnencodable)
896 {
897 	return BuildBoolMenu(P_WARN_UNENCODABLE,"warnUnencodable",warnUnencodable);
898 }
899 
900 
901 BPopUpMenu *
902 TPrefsWindow::BuildSpellCheckStartOnMenu(bool spellCheckStartOn)
903 {
904 	return BuildBoolMenu(P_SPELL_CHECK_START_ON, "spellCheckStartOn", spellCheckStartOn);
905 }
906 
907 
908 BPopUpMenu *
909 TPrefsWindow::BuildButtonBarMenu(uint8 show)
910 {
911 	BMenuItem	*item;
912 	BMessage	*msg;
913 	BPopUpMenu	*menu;
914 
915 	menu = new BPopUpMenu("");
916 
917 	msg = new BMessage(P_BUTTON_BAR);
918 	msg->AddInt8("bar", 1);
919 	menu->AddItem(item = new BMenuItem(ICON_LABEL_TEXT, msg));
920 	if (show & 1)
921 		item->SetMarked(true);
922 
923 	msg = new BMessage(P_BUTTON_BAR);
924 	msg->AddInt8("bar", 2);
925 	menu->AddItem(item = new BMenuItem(ICON_TEXT, msg));
926 	if (show & 2)
927 		item->SetMarked(true);
928 
929 	msg = new BMessage(P_BUTTON_BAR);
930 	msg->AddInt8("bar", 0);
931 	menu->AddItem(item = new BMenuItem(HIDE_TEXT, msg));
932 	if (!show)
933 		item->SetMarked(true);
934 
935 	return menu;
936 }
937