xref: /haiku/src/apps/stylededit/StyledEditWindow.cpp (revision b06a48ab8f30b45916a9c157b992827779182163)
1 /*
2  * Copyright 2002-2006, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Mattias Sundblad
7  *		Andrew Bachmann
8  */
9 
10 
11 #include "Constants.h"
12 #include "ColorMenuItem.h"
13 #include "FindWindow.h"
14 #include "ReplaceWindow.h"
15 #include "StyledEditApp.h"
16 #include "StyledEditView.h"
17 #include "StyledEditWindow.h"
18 
19 #include <Alert.h>
20 #include <Autolock.h>
21 #include <CharacterSet.h>
22 #include <CharacterSetRoster.h>
23 #include <Clipboard.h>
24 #include <Debug.h>
25 #include <File.h>
26 #include <FilePanel.h>
27 #include <Menu.h>
28 #include <MenuBar.h>
29 #include <MenuItem.h>
30 #include <PrintJob.h>
31 #include <Rect.h>
32 #include <Roster.h>
33 #include <ScrollView.h>
34 #include <TextControl.h>
35 #include <TextView.h>
36 #include <TranslationUtils.h>
37 
38 #include <stdlib.h>
39 
40 
41 using namespace BPrivate;
42 
43 
44 StyledEditWindow::StyledEditWindow(BRect frame, int32 id, uint32 encoding)
45 	: BWindow(frame, "untitled", B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS)
46 {
47 	InitWindow(encoding);
48 	BString unTitled("Untitled ");
49 	unTitled << id;
50 	SetTitle(unTitled.String());
51 	fSaveItem->SetEnabled(true);
52 		// allow saving empty files
53 	Show();
54 }
55 
56 
57 StyledEditWindow::StyledEditWindow(BRect frame, entry_ref *ref, uint32 encoding)
58 	: BWindow(frame, "untitled", B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS)
59 {
60 	InitWindow(encoding);
61 	OpenFile(ref);
62 	Show();
63 }
64 
65 
66 StyledEditWindow::~StyledEditWindow()
67 {
68 	delete fSaveMessage;
69 	delete fPrintSettings;
70 	delete fSavePanel;
71 }
72 
73 
74 void
75 StyledEditWindow::InitWindow(uint32 encoding)
76 {
77 	fPrintSettings = NULL;
78 	fSaveMessage = NULL;
79 
80 	// undo modes
81 	fUndoFlag = false;
82 	fCanUndo = false;
83 	fRedoFlag = false;
84 	fCanRedo = false;
85 
86 	// clean modes
87 	fUndoCleans = false;
88 	fRedoCleans = false;
89 	fClean = true;
90 
91 	// search- state
92 	fReplaceString = "";
93 	fStringToFind = "";
94 	fCaseSens = false;
95 	fWrapAround = false;
96 	fBackSearch = false;
97 
98 	// add menubar
99 	fMenuBar = new BMenuBar(BRect(0, 0, 0, 0), "menubar");
100 	AddChild(fMenuBar);
101 
102 	// add textview and scrollview
103 
104 	BRect viewFrame = Bounds();
105 	viewFrame.top = fMenuBar->Bounds().Height() + 1;
106 	viewFrame.right -=  B_V_SCROLL_BAR_WIDTH;
107 	viewFrame.left = 0;
108 	viewFrame.bottom -= B_H_SCROLL_BAR_HEIGHT;
109 
110 	BRect textBounds = viewFrame;
111 	textBounds.OffsetTo(B_ORIGIN);
112 	textBounds.InsetBy(TEXT_INSET, TEXT_INSET);
113 
114 	fTextView= new StyledEditView(viewFrame, textBounds, this);
115 	fTextView->SetDoesUndo(true);
116 	fTextView->SetStylable(true);
117 	fTextView->SetEncoding(encoding);
118 
119 	fScrollView = new BScrollView("scrollview", fTextView, B_FOLLOW_ALL, 0,
120 		true, true, B_PLAIN_BORDER);
121 	AddChild(fScrollView);
122 	fTextView->MakeFocus(true);
123 
124 	// Add "File"-menu:
125 
126 	BMenu* menu = new BMenu("File");
127 	fMenuBar->AddItem(menu);
128 
129 	BMenuItem* menuItem;
130 	menu->AddItem(menuItem = new BMenuItem("New", new BMessage(MENU_NEW), 'N'));
131 	menuItem->SetTarget(be_app);
132 
133 	menu->AddItem(menuItem = new BMenuItem(fRecentMenu = new BMenu("Open" B_UTF8_ELLIPSIS),
134 		new BMessage(MENU_OPEN)));
135 	menuItem->SetShortcut('O', 0);
136 	menuItem->SetTarget(be_app);
137 	menu->AddSeparatorItem();
138 
139 	menu->AddItem(fSaveItem = new BMenuItem("Save", new BMessage(MENU_SAVE), 'S'));
140 	fSaveItem->SetEnabled(false);
141 	menu->AddItem(menuItem = new BMenuItem("Save As" B_UTF8_ELLIPSIS, new BMessage(MENU_SAVEAS)));
142 	menuItem->SetShortcut('S',B_SHIFT_KEY);
143 	menuItem->SetEnabled(true);
144 
145 	menu->AddItem(fRevertItem = new BMenuItem("Revert to Saved" B_UTF8_ELLIPSIS,
146 		new BMessage(MENU_REVERT)));
147 	fRevertItem->SetEnabled(false);
148 	menu->AddItem(menuItem = new BMenuItem("Close", new BMessage(MENU_CLOSE), 'W'));
149 
150 	menu->AddSeparatorItem();
151 	menu->AddItem(menuItem = new BMenuItem("Page Setup" B_UTF8_ELLIPSIS, new BMessage(MENU_PAGESETUP)));
152 	menu->AddItem(menuItem = new BMenuItem("Print" B_UTF8_ELLIPSIS, new BMessage(MENU_PRINT), 'P'));
153 
154 	menu->AddSeparatorItem();
155 	menu->AddItem(menuItem = new BMenuItem("Quit", new BMessage(MENU_QUIT), 'Q'));
156 
157 	// Add the "Edit"-menu:
158 	menu = new BMenu("Edit");
159 	fMenuBar->AddItem(menu);
160 
161 	menu->AddItem(fUndoItem = new BMenuItem("Can't Undo", new BMessage(B_UNDO), 'Z'));
162 	fUndoItem->SetEnabled(false);
163 
164 	menu->AddSeparatorItem();
165 	menu->AddItem(fCutItem = new BMenuItem("Cut", new BMessage(B_CUT), 'X'));
166 	fCutItem->SetEnabled(false);
167 	fCutItem->SetTarget(fTextView);
168 
169 	menu->AddItem(fCopyItem = new BMenuItem("Copy", new BMessage(B_COPY), 'C'));
170 	fCopyItem->SetEnabled(false);
171 	fCopyItem->SetTarget(fTextView);
172 
173 	menu->AddItem(menuItem = new BMenuItem("Paste", new BMessage(B_PASTE), 'V'));
174 	menuItem->SetTarget(fTextView);
175 	menu->AddItem(fClearItem = new BMenuItem("Clear", new BMessage(MENU_CLEAR)));
176 	fClearItem->SetEnabled(false);
177 	fClearItem->SetTarget(fTextView);
178 
179 	menu->AddSeparatorItem();
180 	menu->AddItem(menuItem = new BMenuItem("Select All", new BMessage(B_SELECT_ALL), 'A'));
181 	menuItem->SetTarget(fTextView);
182 
183 	menu->AddSeparatorItem();
184 	menu->AddItem(menuItem = new BMenuItem("Find" B_UTF8_ELLIPSIS, new BMessage(MENU_FIND),'F'));
185 	menu->AddItem(fFindAgainItem= new BMenuItem("Find Again",new BMessage(MENU_FIND_AGAIN),'G'));
186 	fFindAgainItem->SetEnabled(false);
187 
188 	menu->AddItem(menuItem = new BMenuItem("Find Selection", new BMessage(MENU_FIND_SELECTION),'H'));
189 	menu->AddItem(menuItem = new BMenuItem("Replace" B_UTF8_ELLIPSIS, new BMessage(MENU_REPLACE),'R'));
190 	menu->AddItem(fReplaceSameItem = new BMenuItem("Replace Same", new BMessage(MENU_REPLACE_SAME),'T'));
191 	fReplaceSameItem->SetEnabled(false);
192 
193 	// Add the "Font"-menu:
194 	fFontMenu = new BMenu("Font");
195 	fMenuBar->AddItem(fFontMenu);
196 
197 	//"Size"-subMenu
198 	fFontSizeMenu = new BMenu("Size");
199 	fFontSizeMenu->SetRadioMode(true);
200 	fFontMenu->AddItem(fFontSizeMenu);
201 
202 	const int32 fontSizes[] = {9, 10, 11, 12, 14, 18, 24, 36, 48, 72};
203 	for (uint32 i = 0; i < sizeof(fontSizes) / sizeof(fontSizes[0]); i++) {
204 		BMessage* fontMessage = new BMessage(FONT_SIZE);
205 		fontMessage->AddFloat("size", fontSizes[i]);
206 
207 		char label[64];
208 		snprintf(label, sizeof(label), "%ld", fontSizes[i]);
209 		fFontSizeMenu->AddItem(menuItem = new BMenuItem(label, fontMessage));
210 
211 		if (fontSizes[i] == (int32)be_plain_font->Size())
212 			menuItem->SetMarked(true);
213 	}
214 
215 	// "Color"-subMenu
216 	fFontColorMenu = new BMenu("Color");
217 	fFontColorMenu->SetRadioMode(true);
218 	fFontMenu->AddItem(fFontColorMenu);
219 
220 	fFontColorMenu->AddItem(fBlackItem = new BMenuItem("Black", new BMessage(FONT_COLOR)));
221 	fBlackItem->SetMarked(true);
222 	fFontColorMenu->AddItem(fRedItem = new ColorMenuItem("Red", RED, new BMessage(FONT_COLOR)));
223 	fFontColorMenu->AddItem(fGreenItem = new ColorMenuItem("Green", GREEN, new BMessage(FONT_COLOR)));
224 	fFontColorMenu->AddItem(fBlueItem = new ColorMenuItem("Blue", BLUE, new BMessage(FONT_COLOR)));
225 	fFontColorMenu->AddItem(fCyanItem = new ColorMenuItem("Cyan", CYAN, new BMessage(FONT_COLOR)));
226 	fFontColorMenu->AddItem(fMagentaItem = new ColorMenuItem("Magenta", MAGENTA, new BMessage(FONT_COLOR)));
227 	fFontColorMenu->AddItem(fYellowItem = new ColorMenuItem("Yellow", YELLOW, new BMessage(FONT_COLOR)));
228 	fFontMenu->AddSeparatorItem();
229 
230 	// Available fonts, mark "be_plain_font" item
231 
232 	font_family plainFamily;
233 	font_style plainStyle;
234 	be_plain_font->GetFamilyAndStyle(&plainFamily, &plainStyle);
235 	fCurrentFontItem = 0;
236 
237 	BMenu* subMenu;
238 	int32 numFamilies = count_font_families();
239 	for (int32 i = 0; i < numFamilies; i++) {
240 		font_family family;
241 		if (get_font_family(i, &family) == B_OK) {
242 			subMenu = new BMenu(family);
243 			subMenu->SetRadioMode(true);
244 			fFontMenu->AddItem(menuItem = new BMenuItem(subMenu, new BMessage(FONT_FAMILY)));
245 
246 			if (!strcmp(plainFamily, family)) {
247 				menuItem->SetMarked(true);
248 				fCurrentFontItem = menuItem;
249 			}
250 
251 			int32 numStyles = count_font_styles(family);
252 			for (int32 j = 0; j < numStyles; j++) {
253 				font_style style;
254 				uint32 flags;
255 				if (get_font_style(family, j, &style, &flags) == B_OK) {
256 					subMenu->AddItem(menuItem = new BMenuItem(style,
257 						new BMessage(FONT_STYLE)));
258 
259 					if (!strcmp(plainStyle, style))
260 						menuItem->SetMarked(true);
261 				}
262 			}
263 		}
264 	}
265 
266 	// Add the "Document"-menu:
267 	menu = new BMenu("Document");
268 	fMenuBar->AddItem(menu);
269 
270 	// "Align"-subMenu:
271 	subMenu = new BMenu("Align");
272 	subMenu->SetRadioMode(true);
273 
274 	subMenu->AddItem(fAlignLeft = new BMenuItem("Left", new BMessage(ALIGN_LEFT)));
275 	menuItem->SetMarked(true);
276 
277 	subMenu->AddItem(fAlignCenter = new BMenuItem("Center", new BMessage(ALIGN_CENTER)));
278 	subMenu->AddItem(fAlignRight = new BMenuItem("Right", new BMessage(ALIGN_RIGHT)));
279 	menu->AddItem(subMenu);
280 	menu->AddItem(fWrapItem = new BMenuItem("Wrap Lines", new BMessage(WRAP_LINES)));
281 	fWrapItem->SetMarked(true);
282 
283 	fSavePanel = NULL;
284 	fSavePanelEncodingMenu = NULL;
285 		// build lazily
286 }
287 
288 
289 void
290 StyledEditWindow::MessageReceived(BMessage *message)
291 {
292 	if (message->WasDropped()) {
293 		entry_ref ref;
294 		if (message->FindRef("refs", 0, &ref)==B_OK) {
295 			message->what = B_REFS_RECEIVED;
296 			be_app->PostMessage(message);
297 		}
298 	}
299 
300 	switch (message->what) {
301 		// File menu
302 		case MENU_SAVE:
303 			if (!fSaveMessage)
304 				SaveAs();
305 			else
306 				Save(fSaveMessage);
307 			break;
308 
309 		case MENU_SAVEAS:
310 			SaveAs();
311 			break;
312 
313 		case B_SAVE_REQUESTED:
314 			Save(message);
315 			break;
316 
317 		case SAVE_THEN_QUIT:
318 			if (Save(message) == B_OK)
319 				Quit();
320 			break;
321 
322 		case MENU_REVERT:
323 			RevertToSaved();
324 			break;
325 
326 		case MENU_CLOSE:
327 			if (QuitRequested())
328 				Quit();
329 			break;
330 
331 		case MENU_PAGESETUP:
332 			PageSetup(fTextView->Window()->Title());
333 			break;
334 		case MENU_PRINT:
335 			Print(fTextView->Window()->Title());
336 			break;
337 		case MENU_QUIT:
338 			be_app->PostMessage(B_QUIT_REQUESTED);
339 			break;
340 
341 		// Edit menu
342 
343 		case B_UNDO:
344 			ASSERT(fCanUndo || fCanRedo);
345 			ASSERT(!(fCanUndo && fCanRedo));
346 			if (fCanUndo)
347 				fUndoFlag = true;
348 			if (fCanRedo)
349 				fRedoFlag = true;
350 
351 			fTextView->Undo(be_clipboard);
352 			break;
353 		case B_CUT:
354 			fTextView->Cut(be_clipboard);
355 			break;
356 		case B_COPY:
357 			fTextView->Copy(be_clipboard);
358 			break;
359 		case B_PASTE:
360 			fTextView->Paste(be_clipboard);
361 			break;
362 		case MENU_CLEAR:
363 			fTextView->Clear();
364 			break;
365 		case MENU_FIND:
366 		{
367 			BRect findWindowFrame(100, 100, 400, 235);
368 			BWindow* window = new FindWindow(findWindowFrame, this,
369 				&fStringToFind, fCaseSens, fWrapAround, fBackSearch);
370 			window->Show();
371 			break;
372 		}
373 		case MSG_SEARCH:
374 			message->FindString("findtext", &fStringToFind);
375 			fFindAgainItem->SetEnabled(true);
376 			message->FindBool("casesens", &fCaseSens);
377 			message->FindBool("wrap", &fWrapAround);
378 			message->FindBool("backsearch", &fBackSearch);
379 
380 			Search(fStringToFind, fCaseSens, fWrapAround, fBackSearch);
381 			break;
382 		case MENU_FIND_AGAIN:
383 			Search(fStringToFind, fCaseSens, fWrapAround, fBackSearch);
384 			break;
385 		case MENU_FIND_SELECTION:
386 			FindSelection();
387 			break;
388 		case MENU_REPLACE:
389 		{
390 			BRect replaceWindowFrame(100, 100, 400, 284);
391 			BWindow* window = new ReplaceWindow(replaceWindowFrame, this,
392 				&fStringToFind, &fReplaceString, fCaseSens, fWrapAround, fBackSearch);
393 			window->Show();
394 			break;
395 		}
396 		case MSG_REPLACE:
397 		{
398 			message->FindBool("casesens", &fCaseSens);
399 			message->FindBool("wrap", &fWrapAround);
400 			message->FindBool("backsearch", &fBackSearch);
401 
402 			message->FindString("FindText", &fStringToFind);
403 			message->FindString("ReplaceText", &fReplaceString);
404 
405 			fFindAgainItem->SetEnabled(true);
406 			fReplaceSameItem->SetEnabled(true);
407 
408 			Replace(fStringToFind, fReplaceString, fCaseSens, fWrapAround, fBackSearch);
409 			break;
410 		}
411 		case MENU_REPLACE_SAME:
412 			Replace(fStringToFind, fReplaceString, fCaseSens, fWrapAround, fBackSearch);
413 			break;
414 
415 		case MSG_REPLACE_ALL:
416 		{
417 			message->FindBool("casesens", &fCaseSens);
418 			message->FindString("FindText",&fStringToFind);
419 			message->FindString("ReplaceText",&fReplaceString);
420 
421 			bool allWindows;
422 			message->FindBool("allwindows", &allWindows);
423 
424 			fFindAgainItem->SetEnabled(true);
425 			fReplaceSameItem->SetEnabled(true);
426 
427 			if (allWindows)
428 				SearchAllWindows(fStringToFind, fReplaceString, fCaseSens);
429 			else
430 				ReplaceAll(fStringToFind, fReplaceString, fCaseSens);
431 			break;
432 		}
433 
434 		// Font menu
435 
436 		case FONT_SIZE:
437 		{
438 			float fontSize;
439 			if (message->FindFloat("size", &fontSize) == B_OK)
440 				SetFontSize(fontSize);
441 			break;
442 		}
443 		case FONT_FAMILY:
444 		{
445 			const char* fontFamily = NULL;
446 			const char* fontStyle = NULL;
447 			void* ptr;
448 			if (message->FindPointer("source", &ptr) == B_OK) {
449 				fCurrentFontItem = static_cast<BMenuItem*>(ptr);
450 				fontFamily = fCurrentFontItem->Label();
451 			}
452 			SetFontStyle(fontFamily, fontStyle);
453 			break;
454 		}
455 		case FONT_STYLE:
456 		{
457 			const char* fontFamily = NULL;
458 			const char* fontStyle = NULL;
459 			void* ptr;
460 			if (message->FindPointer("source", &ptr) == B_OK) {
461 				BMenuItem* item = static_cast<BMenuItem*>(ptr);
462 				fontStyle = item->Label();
463 				BMenu* menu = item->Menu();
464 				if (menu != NULL) {
465 					fCurrentFontItem = menu->Superitem();
466 					if (fCurrentFontItem != NULL)
467 						fontFamily = fCurrentFontItem->Label();
468 				}
469 			}
470 			SetFontStyle(fontFamily, fontStyle);
471 			break;
472 		}
473 		case FONT_COLOR:
474 		{
475 			void* ptr;
476 			if (message->FindPointer("source", &ptr) == B_OK) {
477 				if (ptr == fBlackItem)
478 					SetFontColor(&BLACK);
479 				else if (ptr == fRedItem)
480 					SetFontColor(&RED);
481 				else if (ptr == fGreenItem)
482 					SetFontColor(&GREEN);
483 				else if (ptr == fBlueItem)
484 					SetFontColor(&BLUE);
485 				else if (ptr == fCyanItem)
486 					SetFontColor(&CYAN);
487 				else if (ptr == fMagentaItem)
488 					SetFontColor(&MAGENTA);
489 				else if (ptr == fYellowItem)
490 					SetFontColor(&YELLOW);
491 			}
492 			break;
493 		}
494 
495 		// Document menu
496 
497 		case ALIGN_LEFT:
498 			fTextView->SetAlignment(B_ALIGN_LEFT);
499 			_UpdateCleanUndoRedoSaveRevert();
500 			break;
501 		case ALIGN_CENTER:
502 			fTextView->SetAlignment(B_ALIGN_CENTER);
503 			_UpdateCleanUndoRedoSaveRevert();
504 			break;
505 		case ALIGN_RIGHT:
506 			fTextView->SetAlignment(B_ALIGN_RIGHT);
507 			_UpdateCleanUndoRedoSaveRevert();
508 			break;
509 		case WRAP_LINES:
510 		{
511 			BRect textRect(fTextView->Bounds());
512 			textRect.OffsetTo(B_ORIGIN);
513 			textRect.InsetBy(TEXT_INSET,TEXT_INSET);
514 			if (fTextView->DoesWordWrap()) {
515 				fTextView->SetWordWrap(false);
516 				fWrapItem->SetMarked(false);
517 				// the width comes from stylededit R5. TODO: find a better way
518 				textRect.SetRightBottom(BPoint(1500.0, textRect.RightBottom().y));
519 			} else {
520 				fTextView->SetWordWrap(true);
521 				fWrapItem->SetMarked(true);
522 			}
523 			fTextView->SetTextRect(textRect);
524 
525 			_UpdateCleanUndoRedoSaveRevert();
526 			break;
527 		}
528 		case ENABLE_ITEMS:
529 			fCutItem->SetEnabled(true);
530 			fCopyItem->SetEnabled(true);
531 			fClearItem->SetEnabled(true);
532 			break;
533 		case DISABLE_ITEMS:
534 			fCutItem->SetEnabled(false);
535 			fCopyItem->SetEnabled(false);
536 			fClearItem->SetEnabled(false);
537 			break;
538 		case TEXT_CHANGED:
539 			if (fUndoFlag) {
540 				if (fUndoCleans) {
541 					// we cleaned!
542 					fClean = true;
543 					fUndoCleans = false;
544 				} else if (fClean) {
545 				   // if we were clean
546 				   // then a redo will make us clean again
547 				   fRedoCleans = true;
548 				   fClean = false;
549 				}
550 				// set mode
551 				fCanUndo = false;
552 				fCanRedo = true;
553 				fUndoItem->SetLabel("Redo Typing");
554 				fUndoItem->SetEnabled(true);
555 				fUndoFlag = false;
556 			} else {
557 				if (fRedoFlag && fRedoCleans) {
558 					// we cleaned!
559 					fClean = true;
560 					fRedoCleans = false;
561 				} else if (fClean) {
562 					// if we were clean
563 					// then an undo will make us clean again
564 					fUndoCleans = true;
565 					fClean = false;
566 				} else {
567 					// no more cleaning from undo now...
568 					fUndoCleans = false;
569 				}
570 				// set mode
571 				fCanUndo = true;
572 				fCanRedo = false;
573 				fUndoItem->SetLabel("Undo Typing");
574 				fUndoItem->SetEnabled(true);
575 				fRedoFlag = false;
576 			}
577 			if (fClean) {
578 				fRevertItem->SetEnabled(false);
579 				fSaveItem->SetEnabled(fSaveMessage == NULL);
580 			} else {
581 				fRevertItem->SetEnabled(fSaveMessage != NULL);
582 				fSaveItem->SetEnabled(true);
583 			}
584 			break;
585 
586 		case SAVE_AS_ENCODING:
587 			void* ptr;
588 			if (message->FindPointer("source", &ptr) == B_OK
589 				&& fSavePanelEncodingMenu != NULL) {
590 				fTextView->SetEncoding((uint32)fSavePanelEncodingMenu->IndexOf((BMenuItem*)ptr));
591 			}
592 			break;
593 
594 		default:
595 			BWindow::MessageReceived(message);
596 			break;
597 	}
598 }
599 
600 
601 void
602 StyledEditWindow::MenusBeginning()
603 {
604 	// set up the recent documents menu
605 	BMessage documents;
606 	be_roster->GetRecentDocuments(&documents, 9, NULL, APP_SIGNATURE);
607 
608 	// delete old items..
609 	//    shatty: it would be preferable to keep the old
610 	//            menu around instead of continuously thrashing
611 	//            the menu, but unfortunately there does not
612 	//            seem to be a straightforward way to update it
613 	// going backwards may simplify memory management
614 	for (int i = fRecentMenu->CountItems(); i-- > 0;) {
615 		delete fRecentMenu->RemoveItem(i);
616 	}
617 
618 	// add new items
619 	int count = 0;
620 	entry_ref ref;
621 	while (documents.FindRef("refs", count++, &ref) == B_OK) {
622 		if (ref.device != -1 && ref.directory != -1) {
623 			// sanity check passed
624 			BMessage* openRecent = new BMessage(B_REFS_RECEIVED);
625 			openRecent->AddRef("refs", &ref);
626 			BMenuItem* item = new BMenuItem(ref.name, openRecent);
627 			item->SetTarget(be_app);
628 			fRecentMenu->AddItem(item);
629 		}
630 	}
631 
632 	// update the font menu
633 	// unselect the old values
634 	if (fCurrentFontItem != NULL)
635 		fCurrentFontItem->SetMarked(false);
636 
637 	BMenuItem* oldColorItem = fFontColorMenu->FindMarked();
638 	if (oldColorItem != NULL)
639 		oldColorItem->SetMarked(false);
640 
641 	BMenuItem* oldSizeItem = fFontSizeMenu->FindMarked();
642 	if (oldSizeItem != NULL)
643 		oldSizeItem->SetMarked(false);
644 
645 	// find the current font, color, size
646 	BFont font;
647 	uint32 sameProperties;
648 	rgb_color color = BLACK;
649 	bool sameColor;
650 	fTextView->GetFontAndColor(&font, &sameProperties, &color, &sameColor);
651 
652 	if (sameColor && color.alpha == 255) {
653 		// select the current color
654 		if (color.red == 0) {
655 			if (color.green == 0) {
656 				if (color.blue == 0) {
657 					fBlackItem->SetMarked(true);
658 				} else if (color.blue == 255) {
659 					fBlueItem->SetMarked(true);
660 				}
661 			} else if (color.green == 255) {
662 				if (color.blue == 0) {
663 					fGreenItem->SetMarked(true);
664 				} else if (color.blue == 255) {
665 					fCyanItem->SetMarked(true);
666 				}
667 			}
668 		} else if (color.red == 255) {
669 			if (color.green == 0) {
670 				if (color.blue == 0) {
671 					fRedItem->SetMarked(true);
672 				} else if (color.blue == 255) {
673 					fMagentaItem->SetMarked(true);
674 				}
675 			} else if (color.green == 255) {
676 				if (color.blue == 0) {
677 					fYellowItem->SetMarked(true);
678 				}
679 			}
680 		}
681 	}
682 
683 	if (sameProperties & B_FONT_SIZE) {
684 		if ((int)font.Size() == font.Size()) {
685 			// select the current font size
686 			char fontSizeStr[16];
687 			snprintf(fontSizeStr, 15, "%i", (int)font.Size());
688 			BMenuItem* item = fFontSizeMenu->FindItem(fontSizeStr);
689 			if (item != NULL)
690 				item->SetMarked(true);
691 		}
692 	}
693 
694 	if (sameProperties & B_FONT_FAMILY_AND_STYLE) {
695 		font_family family;
696 		font_style style;
697 		font.GetFamilyAndStyle(&family, &style);
698 		fCurrentFontItem = fFontMenu->FindItem(family);
699 		if (fCurrentFontItem != NULL) {
700 			fCurrentFontItem->SetMarked(true);
701 			BMenu* menu = fCurrentFontItem->Submenu();
702 			if (menu != NULL) {
703 				BMenuItem* item = menu->FindItem(style);
704 				if (item != NULL)
705 					item->SetMarked(true);
706 			}
707 		}
708 	}
709 
710 	switch (fTextView->Alignment()) {
711 		case B_ALIGN_LEFT:
712 		default:
713 			fAlignLeft->SetMarked(true);
714 			break;
715 		case B_ALIGN_CENTER:
716 			fAlignCenter->SetMarked(true);
717 			break;
718 		case B_ALIGN_RIGHT:
719 			fAlignRight->SetMarked(true);
720 			break;
721 	}
722 }
723 
724 
725 void
726 StyledEditWindow::Quit()
727 {
728 	styled_edit_app->CloseDocument();
729 	BWindow::Quit();
730 }
731 
732 
733 bool
734 StyledEditWindow::QuitRequested()
735 {
736 	int32 buttonIndex = 0;
737 
738 	if (fClean)
739 		return true;
740 
741 	BAlert *saveAlert;
742 	BString alertText;
743 	alertText.SetTo("Save changes to the document \"");
744 	alertText<< Title();
745 	alertText<<"\"? ";
746 	saveAlert = new BAlert("savealert",alertText.String(), "Cancel", "Don't Save","Save",
747 		B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);
748 	saveAlert->SetShortcut(0, B_ESCAPE);
749 	saveAlert->SetShortcut(1, 'd');
750 	saveAlert->SetShortcut(2, 's');
751 	buttonIndex = saveAlert->Go();
752 
753 	if (buttonIndex == 0) {
754 		// "cancel": dont save, dont close the window
755 		return false;
756 	} else if (buttonIndex == 1) {
757 		// "don't save": just close the window
758 		return true;
759 	} else if (!fSaveMessage) {
760 		// save as
761 		BMessage* message = new BMessage(SAVE_THEN_QUIT);
762 		SaveAs(message);
763 		return false;
764 	}
765 
766 	return Save() == B_OK;
767 }
768 
769 
770 status_t
771 StyledEditWindow::Save(BMessage *message)
772 {
773 	status_t err = B_OK;
774 
775 	if (!message){
776 		message = fSaveMessage;
777 		if (!message)
778 			return B_ERROR;
779 	}
780 
781 	entry_ref dirRef;
782 	err = message->FindRef("directory", &dirRef);
783 	if (err!= B_OK)
784 		return err;
785 
786 	const char* name;
787 	err = message->FindString("name", &name);
788 	if (err!= B_OK)
789 		return err;
790 
791 	BDirectory dir(&dirRef);
792 	err = dir.InitCheck();
793 	if (err != B_OK)
794 		return err;
795 
796 	BEntry entry(&dir, name);
797 	err = entry.InitCheck();
798 	if (err != B_OK)
799 		return err;
800 
801 	BFile file(&entry, B_READ_WRITE | B_CREATE_FILE);
802 	err = file.InitCheck();
803 	if (err != B_OK)
804 		return err;
805 
806 	err = fTextView->WriteStyledEditFile(&file);
807 	if (err != B_OK) {
808 		BAlert *saveFailedAlert;
809 		BString alertText;
810 		if (err == B_TRANSLATION_ERROR_BASE)
811 			alertText.SetTo("Translation error saving \"");
812 		else
813 			alertText.SetTo("Unknown error saving \"");
814 
815 		alertText << name;
816 		alertText << "\".";
817 		saveFailedAlert = new BAlert("saveFailedAlert", alertText.String(), "Bummer",
818 			0, 0, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_STOP_ALERT);
819 		saveFailedAlert->SetShortcut(0, B_ESCAPE);
820 		saveFailedAlert->Go();
821 		return err;
822 	}
823 
824 	SetTitle(name);
825 
826 	if (fSaveMessage != message) {
827 		delete fSaveMessage;
828 		fSaveMessage = new BMessage(*message);
829 	}
830 
831 	entry_ref ref;
832 	if (entry.GetRef(&ref) == B_OK)
833 		be_roster->AddToRecentDocuments(&ref, APP_SIGNATURE);
834 
835 	// clear clean modes
836 	fSaveItem->SetEnabled(false);
837 	fRevertItem->SetEnabled(false);
838 	fUndoCleans = false;
839 	fRedoCleans = false;
840 	fClean = true;
841 	return err;
842 }
843 
844 
845 status_t
846 StyledEditWindow::SaveAs(BMessage *message)
847 {
848 	if (fSavePanel == NULL) {
849 		entry_ref* directory = NULL;
850 		if (fSaveMessage != NULL) {
851 			entry_ref dirRef;
852 			if (fSaveMessage->FindRef("directory", &dirRef))
853 				directory = new entry_ref(dirRef);
854 		}
855 
856 		fSavePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(this),
857 			directory, B_FILE_NODE, false);
858 
859 		BMenuBar* menuBar = dynamic_cast<BMenuBar*>(
860 			fSavePanel->Window()->FindView("MenuBar"));
861 
862 		fSavePanelEncodingMenu= new BMenu("Encoding");
863 		menuBar->AddItem(fSavePanelEncodingMenu);
864 		fSavePanelEncodingMenu->SetRadioMode(true);
865 
866 		BCharacterSetRoster roster;
867 		BCharacterSet charset;
868 		while (roster.GetNextCharacterSet(&charset) == B_NO_ERROR) {
869 			BString name(charset.GetPrintName());
870 			const char* mime = charset.GetMIMEName();
871 			if (mime) {
872 				name.Append(" (");
873 				name.Append(mime);
874 				name.Append(")");
875 			}
876 			BMenuItem * item = new BMenuItem(name.String(), new BMessage(SAVE_AS_ENCODING));
877 			item->SetTarget(this);
878 			fSavePanelEncodingMenu->AddItem(item);
879 			if (charset.GetFontID() == fTextView->GetEncoding())
880 				item->SetMarked(true);
881 		}
882 	}
883 
884 	fSavePanel->SetSaveText(Title());
885 	if (message != NULL)
886 		fSavePanel->SetMessage(message);
887 
888 	fSavePanel->Show();
889 	return B_OK;
890 }
891 
892 
893 status_t
894 StyledEditWindow::_LoadFile(entry_ref* ref)
895 {
896 	BEntry entry(ref, true);
897 		// traverse an eventual link
898 
899 	status_t status = entry.InitCheck();
900 	if (status == B_OK && entry.IsDirectory())
901 		status = B_IS_A_DIRECTORY;
902 
903 	BFile file;
904 	if (status == B_OK)
905 		status = file.SetTo(&entry, B_READ_ONLY);
906 	if (status == B_OK)
907 		status = fTextView->GetStyledText(&file);
908 
909 	if (status == B_ENTRY_NOT_FOUND) {
910 		// Treat non-existing files consideratley; we just want to get an
911 		// empty window for them - to create this new document
912 		status = B_OK;
913 	}
914 
915 	if (status != B_OK) {
916 		// If an error occured, bail out and tell the user what happened
917 		BEntry entry(ref, true);
918 		char name[B_FILE_NAME_LENGTH];
919 		if (entry.GetName(name) != B_OK)
920 			strcpy(name, "???");
921 
922 		char text[B_PATH_NAME_LENGTH + 100];
923 		snprintf(text, sizeof(text), "Error loading \"%s\":\n\t%s", name,
924 			strerror(status));
925 
926 		BAlert* alert = new BAlert("StyledEdit Load Failed", text,
927 			"Bummer", 0, 0, B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_STOP_ALERT);
928 		alert->Go();
929 		return status;
930 	}
931 
932 	// update alignment
933 	switch (fTextView->Alignment()) {
934 		case B_ALIGN_LEFT:
935 		default:
936 			fAlignLeft->SetMarked(true);
937 			break;
938 		case B_ALIGN_CENTER:
939 			fAlignCenter->SetMarked(true);
940 			break;
941 		case B_ALIGN_RIGHT:
942 			fAlignRight->SetMarked(true);
943 			break;
944 	}
945 
946 	// update word wrapping
947 	fWrapItem->SetMarked(fTextView->DoesWordWrap());
948 	return B_OK;
949 }
950 
951 
952 void
953 StyledEditWindow::OpenFile(entry_ref* ref)
954 {
955 	if (_LoadFile(ref) != B_OK) {
956 		fSaveItem->SetEnabled(true);
957 			// allow saving new files
958 	}
959 
960 	be_roster->AddToRecentDocuments(ref, APP_SIGNATURE);
961 	fSaveMessage = new BMessage(B_SAVE_REQUESTED);
962 	if (fSaveMessage) {
963 		BEntry entry(ref, true);
964 		BEntry parent;
965 		entry_ref parentRef;
966 		char name[B_FILE_NAME_LENGTH];
967 
968 		entry.GetParent(&parent);
969 		entry.GetName(name);
970 		parent.GetRef(&parentRef);
971 		fSaveMessage->AddRef("directory", &parentRef);
972 		fSaveMessage->AddString("name", name);
973 		SetTitle(name);
974 	}
975 	fTextView->Select(0, 0);
976 }
977 
978 
979 void
980 StyledEditWindow::RevertToSaved()
981 {
982 	entry_ref ref;
983 	const char *name;
984 
985 	fSaveMessage->FindRef("directory", &ref);
986 	fSaveMessage->FindString("name", &name);
987 
988 	BDirectory dir(&ref);
989 	status_t status = dir.InitCheck();
990 	BEntry entry;
991 	if (status == B_OK)
992 		status = entry.SetTo(&dir, name);
993 	if (status == B_OK)
994 		status = entry.GetRef(&ref);
995 	if (status != B_OK || !entry.Exists()) {
996 		BAlert *vanishedAlert;
997 		BString alertText;
998 		alertText.SetTo("Cannot revert, file not found: \"");
999 		alertText << name;
1000 		alertText << "\".";
1001 		vanishedAlert = new BAlert("vanishedAlert", alertText.String(), "Bummer", 0, 0,
1002 			B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_STOP_ALERT);
1003 		vanishedAlert->SetShortcut(0, B_ESCAPE);
1004 		vanishedAlert->Go();
1005 		return;
1006 	}
1007 
1008 	int32 buttonIndex = 0;
1009 	BAlert* revertAlert;
1010 	BString alertText;
1011 	alertText.SetTo("Revert to the last version of \"");
1012 	alertText << Title();
1013 	alertText << "\"? ";
1014 	revertAlert= new BAlert("revertAlert", alertText.String(), "Cancel", "OK", 0,
1015 		B_WIDTH_AS_USUAL, B_EVEN_SPACING, B_WARNING_ALERT);
1016 	revertAlert->SetShortcut(0, B_ESCAPE);
1017 	revertAlert->SetShortcut(1, 'o');
1018 	buttonIndex = revertAlert->Go();
1019 
1020 	if (buttonIndex != 1) {
1021 		// some sort of cancel, don't revert
1022 		return;
1023 	}
1024 
1025 	fTextView->Reset();
1026 
1027 	if (_LoadFile(&ref) != B_OK)
1028 		return;
1029 
1030 	// clear undo modes
1031 	fUndoItem->SetLabel("Can't Undo");
1032 	fUndoItem->SetEnabled(false);
1033 	fUndoFlag = false;
1034 	fCanUndo = false;
1035 	fRedoFlag = false;
1036 	fCanRedo = false;
1037 
1038 	// clear clean modes
1039 	fSaveItem->SetEnabled(false);
1040 	fRevertItem->SetEnabled(false);
1041 	fUndoCleans = false;
1042 	fRedoCleans = false;
1043 	fClean = true;
1044 }
1045 
1046 
1047 status_t
1048 StyledEditWindow::PageSetup(const char* documentName)
1049 {
1050 	BPrintJob printJob(documentName);
1051 
1052 	if (fPrintSettings != NULL)
1053 		printJob.SetSettings(new BMessage(*fPrintSettings));
1054 
1055 	status_t result = printJob.ConfigPage();
1056 	if (result == B_OK) {
1057 		delete fPrintSettings;
1058 		fPrintSettings = printJob.Settings();
1059 	}
1060 
1061 	return result;
1062 }
1063 
1064 
1065 void
1066 StyledEditWindow::Print(const char* documentName)
1067 {
1068 	status_t result;
1069 
1070 	if (fPrintSettings == NULL) {
1071 		result = PageSetup(documentName);
1072 		if (result != B_OK)
1073 			return;
1074 	}
1075 
1076 	BPrintJob printJob(documentName);
1077 	printJob.SetSettings(new BMessage(*fPrintSettings));
1078 	result = printJob.ConfigJob();
1079 	if (result != B_OK)
1080 		return;
1081 
1082 	// information from printJob
1083 	BRect printableRect = printJob.PrintableRect();
1084 	int32 firstPage = printJob.FirstPage();
1085 	int32 lastPage = printJob.LastPage();
1086 
1087 	// lines eventually to be used to compute pages to print
1088 	int32 firstLine = 0;
1089 	int32 lastLine = fTextView->CountLines();
1090 
1091 	// values to be computed
1092 	int32 pagesInDocument = 1;
1093 	int32 linesInDocument = fTextView->CountLines();
1094 
1095 	int32 currentLine = 0;
1096 	while (currentLine < linesInDocument) {
1097 		float currentHeight = 0;
1098 		while (currentHeight < printableRect.Height() && currentLine < linesInDocument) {
1099 			currentHeight += fTextView->LineHeight(currentLine);
1100 			if (currentHeight < printableRect.Height())
1101 				currentLine++;
1102 		}
1103 		if (pagesInDocument == lastPage)
1104 			lastLine = currentLine - 1;
1105 
1106 		if (currentHeight >= printableRect.Height()) {
1107 			pagesInDocument++;
1108 			if (pagesInDocument == firstPage)
1109 				firstLine = currentLine;
1110 		}
1111 	}
1112 
1113 	if (lastPage > pagesInDocument - 1) {
1114 		lastPage = pagesInDocument - 1;
1115 		lastLine = currentLine - 1;
1116 	}
1117 
1118 
1119 	printJob.BeginJob();
1120 	if (fTextView->CountLines() > 0 && fTextView->TextLength() > 0) {
1121 		int32 printLine = firstLine;
1122 		while (printLine <= lastLine) {
1123 			float currentHeight = 0;
1124 			int32 firstLineOnPage = printLine;
1125 			while (currentHeight < printableRect.Height() && printLine <= lastLine) {
1126 				currentHeight += fTextView->LineHeight(printLine);
1127 				if (currentHeight < printableRect.Height())
1128 					printLine++;
1129 			}
1130 
1131 			float top = 0;
1132 			if (firstLineOnPage != 0)
1133 				top = fTextView->TextHeight(0, firstLineOnPage - 1);
1134 
1135 			float bottom = fTextView->TextHeight(0, printLine - 1);
1136 			BRect textRect(0.0, top + TEXT_INSET, printableRect.Width(), bottom + TEXT_INSET);
1137 			printJob.DrawView(fTextView, textRect, B_ORIGIN);
1138 			printJob.SpoolPage();
1139 		}
1140 	}
1141 
1142 
1143 	printJob.CommitJob();
1144 }
1145 
1146 
1147 bool
1148 StyledEditWindow::Search(BString string, bool caseSensitive, bool wrap, bool backsearch)
1149 {
1150 	int32 start;
1151 	int32 finish;
1152 
1153 	start = B_ERROR;
1154 
1155 	int32 length = string.Length();
1156 	if (length == 0)
1157 		return false;
1158 
1159 	BString viewText(fTextView->Text());
1160 	int32 textStart, textFinish;
1161 	fTextView->GetSelection(&textStart, &textFinish);
1162 	if (backsearch) {
1163 		if (caseSensitive) {
1164 			start = viewText.FindLast(string, textStart);
1165 		} else {
1166 			start = viewText.IFindLast(string, textStart);
1167 		}
1168 	} else {
1169 		if (caseSensitive == true) {
1170 			start = viewText.FindFirst(string, textFinish);
1171 		} else {
1172 			start = viewText.IFindFirst(string, textFinish);
1173 		}
1174 	}
1175 	if (start == B_ERROR && wrap) {
1176 		if (backsearch) {
1177 			if (caseSensitive) {
1178 				start = viewText.FindLast(string, viewText.Length());
1179 			} else {
1180 				start = viewText.IFindLast(string, viewText.Length());
1181 			}
1182 		} else {
1183 			if (caseSensitive) {
1184 				start = viewText.FindFirst(string, 0);
1185 			} else {
1186 				start = viewText.IFindFirst(string, 0);
1187 			}
1188 		}
1189 	}
1190 
1191 	if (start != B_ERROR) {
1192 		finish = start + length;
1193 		fTextView->Select(start, finish);
1194 		fTextView->ScrollToSelection();
1195 		return true;
1196 	}
1197 
1198 	return false;
1199 }
1200 
1201 
1202 void
1203 StyledEditWindow::FindSelection()
1204 {
1205 	int32 selectionStart, selectionFinish;
1206 	fTextView->GetSelection(&selectionStart, &selectionFinish);
1207 
1208 	int32 selectionLength = selectionFinish- selectionStart;
1209 
1210 	BString viewText = fTextView->Text();
1211 	viewText.CopyInto(fStringToFind, selectionStart, selectionLength);
1212 	fFindAgainItem->SetEnabled(true);
1213 	Search(fStringToFind, fCaseSens, fWrapAround, fBackSearch);
1214 }
1215 
1216 
1217 bool
1218 StyledEditWindow::Replace(BString findthis, BString replaceWith, bool caseSensitive,
1219 	bool wrap, bool backsearch)
1220 {
1221 	if (Search(findthis, caseSensitive, wrap, backsearch)) {
1222 		int32 start, finish;
1223 		fTextView->GetSelection(&start, &finish);
1224 
1225 		fTextView->Delete(start, start + findthis.Length());
1226 		fTextView->Insert(start, replaceWith.String(), replaceWith.Length());
1227 		fTextView->Select(start, start + replaceWith.Length());
1228 		fTextView->ScrollToSelection();
1229 		return true;
1230 	}
1231 
1232 	return false;
1233 }
1234 
1235 
1236 void
1237 StyledEditWindow::ReplaceAll(BString findIt, BString replaceWith, bool caseSensitive)
1238 {
1239 	BString viewText(fTextView->Text());
1240 	if (caseSensitive)
1241 		viewText.ReplaceAll(findIt.String(), replaceWith.String());
1242 	else
1243 		viewText.IReplaceAll(findIt.String(), replaceWith.String());
1244 
1245 	if (viewText.Compare(fTextView->Text()) == 0) {
1246 		// they are the same
1247 		return;
1248 	}
1249 
1250 	int32 textStart, textFinish;
1251 	fTextView->GetSelection(&textStart, &textFinish);
1252 
1253 	fTextView->SetText(viewText.String());
1254 
1255 	if (viewText.Length() < textStart)
1256 		textStart = viewText.Length();
1257 	if (viewText.Length() < textFinish)
1258 		textFinish = viewText.Length();
1259 
1260 	fTextView->Select(textStart,textFinish);
1261 	fTextView->ScrollToSelection();
1262 
1263 	_UpdateCleanUndoRedoSaveRevert();
1264 }
1265 
1266 
1267 void
1268 StyledEditWindow::SearchAllWindows(BString find, BString replace, bool caseSensitive)
1269 {
1270 	int32 numWindows;
1271 	numWindows = be_app->CountWindows();
1272 
1273 	BMessage *message;
1274 	message= new BMessage(MSG_REPLACE_ALL);
1275 	message->AddString("FindText", find);
1276 	message->AddString("ReplaceText", replace);
1277 	message->AddBool("casesens", caseSensitive);
1278 
1279 	while (numWindows >= 0) {
1280 		StyledEditWindow *window = dynamic_cast<StyledEditWindow *>(
1281 			be_app->WindowAt(numWindows));
1282 
1283 		BMessenger messenger(window);
1284 		messenger.SendMessage(message);
1285 
1286 		numWindows--;
1287 	}
1288 }
1289 
1290 
1291 void
1292 StyledEditWindow::SetFontSize(float fontSize)
1293 {
1294 	uint32 sameProperties;
1295 	BFont font;
1296 
1297 	fTextView->GetFontAndColor(&font, &sameProperties);
1298 	font.SetSize(fontSize);
1299 	fTextView->SetFontAndColor(&font, B_FONT_SIZE);
1300 
1301 	_UpdateCleanUndoRedoSaveRevert();
1302 }
1303 
1304 
1305 void
1306 StyledEditWindow::SetFontColor(const rgb_color *color)
1307 {
1308 	uint32 sameProperties;
1309 	BFont font;
1310 
1311 	fTextView->GetFontAndColor(&font, &sameProperties, NULL, NULL);
1312 	fTextView->SetFontAndColor(&font, 0, color);
1313 
1314 	_UpdateCleanUndoRedoSaveRevert();
1315 }
1316 
1317 
1318 void
1319 StyledEditWindow::SetFontStyle(const char *fontFamily, const char *fontStyle)
1320 {
1321 	BFont font;
1322 	uint32 sameProperties;
1323 
1324 	// find out what the old font was
1325 	font_family oldFamily;
1326 	font_style oldStyle;
1327 	fTextView->GetFontAndColor(&font, &sameProperties);
1328 	font.GetFamilyAndStyle(&oldFamily, &oldStyle);
1329 
1330 	// clear that family's bit on the menu, if necessary
1331 	if (strcmp(oldFamily, fontFamily)) {
1332 		BMenuItem* oldItem = fFontMenu->FindItem(oldFamily);
1333 		if (oldItem != NULL)
1334 			oldItem->SetMarked(false);
1335 	}
1336 
1337 	font.SetFamilyAndStyle(fontFamily, fontStyle);
1338 	fTextView->SetFontAndColor(&font);
1339 
1340 	BMenuItem* superItem;
1341 	superItem = fFontMenu->FindItem(fontFamily);
1342 	if (superItem != NULL)
1343 		superItem->SetMarked(true);
1344 
1345 	_UpdateCleanUndoRedoSaveRevert();
1346 }
1347 
1348 void
1349 StyledEditWindow::_UpdateCleanUndoRedoSaveRevert()
1350 {
1351 	fClean = false;
1352 	fUndoCleans = false;
1353 	fRedoCleans = false;
1354 	fRevertItem->SetEnabled(fSaveMessage != NULL);
1355 	fSaveItem->SetEnabled(true);
1356 	fUndoItem->SetLabel("Can't Undo");
1357 	fUndoItem->SetEnabled(false);
1358 	fCanUndo = false;
1359 	fCanRedo = false;
1360 }
1361 
1362