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