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