xref: /haiku/src/apps/terminal/AppearPrefView.cpp (revision 52f7c9389475e19fc21487b38064b4390eeb6fea)
1 /*
2  * Copyright 2001-2015, Haiku, Inc.
3  * Copyright 2003-2004 Kian Duffy, myob@users.sourceforge.net
4  * Parts Copyright 1998-1999 Kazuho Okui and Takashi Murai.
5  * All rights reserved. Distributed under the terms of the MIT license.
6  */
7 
8 
9 #include "AppearPrefView.h"
10 
11 #include <stdio.h>
12 #include <stdlib.h>
13 
14 #include <Button.h>
15 #include <Catalog.h>
16 #include <CharacterSet.h>
17 #include <CharacterSetRoster.h>
18 #include <CheckBox.h>
19 #include <ColorControl.h>
20 #include <LayoutBuilder.h>
21 #include <Locale.h>
22 #include <Menu.h>
23 #include <MenuField.h>
24 #include <MenuItem.h>
25 #include <PopUpMenu.h>
26 #include <TextControl.h>
27 #include <View.h>
28 
29 #include "Colors.h"
30 #include "Globals.h"
31 #include "PrefHandler.h"
32 #include "TermConst.h"
33 #include "TermWindow.h"
34 
35 
36 #undef B_TRANSLATION_CONTEXT
37 #define B_TRANSLATION_CONTEXT "Terminal AppearancePrefView"
38 
39 
40 
41 // #pragma mark -
42 
43 
44 AppearancePrefView::AppearancePrefView(const char* name,
45 		const BMessenger& messenger)
46 	:
47 	BGroupView(name, B_VERTICAL, 5),
48 	fTerminalMessenger(messenger)
49 {
50 	const char* kColorTable[] = {
51 		B_TRANSLATE_MARK("Text"),
52 		B_TRANSLATE_MARK("Background"),
53 		B_TRANSLATE_MARK("Cursor"),
54 		B_TRANSLATE_MARK("Text under cursor"),
55 		B_TRANSLATE_MARK("Selected text"),
56 		B_TRANSLATE_MARK("Selected background"),
57 		"",
58 		B_TRANSLATE_MARK("ANSI black color"),
59 		B_TRANSLATE_MARK("ANSI red color"),
60 		B_TRANSLATE_MARK("ANSI green color"),
61 		B_TRANSLATE_MARK("ANSI yellow color"),
62 		B_TRANSLATE_MARK("ANSI blue color"),
63 		B_TRANSLATE_MARK("ANSI magenta color"),
64 		B_TRANSLATE_MARK("ANSI cyan color"),
65 		B_TRANSLATE_MARK("ANSI white color"),
66 		"",
67 		B_TRANSLATE_MARK("ANSI bright black color"),
68 		B_TRANSLATE_MARK("ANSI bright red color"),
69 		B_TRANSLATE_MARK("ANSI bright green color"),
70 		B_TRANSLATE_MARK("ANSI bright yellow color"),
71 		B_TRANSLATE_MARK("ANSI bright blue color"),
72 		B_TRANSLATE_MARK("ANSI bright magenta color"),
73 		B_TRANSLATE_MARK("ANSI bright cyan color"),
74 		B_TRANSLATE_MARK("ANSI bright white color"),
75 		NULL
76 	};
77 
78 	fBlinkCursor = new BCheckBox(
79 		B_TRANSLATE("Blinking cursor"),
80 			new BMessage(MSG_BLINK_CURSOR_CHANGED));
81 
82 	fAllowBold = new BCheckBox(
83 		B_TRANSLATE("Allow bold text"),
84 			new BMessage(MSG_ALLOW_BOLD_CHANGED));
85 
86 	fUseOptionAsMetaKey = new BCheckBox(
87 		B_TRANSLATE("Use left Option as Meta key"),
88 			new BMessage(MSG_USE_OPTION_AS_META_CHANGED));
89 
90 	fWarnOnExit = new BCheckBox(
91 		B_TRANSLATE("Confirm exit if active programs exist"),
92 			new BMessage(MSG_WARN_ON_EXIT_CHANGED));
93 
94 	BMenu* fontMenu = _MakeFontMenu(MSG_HALF_FONT_CHANGED,
95 		PrefHandler::Default()->getString(PREF_HALF_FONT_FAMILY),
96 		PrefHandler::Default()->getString(PREF_HALF_FONT_STYLE));
97 	fFontField = new BMenuField(B_TRANSLATE("Font:"), fontMenu);
98 
99 	BMenu* sizeMenu = new (std::nothrow) BPopUpMenu(
100 		B_TRANSLATE_COMMENT("Custom", "Window size"));
101 	if (sizeMenu != NULL) {
102 		TermWindow::MakeWindowSizeMenu(sizeMenu);
103 		sizeMenu->SetLabelFromMarked(true);
104 	}
105 	fWindowSizeField = new BMenuField(B_TRANSLATE("Window size:"), sizeMenu);
106 
107 	BMenu* encodingMenu = new (std::nothrow) BPopUpMenu("Text encoding");
108 	if (encodingMenu != NULL) {
109 		TermWindow::MakeEncodingMenu(encodingMenu);
110 		encodingMenu->SetLabelFromMarked(true);
111 	}
112 	fEncodingField = new BMenuField(B_TRANSLATE("Encoding:"), encodingMenu);
113 
114 	BPopUpMenu* schemesPopUp = _MakeColorSchemeMenu(MSG_COLOR_SCHEME_CHANGED,
115 		gPredefinedColorSchemes, gPredefinedColorSchemes[0]);
116 	fColorSchemeField = new BMenuField(B_TRANSLATE("Color scheme:"),
117 		schemesPopUp);
118 
119 	BPopUpMenu* colorsPopUp = _MakeMenu(MSG_COLOR_FIELD_CHANGED, kColorTable,
120 		kColorTable[0]);
121 
122 	fColorField = new BMenuField(B_TRANSLATE("Color:"), colorsPopUp);
123 
124 	fTabTitle = new BTextControl("tabTitle", B_TRANSLATE("Tab title:"), "",
125 		NULL);
126 	fTabTitle->SetModificationMessage(
127 		new BMessage(MSG_TAB_TITLE_SETTING_CHANGED));
128 	fTabTitle->SetToolTip(BString(B_TRANSLATE(
129 		"The pattern specifying the tab titles. The following placeholders\n"
130 		"can be used:")) << "\n" << kToolTipSetTabTitlePlaceholders
131 		<< "\n" << kToolTipCommonTitlePlaceholders);
132 
133 	fWindowTitle = new BTextControl("windowTitle", B_TRANSLATE("Window title:"),
134 		"", NULL);
135 	fWindowTitle->SetModificationMessage(
136 		new BMessage(MSG_WINDOW_TITLE_SETTING_CHANGED));
137 	fWindowTitle->SetToolTip(BString(B_TRANSLATE(
138 		"The pattern specifying the window titles. The following placeholders\n"
139 		"can be used:")) << "\n" << kToolTipSetWindowTitlePlaceholders
140 		<< "\n" << kToolTipCommonTitlePlaceholders);
141 
142 	BLayoutBuilder::Group<>(this)
143 		.SetInsets(5, 5, 5, 5)
144 		.AddGrid(5, 5)
145 			.Add(fTabTitle->CreateLabelLayoutItem(), 0, 0)
146 			.Add(fTabTitle->CreateTextViewLayoutItem(), 1, 0)
147 			.Add(fWindowTitle->CreateLabelLayoutItem(), 0, 1)
148 			.Add(fWindowTitle->CreateTextViewLayoutItem(), 1, 1)
149 			.Add(fWindowSizeField->CreateLabelLayoutItem(), 0, 2)
150 			.Add(fWindowSizeField->CreateMenuBarLayoutItem(), 1, 2)
151 			.Add(fFontField->CreateLabelLayoutItem(), 0, 3)
152 			.Add(fFontField->CreateMenuBarLayoutItem(), 1, 3)
153 			.Add(fEncodingField->CreateLabelLayoutItem(), 0, 4)
154 			.Add(fEncodingField->CreateMenuBarLayoutItem(), 1, 4)
155 			.Add(fColorSchemeField->CreateLabelLayoutItem(), 0, 5)
156 			.Add(fColorSchemeField->CreateMenuBarLayoutItem(), 1, 5)
157 			.Add(fColorField->CreateLabelLayoutItem(), 0, 6)
158 			.Add(fColorField->CreateMenuBarLayoutItem(), 1, 6)
159 			.End()
160 		.AddGlue()
161 		.Add(fColorControl = new BColorControl(BPoint(10, 10),
162 			B_CELLS_32x8, 8.0, "", new BMessage(MSG_COLOR_CHANGED)))
163 		.Add(fBlinkCursor)
164 		.Add(fAllowBold)
165 		.Add(fUseOptionAsMetaKey)
166 		.Add(fWarnOnExit);
167 
168 	fTabTitle->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
169 	fWindowTitle->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
170 	fFontField->SetAlignment(B_ALIGN_RIGHT);
171 	fWindowSizeField->SetAlignment(B_ALIGN_RIGHT);
172 	fEncodingField->SetAlignment(B_ALIGN_RIGHT);
173 	fColorField->SetAlignment(B_ALIGN_RIGHT);
174 	fColorSchemeField->SetAlignment(B_ALIGN_RIGHT);
175 
176 	Revert();
177 
178 	BTextControl* redInput = (BTextControl*)fColorControl->ChildAt(0);
179 	BTextControl* greenInput = (BTextControl*)fColorControl->ChildAt(1);
180 	BTextControl* blueInput = (BTextControl*)fColorControl->ChildAt(2);
181 
182 	redInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
183 	greenInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
184 	blueInput->SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
185 }
186 
187 
188 void
189 AppearancePrefView::Revert()
190 {
191 	PrefHandler* pref = PrefHandler::Default();
192 
193 	fTabTitle->SetText(pref->getString(PREF_TAB_TITLE));
194 	fWindowTitle->SetText(pref->getString(PREF_WINDOW_TITLE));
195 
196 	fBlinkCursor->SetValue(pref->getBool(PREF_BLINK_CURSOR));
197 	fAllowBold->SetValue(pref->getBool(PREF_ALLOW_BOLD));
198 	fUseOptionAsMetaKey->SetValue(pref->getBool(PREF_USE_OPTION_AS_META));
199 	fWarnOnExit->SetValue(pref->getBool(PREF_WARN_ON_EXIT));
200 
201 	_SetCurrentColorScheme();
202 	_SetEncoding(pref->getString(PREF_TEXT_ENCODING));
203 	_SetWindowSize(pref->getInt32(PREF_ROWS), pref->getInt32(PREF_COLS));
204 	fColorControl->SetValue(pref->getRGB(PREF_TEXT_FORE_COLOR));
205 
206 	const char* family = pref->getString(PREF_HALF_FONT_FAMILY);
207 	const char* style = pref->getString(PREF_HALF_FONT_STYLE);
208 	const char* size = pref->getString(PREF_HALF_FONT_SIZE);
209 
210 	_MarkSelectedFont(family, style, size);
211 }
212 
213 
214 void
215 AppearancePrefView::AttachedToWindow()
216 {
217 	fTabTitle->SetTarget(this);
218 	fWindowTitle->SetTarget(this);
219 	fBlinkCursor->SetTarget(this);
220 	fAllowBold->SetTarget(this);
221 	fUseOptionAsMetaKey->SetTarget(this);
222 	fWarnOnExit->SetTarget(this);
223 
224 	fFontField->Menu()->SetTargetForItems(this);
225 	for (int32 i = 0; i < fFontField->Menu()->CountItems(); i++) {
226 		BMenu* fontSizeMenu = fFontField->Menu()->SubmenuAt(i);
227 		if (fontSizeMenu == NULL)
228 			continue;
229 
230 		fontSizeMenu->SetTargetForItems(this);
231 	}
232 
233 	fColorControl->SetTarget(this);
234 	fColorField->Menu()->SetTargetForItems(this);
235 	fColorSchemeField->Menu()->SetTargetForItems(this);
236 	fWindowSizeField->Menu()->SetTargetForItems(this);
237 	fEncodingField->Menu()->SetTargetForItems(this);
238 
239 	_SetCurrentColorScheme();
240 }
241 
242 
243 void
244 
245 AppearancePrefView::MessageReceived(BMessage* msg)
246 {
247 	bool modified = false;
248 
249 	switch (msg->what) {
250 		case MSG_HALF_FONT_CHANGED:
251 		{
252 			const char* family = NULL;
253 			const char* style = NULL;
254 			const char* size = NULL;
255 			if (msg->FindString("font_family", &family) != B_OK
256 				|| msg->FindString("font_style", &style) != B_OK
257 				|| msg->FindString("font_size", &size) != B_OK) {
258 				break;
259 			}
260 
261 			PrefHandler* pref = PrefHandler::Default();
262 			const char* currentFamily
263 				= pref->getString(PREF_HALF_FONT_FAMILY);
264 			const char* currentStyle
265 				= pref->getString(PREF_HALF_FONT_STYLE);
266 			const char* currentSize
267 				= pref->getString(PREF_HALF_FONT_SIZE);
268 
269 			if (currentFamily == NULL || strcmp(currentFamily, family) != 0
270 				|| currentStyle == NULL || strcmp(currentStyle, style) != 0
271 				|| currentSize == NULL || strcmp(currentSize, size) != 0) {
272 				pref->setString(PREF_HALF_FONT_FAMILY, family);
273 				pref->setString(PREF_HALF_FONT_STYLE, style);
274 				pref->setString(PREF_HALF_FONT_SIZE, size);
275 				_MarkSelectedFont(family, style, size);
276 				modified = true;
277 			}
278 			break;
279 		}
280 
281 		case MSG_COLOR_CHANGED:
282 		{
283 			const BMessage* itemMessage
284 				= fColorField->Menu()->FindMarked()->Message();
285 			const char* label = NULL;
286 			if (itemMessage->FindString("label", &label) != B_OK)
287 				break;
288 			rgb_color oldColor = PrefHandler::Default()->getRGB(label);
289 			if (oldColor != fColorControl->ValueAsColor()) {
290 				BMenuItem* item = fColorSchemeField->Menu()->FindMarked();
291 				if (strcmp(item->Label(), gCustomColorScheme.name) != 0) {
292 					item->SetMarked(false);
293 					item = fColorSchemeField->Menu()->FindItem(
294 						gCustomColorScheme.name);
295 					if (item)
296 						item->SetMarked(true);
297 				}
298 
299 				PrefHandler::Default()->setRGB(label,
300 					fColorControl->ValueAsColor());
301 				modified = true;
302 			}
303 			break;
304 		}
305 
306 		case MSG_COLOR_SCHEME_CHANGED:
307 		{
308 			color_scheme* newScheme = NULL;
309 			if (msg->FindPointer("color_scheme",
310 					(void**)&newScheme) == B_OK) {
311 				_ChangeColorScheme(newScheme);
312 				const char* label = NULL;
313 				if (fColorField->Menu()->FindMarked()->Message()->FindString(
314 						"label", &label) == B_OK)
315 					fColorControl->SetValue(
316 						PrefHandler::Default()->getRGB(label));
317 				modified = true;
318 			}
319 			break;
320 		}
321 
322 		case MSG_COLOR_FIELD_CHANGED:
323 		{
324 			const char* label = NULL;
325 			if (msg->FindString("label", &label) == B_OK)
326 				fColorControl->SetValue(PrefHandler::Default()->getRGB(label));
327 			break;
328 		}
329 
330 		case MSG_COLS_CHANGED:
331 		{
332 			int rows = msg->FindInt32("rows");
333 			int columns = msg->FindInt32("columns");
334 			_SetWindowSize(rows, columns);
335 			PrefHandler* handler = PrefHandler::Default();
336 			if (handler->getInt32(PREF_ROWS) != rows) {
337 				PrefHandler::Default()->setInt32(PREF_ROWS, rows);
338 				modified = true;
339 			}
340 			if (handler->getInt32(PREF_COLS) != columns) {
341 				PrefHandler::Default()->setInt32(PREF_COLS, columns);
342 				modified = true;
343 			}
344 
345 			break;
346 		}
347 
348 		case MSG_BLINK_CURSOR_CHANGED:
349 			if (PrefHandler::Default()->getBool(PREF_BLINK_CURSOR)
350 				!= fBlinkCursor->Value()) {
351 					PrefHandler::Default()->setBool(PREF_BLINK_CURSOR,
352 						fBlinkCursor->Value());
353 					modified = true;
354 			}
355 			break;
356 
357 		case MSG_ALLOW_BOLD_CHANGED:
358 			if (PrefHandler::Default()->getBool(PREF_ALLOW_BOLD)
359 				!= fAllowBold->Value()) {
360 					PrefHandler::Default()->setBool(PREF_ALLOW_BOLD,
361 						fAllowBold->Value());
362 					modified = true;
363 			}
364 			break;
365 
366 		case MSG_USE_OPTION_AS_META_CHANGED:
367 			if (PrefHandler::Default()->getBool(PREF_USE_OPTION_AS_META)
368 				!= fUseOptionAsMetaKey->Value()) {
369 					PrefHandler::Default()->setBool(PREF_USE_OPTION_AS_META,
370 						fUseOptionAsMetaKey->Value());
371 					modified = true;
372 			}
373 			break;
374 
375 		case MSG_WARN_ON_EXIT_CHANGED:
376 			if (PrefHandler::Default()->getBool(PREF_WARN_ON_EXIT)
377 				!= fWarnOnExit->Value()) {
378 					PrefHandler::Default()->setBool(PREF_WARN_ON_EXIT,
379 						fWarnOnExit->Value());
380 					modified = true;
381 			}
382 			break;
383 
384 		case MSG_TAB_TITLE_SETTING_CHANGED:
385 		{
386 			BString oldValue(PrefHandler::Default()->getString(PREF_TAB_TITLE));
387 			if (oldValue != fTabTitle->Text()) {
388 				PrefHandler::Default()->setString(PREF_TAB_TITLE,
389 					fTabTitle->Text());
390 				modified = true;
391 			}
392 			break;
393 		}
394 
395 		case MSG_WINDOW_TITLE_SETTING_CHANGED:
396 		{
397 			BString oldValue(PrefHandler::Default()->getString(
398 				PREF_WINDOW_TITLE));
399 			if (oldValue != fWindowTitle->Text()) {
400 				PrefHandler::Default()->setString(PREF_WINDOW_TITLE,
401 					fWindowTitle->Text());
402 				modified = true;
403 			}
404 			break;
405 		}
406 
407 		default:
408 			BView::MessageReceived(msg);
409 			return;
410 	}
411 
412 	if (modified) {
413 		fTerminalMessenger.SendMessage(msg);
414 
415 		BMessenger messenger(this);
416 		messenger.SendMessage(MSG_PREF_MODIFIED);
417 	}
418 }
419 
420 
421 void
422 AppearancePrefView::_ChangeColorScheme(color_scheme* scheme)
423 {
424 	PrefHandler* pref = PrefHandler::Default();
425 
426 	pref->setRGB(PREF_TEXT_FORE_COLOR, scheme->text_fore_color);
427 	pref->setRGB(PREF_TEXT_BACK_COLOR, scheme->text_back_color);
428 	pref->setRGB(PREF_SELECT_FORE_COLOR, scheme->select_fore_color);
429 	pref->setRGB(PREF_SELECT_BACK_COLOR, scheme->select_back_color);
430 	pref->setRGB(PREF_CURSOR_FORE_COLOR, scheme->cursor_fore_color);
431 	pref->setRGB(PREF_CURSOR_BACK_COLOR, scheme->cursor_back_color);
432 	pref->setRGB(PREF_ANSI_BLACK_COLOR, scheme->ansi_colors.black);
433 	pref->setRGB(PREF_ANSI_RED_COLOR, scheme->ansi_colors.red);
434 	pref->setRGB(PREF_ANSI_GREEN_COLOR, scheme->ansi_colors.green);
435 	pref->setRGB(PREF_ANSI_YELLOW_COLOR, scheme->ansi_colors.yellow);
436 	pref->setRGB(PREF_ANSI_BLUE_COLOR, scheme->ansi_colors.blue);
437 	pref->setRGB(PREF_ANSI_MAGENTA_COLOR, scheme->ansi_colors.magenta);
438 	pref->setRGB(PREF_ANSI_CYAN_COLOR, scheme->ansi_colors.cyan);
439 	pref->setRGB(PREF_ANSI_WHITE_COLOR, scheme->ansi_colors.white);
440 	pref->setRGB(PREF_ANSI_BLACK_HCOLOR, scheme->ansi_colors_h.black);
441 	pref->setRGB(PREF_ANSI_RED_HCOLOR, scheme->ansi_colors_h.red);
442 	pref->setRGB(PREF_ANSI_GREEN_HCOLOR, scheme->ansi_colors_h.green);
443 	pref->setRGB(PREF_ANSI_YELLOW_HCOLOR, scheme->ansi_colors_h.yellow);
444 	pref->setRGB(PREF_ANSI_BLUE_HCOLOR, scheme->ansi_colors_h.blue);
445 	pref->setRGB(PREF_ANSI_MAGENTA_HCOLOR, scheme->ansi_colors_h.magenta);
446 	pref->setRGB(PREF_ANSI_CYAN_HCOLOR, scheme->ansi_colors_h.cyan);
447 	pref->setRGB(PREF_ANSI_WHITE_HCOLOR, scheme->ansi_colors_h.white);
448 }
449 
450 
451 void
452 AppearancePrefView::_SetCurrentColorScheme()
453 {
454 	PrefHandler* pref = PrefHandler::Default();
455 
456 	gCustomColorScheme.text_fore_color = pref->getRGB(PREF_TEXT_FORE_COLOR);
457 	gCustomColorScheme.text_back_color = pref->getRGB(PREF_TEXT_BACK_COLOR);
458 	gCustomColorScheme.select_fore_color = pref->getRGB(PREF_SELECT_FORE_COLOR);
459 	gCustomColorScheme.select_back_color = pref->getRGB(PREF_SELECT_BACK_COLOR);
460 	gCustomColorScheme.cursor_fore_color = pref->getRGB(PREF_CURSOR_FORE_COLOR);
461 	gCustomColorScheme.cursor_back_color = pref->getRGB(PREF_CURSOR_BACK_COLOR);
462 	gCustomColorScheme.ansi_colors.black = pref->getRGB(PREF_ANSI_BLACK_COLOR);
463 	gCustomColorScheme.ansi_colors.red = pref->getRGB(PREF_ANSI_RED_COLOR);
464 	gCustomColorScheme.ansi_colors.green = pref->getRGB(PREF_ANSI_GREEN_COLOR);
465 	gCustomColorScheme.ansi_colors.yellow = pref->getRGB(PREF_ANSI_YELLOW_COLOR);
466 	gCustomColorScheme.ansi_colors.blue = pref->getRGB(PREF_ANSI_BLUE_COLOR);
467 	gCustomColorScheme.ansi_colors.magenta =
468 		pref->getRGB(PREF_ANSI_MAGENTA_COLOR);
469 	gCustomColorScheme.ansi_colors.cyan = pref->getRGB(PREF_ANSI_CYAN_COLOR);
470 	gCustomColorScheme.ansi_colors.white = pref->getRGB(PREF_ANSI_WHITE_COLOR);
471 	gCustomColorScheme.ansi_colors_h.black = pref->getRGB(PREF_ANSI_BLACK_HCOLOR);
472 	gCustomColorScheme.ansi_colors_h.red = pref->getRGB(PREF_ANSI_RED_HCOLOR);
473 	gCustomColorScheme.ansi_colors_h.green = pref->getRGB(PREF_ANSI_GREEN_HCOLOR);
474 	gCustomColorScheme.ansi_colors_h.yellow =
475 		pref->getRGB(PREF_ANSI_YELLOW_HCOLOR);
476 	gCustomColorScheme.ansi_colors_h.blue = pref->getRGB(PREF_ANSI_BLUE_HCOLOR);
477 	gCustomColorScheme.ansi_colors_h.magenta =
478 		pref->getRGB(PREF_ANSI_MAGENTA_HCOLOR);
479 	gCustomColorScheme.ansi_colors_h.cyan = pref->getRGB(PREF_ANSI_CYAN_HCOLOR);
480 	gCustomColorScheme.ansi_colors_h.white = pref->getRGB(PREF_ANSI_WHITE_HCOLOR);
481 
482 	const char* currentSchemeName = NULL;
483 
484 	for (const color_scheme** schemes = gPredefinedColorSchemes;
485 			*schemes != NULL; schemes++) {
486 		if (gCustomColorScheme == **schemes) {
487 			currentSchemeName = (*schemes)->name;
488 			break;
489 		}
490 	}
491 
492 	// If the scheme is not one of the known ones, assume a custom one.
493 	if (currentSchemeName == NULL)
494 		currentSchemeName = "Custom";
495 
496 	for (int32 i = 0; i < fColorSchemeField->Menu()->CountItems(); i++) {
497 		BMenuItem* item = fColorSchemeField->Menu()->ItemAt(i);
498 		if (strcmp(item->Label(), currentSchemeName) == 0) {
499 			item->SetMarked(true);
500 			break;
501 		}
502 	}
503 }
504 
505 
506 void
507 AppearancePrefView::_SetEncoding(const char* name)
508 {
509 	const BPrivate::BCharacterSet* charset
510 		= BPrivate::BCharacterSetRoster::FindCharacterSetByName(name);
511 	if (charset == NULL)
512 		return;
513 	int code = charset->GetConversionID();
514 	for (int32 i = 0; i < fEncodingField->Menu()->CountItems(); i++) {
515 		BMenuItem* item = fEncodingField->Menu()->ItemAt(i);
516 		BMessage* msg = item->Message();
517 		if (msg->FindInt32("op") == code) {
518 			item->SetMarked(true);
519 			break;
520 		}
521 	}
522 }
523 
524 
525 void
526 AppearancePrefView::_SetWindowSize(int rows, int cols)
527 {
528 	for (int32 i = 0; i < fWindowSizeField->Menu()->CountItems(); i++) {
529 		BMenuItem* item = fWindowSizeField->Menu()->ItemAt(i);
530 		BMessage* msg = item->Message();
531 		if (msg->FindInt32("rows") == rows && msg->FindInt32("columns") == cols) {
532 			item->SetMarked(true);
533 			break;
534 		}
535 	}
536 }
537 
538 
539 /*static*/ BMenu*
540 AppearancePrefView::_MakeFontMenu(uint32 command,
541 	const char* defaultFamily, const char* defaultStyle)
542 {
543 	BPopUpMenu* menu = new BPopUpMenu("");
544 	int32 numFamilies = count_font_families();
545 	for (int32 i = 0; i < numFamilies; i++) {
546 		font_family family;
547 		uint32 flags;
548 		if (get_font_family(i, &family, &flags) == B_OK) {
549 			BFont font;
550 			font_style style;
551 			int32 numStyles = count_font_styles(family);
552 			for (int32 j = 0; j < numStyles; j++) {
553 				if (get_font_style(family, j, &style) == B_OK) {
554 					font.SetFamilyAndStyle(family, style);
555 					if (IsFontUsable(font)) {
556 						BMessage* message = new BMessage(command);
557 						const char* size
558 							= PrefHandler::Default()->getString(PREF_HALF_FONT_SIZE);
559 						message->AddString("font_family", family);
560 						message->AddString("font_style", style);
561 						message->AddString("font_size", size);
562 						char fontMenuLabel[134];
563 						snprintf(fontMenuLabel, sizeof(fontMenuLabel),
564 							"%s - %s", family, style);
565 						BMenu* fontSizeMenu = _MakeFontSizeMenu(fontMenuLabel,
566 							MSG_HALF_FONT_CHANGED, family, style, size);
567 						BMenuItem* item = new BMenuItem(fontSizeMenu, message);
568 						menu->AddItem(item);
569 						if (strcmp(defaultFamily, family) == 0
570 							&& strcmp(defaultStyle, style) == 0)
571 							item->SetMarked(true);
572 					}
573 				}
574 			}
575 		}
576 	}
577 
578 	if (menu->FindMarked() == NULL)
579 		menu->ItemAt(0)->SetMarked(true);
580 
581 	return menu;
582 }
583 
584 
585 /*static*/ BMenu*
586 AppearancePrefView::_MakeFontSizeMenu(const char* label, uint32 command,
587 	const char* family, const char* style, const char* size)
588 {
589 	BMenu* menu = new BMenu(label);
590 	menu->SetRadioMode(true);
591 	menu->SetLabelFromMarked(false);
592 
593 	int32 sizes[] = {
594 		8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 28, 32, 36, 0
595 	};
596 
597 	bool found = false;
598 
599 	for (uint32 i = 0; sizes[i]; i++) {
600 		BString fontSize;
601 		fontSize << sizes[i];
602 		BMessage* message = new BMessage(command);
603 		message->AddString("font_family", family);
604 		message->AddString("font_style", style);
605 		message->AddString("font_size", fontSize.String());
606 		BMenuItem* item = new BMenuItem(fontSize.String(), message);
607 		menu->AddItem(item);
608 		if (sizes[i] == atoi(size)) {
609 			item->SetMarked(true);
610 			found = true;
611 		}
612 	}
613 
614 	if (!found) {
615 		for (uint32 i = 0; sizes[i]; i++) {
616 			if (sizes[i] > atoi(size)) {
617 				BMessage* message = new BMessage(command);
618 				message->AddString("font_family", family);
619 				message->AddString("font_style", style);
620 				message->AddString("font_size", size);
621 				BMenuItem* item = new BMenuItem(size, message);
622 				item->SetMarked(true);
623 				menu->AddItem(item, i);
624 				break;
625 			}
626 		}
627 	}
628 
629 	return menu;
630 }
631 
632 
633 /*static*/ BPopUpMenu*
634 AppearancePrefView::_MakeMenu(uint32 msg, const char** items,
635 	const char* defaultItemName)
636 {
637 	BPopUpMenu* menu = new BPopUpMenu("");
638 
639 	while (*items) {
640 		if (strcmp((*items), "") == 0)
641 			menu->AddSeparatorItem();
642 		else {
643 			BMessage* message = new BMessage(msg);
644 			message->AddString("label", *items);
645 			BMenuItem* item = new BMenuItem(B_TRANSLATE(*items), message);
646 			menu->AddItem(item);
647 			if (strcmp(*items, defaultItemName) == 0)
648 				item->SetMarked(true);
649 		}
650 
651 		items++;
652 	}
653 
654 	return menu;
655 }
656 
657 
658 /*static*/ BPopUpMenu*
659 AppearancePrefView::_MakeColorSchemeMenu(uint32 msg, const color_scheme** items,
660 	const color_scheme* defaultItemName)
661 {
662 	BPopUpMenu* menu = new BPopUpMenu("");
663 
664 	int32 i = 0;
665 	while (*items) {
666 		if (strcmp((*items)->name, "") == 0)
667 			menu->AddSeparatorItem();
668 		else {
669 			BMessage* message = new BMessage(msg);
670 			message->AddPointer("color_scheme", (const void*)*items);
671 			menu->AddItem(new BMenuItem((*items)->name, message));
672 		}
673 
674 		items++;
675 		i++;
676 	}
677 	return menu;
678 }
679 
680 
681 void
682 AppearancePrefView::_MarkSelectedFont(const char* family, const char* style,
683 	const char* size)
684 {
685 	char fontMenuLabel[134];
686 	snprintf(fontMenuLabel, sizeof(fontMenuLabel), "%s - %s", family, style);
687 
688 	// mark the selected font
689 	BMenuItem* selectedFont = fFontField->Menu()->FindItem(fontMenuLabel);
690 	if (selectedFont != NULL)
691 		selectedFont->SetMarked(true);
692 
693 	// mark the selected font size on all font menus
694 	for (int32 i = 0; i < fFontField->Menu()->CountItems(); i++) {
695 		BMenu* fontSizeMenu = fFontField->Menu()->SubmenuAt(i);
696 		if (fontSizeMenu == NULL)
697 			continue;
698 
699 		BMenuItem* item = fontSizeMenu->FindItem(size);
700 		if (item != NULL)
701 			item->SetMarked(true);
702 	}
703 }
704