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