131139022SAxel Dörfler/*
20cc8d8abSSiarzhuk Zharski * Copyright 2002-2012, Haiku, Inc. All Rights Reserved.
331139022SAxel Dörfler * Distributed under the terms of the MIT License.
431139022SAxel Dörfler *
531139022SAxel Dörfler * Authors:
631139022SAxel Dörfler *		Mattias Sundblad
731139022SAxel Dörfler *		Andrew Bachmann
812483e3cSPhilippe Saint-Pierre *		Philippe Saint-Pierre
913e9a630SJonas Sundström *		Jonas Sundstr��m
105d67e2baSRyan Leavengood *		Ryan Leavengood
110cc8d8abSSiarzhuk Zharski *		Vlad Slepukhin
120cc8d8abSSiarzhuk Zharski *		Sarzhuk Zharski
1331139022SAxel Dörfler */
1431139022SAxel Dörfler
15a723b3d4SAxel Dörfler
1631139022SAxel Dörfler#include "ColorMenuItem.h"
170f4985d8SVlad Slepukhin#include "Constants.h"
1831139022SAxel Dörfler#include "FindWindow.h"
1931139022SAxel Dörfler#include "ReplaceWindow.h"
200f4985d8SVlad Slepukhin#include "StatusView.h"
2131139022SAxel Dörfler#include "StyledEditApp.h"
2231139022SAxel Dörfler#include "StyledEditView.h"
2331139022SAxel Dörfler#include "StyledEditWindow.h"
24f7afd44bSPhil Greenway
25f7afd44bSPhil Greenway#include <Alert.h>
26ed48868fSshatty#include <Autolock.h>
27f0da038eSAdrien Destugues#include <Catalog.h>
28f303cd6cSRyan Leavengood#include <CharacterSet.h>
29f303cd6cSRyan Leavengood#include <CharacterSetRoster.h>
30f7afd44bSPhil Greenway#include <Clipboard.h>
31f303cd6cSRyan Leavengood#include <Debug.h>
32f7afd44bSPhil Greenway#include <File.h>
33f303cd6cSRyan Leavengood#include <FilePanel.h>
34a723b3d4SAxel Dörfler#include <fs_attr.h>
35f0da038eSAdrien Destugues#include <Locale.h>
36f7afd44bSPhil Greenway#include <Menu.h>
37f303cd6cSRyan Leavengood#include <MenuBar.h>
38f7afd44bSPhil Greenway#include <MenuItem.h>
390cc8d8abSSiarzhuk Zharski#include <NodeMonitor.h>
4013e9a630SJonas Sundström#include <Path.h>
41f7afd44bSPhil Greenway#include <PrintJob.h>
42e056d320SFreeman Lou#include <RecentItems.h>
43f303cd6cSRyan Leavengood#include <Rect.h>
44b40c9906SRyan Leavengood#include <Roster.h>
459bf722bdSAxel Dörfler#include <Screen.h>
46f7afd44bSPhil Greenway#include <ScrollView.h>
47844ea151Sshatty#include <TextControl.h>
48f303cd6cSRyan Leavengood#include <TextView.h>
49f7afd44bSPhil Greenway#include <TranslationUtils.h>
5015d26d2cSAxel Dörfler#include <UnicodeChar.h>
51f8668ab4SSiarzhuk Zharski#include <UTF8.h>
5242cb481fSSiarzhuk Zharski#include <Volume.h>
53f7afd44bSPhil Greenway
549bf722bdSAxel Dörfler
5546555d8fSshattyusing namespace BPrivate;
5646555d8fSshatty
57ff99f481SAxel Dörfler
588e26769cSRene Gollentconst float kLineViewWidth = 30.0;
59c92efcc0SAxel Dörflerconst char* kInfoAttributeName = "StyledEdit-info";
6031139022SAxel Dörfler
61a723b3d4SAxel Dörfler
62546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
63546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "StyledEditWindow"
64ff99f481SAxel Dörfler
65a723b3d4SAxel Dörfler
669bf722bdSAxel Dörfler// This is a temporary solution for building BString with printf like format.
679bf722bdSAxel Dörfler// will be removed in the future.
689bf722bdSAxel Dörflerstatic void
699bf722bdSAxel Dörflerbs_printf(BString* string, const char* format, ...)
709bf722bdSAxel Dörfler{
719bf722bdSAxel Dörfler	va_list ap;
729bf722bdSAxel Dörfler	va_start(ap, format);
739bf722bdSAxel Dörfler	char* buf;
749bf722bdSAxel Dörfler	vasprintf(&buf, format, ap);
759bf722bdSAxel Dörfler	string->SetTo(buf);
769bf722bdSAxel Dörfler	free(buf);
779bf722bdSAxel Dörfler	va_end(ap);
789bf722bdSAxel Dörfler}
799bf722bdSAxel Dörfler
809bf722bdSAxel Dörfler
819bf722bdSAxel Dörfler// #pragma mark -
829bf722bdSAxel Dörfler
839bf722bdSAxel Dörfler
84670567f9SshattyStyledEditWindow::StyledEditWindow(BRect frame, int32 id, uint32 encoding)
85e62d9cf8SPhilippe Saint-Pierre	:
86e62d9cf8SPhilippe Saint-Pierre	BWindow(frame, "untitled", B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS),
87e62d9cf8SPhilippe Saint-Pierre	fFindWindow(NULL),
88e62d9cf8SPhilippe Saint-Pierre	fReplaceWindow(NULL)
89ed48868fSshatty{
905188c282SAxel Dörfler	_InitWindow(encoding);
91906db303SMatt Madia	BString unTitled(B_TRANSLATE("Untitled "));
92ed48868fSshatty	unTitled << id;
93ed48868fSshatty	SetTitle(unTitled.String());
9431139022SAxel Dörfler	fSaveItem->SetEnabled(true);
9531139022SAxel Dörfler		// allow saving empty files
96ed48868fSshatty	Show();
9731139022SAxel Dörfler}
9831139022SAxel Dörfler
99f7afd44bSPhil Greenway
100f0da038eSAdrien DestuguesStyledEditWindow::StyledEditWindow(BRect frame, entry_ref* ref, uint32 encoding)
101e62d9cf8SPhilippe Saint-Pierre	:
102e62d9cf8SPhilippe Saint-Pierre	BWindow(frame, "untitled", B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS),
103e62d9cf8SPhilippe Saint-Pierre	fFindWindow(NULL),
104e62d9cf8SPhilippe Saint-Pierre	fReplaceWindow(NULL)
105ed48868fSshatty{
1065188c282SAxel Dörfler	_InitWindow(encoding);
107ed48868fSshatty	OpenFile(ref);
108ed48868fSshatty	Show();
10931139022SAxel Dörfler}
11031139022SAxel Dörfler
11131139022SAxel Dörfler
112ed48868fSshattyStyledEditWindow::~StyledEditWindow()
113ed48868fSshatty{
114d727a85bSshatty	delete fSaveMessage;
115d727a85bSshatty	delete fPrintSettings;
116f7afd44bSPhil Greenway	delete fSavePanel;
11731139022SAxel Dörfler}
11831139022SAxel Dörfler
11931139022SAxel Dörfler
1205188c282SAxel Dörflervoid
1215188c282SAxel DörflerStyledEditWindow::Quit()
1225188c282SAxel Dörfler{
1230cc8d8abSSiarzhuk Zharski	_SwitchNodeMonitor(false);
1240cc8d8abSSiarzhuk Zharski
1255188c282SAxel Dörfler	_SaveAttrs();
1265188c282SAxel Dörfler	if (StyledEditApp* app = dynamic_cast<StyledEditApp*>(be_app))
1275188c282SAxel Dörfler		app->CloseDocument();
1285188c282SAxel Dörfler	BWindow::Quit();
1295188c282SAxel Dörfler}
1305188c282SAxel Dörfler
1315188c282SAxel Dörfler
132546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
133546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "QuitAlert"
134f0da038eSAdrien Destugues
135a723b3d4SAxel Dörfler
1365188c282SAxel Dörflerbool
1375188c282SAxel DörflerStyledEditWindow::QuitRequested()
138ed48868fSshatty{
1395188c282SAxel Dörfler	if (fClean)
1405188c282SAxel Dörfler		return true;
14131139022SAxel Dörfler
1420cc8d8abSSiarzhuk Zharski	if (fTextView->TextLength() == 0 && fSaveMessage == NULL)
1430cc8d8abSSiarzhuk Zharski		return true;
1440cc8d8abSSiarzhuk Zharski
1455188c282SAxel Dörfler	BString alertText;
1465188c282SAxel Dörfler	bs_printf(&alertText,
1475188c282SAxel Dörfler		B_TRANSLATE("Save changes to the document \"%s\"? "), Title());
14831139022SAxel Dörfler
1495188c282SAxel Dörfler	int32 index = _ShowAlert(alertText, B_TRANSLATE("Cancel"),
1505188c282SAxel Dörfler		B_TRANSLATE("Don't save"), B_TRANSLATE("Save"),	B_WARNING_ALERT);
15131139022SAxel Dörfler
1525188c282SAxel Dörfler	if (index == 0)
1535188c282SAxel Dörfler		return false;	// "cancel": dont save, dont close the window
15431139022SAxel Dörfler
1555188c282SAxel Dörfler	if (index == 1)
1565188c282SAxel Dörfler		return true;	// "don't save": just close the window
157f7afd44bSPhil Greenway
1585188c282SAxel Dörfler	if (!fSaveMessage) {
1595188c282SAxel Dörfler		SaveAs(new BMessage(SAVE_THEN_QUIT));
1605188c282SAxel Dörfler		return false;
1615188c282SAxel Dörfler	}
16231139022SAxel Dörfler
1635188c282SAxel Dörfler	return Save() == B_OK;
1645188c282SAxel Dörfler}
16514ea5e5eSKarsten Heimrich
16631139022SAxel Dörfler
1675188c282SAxel Dörflervoid
1685188c282SAxel DörflerStyledEditWindow::MessageReceived(BMessage* message)
1695188c282SAxel Dörfler{
1705188c282SAxel Dörfler	if (message->WasDropped()) {
1715188c282SAxel Dörfler		entry_ref ref;
1725188c282SAxel Dörfler		if (message->FindRef("refs", 0, &ref)==B_OK) {
1735188c282SAxel Dörfler			message->what = B_REFS_RECEIVED;
1745188c282SAxel Dörfler			be_app->PostMessage(message);
1755188c282SAxel Dörfler		}
1765188c282SAxel Dörfler	}
17731139022SAxel Dörfler
1785188c282SAxel Dörfler	switch (message->what) {
1795188c282SAxel Dörfler		// File menu
1805188c282SAxel Dörfler		case MENU_SAVE:
1815188c282SAxel Dörfler			if (!fSaveMessage)
1825188c282SAxel Dörfler				SaveAs();
1835188c282SAxel Dörfler			else
1845188c282SAxel Dörfler				Save(fSaveMessage);
1855188c282SAxel Dörfler			break;
186a723b3d4SAxel Dörfler
1875188c282SAxel Dörfler		case MENU_SAVEAS:
1885188c282SAxel Dörfler			SaveAs();
1895188c282SAxel Dörfler			break;
19031139022SAxel Dörfler
1915188c282SAxel Dörfler		case B_SAVE_REQUESTED:
1925188c282SAxel Dörfler			Save(message);
1935188c282SAxel Dörfler			break;
19414ea5e5eSKarsten Heimrich
1955188c282SAxel Dörfler		case SAVE_THEN_QUIT:
1965188c282SAxel Dörfler			if (Save(message) == B_OK)
1975188c282SAxel Dörfler				Quit();
1985188c282SAxel Dörfler			break;
19931139022SAxel Dörfler
2000cc8d8abSSiarzhuk Zharski		case MENU_RELOAD:
2010cc8d8abSSiarzhuk Zharski			_ReloadDocument(message);
2025188c282SAxel Dörfler			break;
20331139022SAxel Dörfler
2045188c282SAxel Dörfler		case MENU_CLOSE:
2055188c282SAxel Dörfler			if (QuitRequested())
2065188c282SAxel Dörfler				Quit();
2075188c282SAxel Dörfler			break;
20831139022SAxel Dörfler
2095188c282SAxel Dörfler		case MENU_PAGESETUP:
2105188c282SAxel Dörfler			PageSetup(fTextView->Window()->Title());
2115188c282SAxel Dörfler			break;
2125188c282SAxel Dörfler		case MENU_PRINT:
2135188c282SAxel Dörfler			Print(fTextView->Window()->Title());
2145188c282SAxel Dörfler			break;
2155188c282SAxel Dörfler		case MENU_QUIT:
2165188c282SAxel Dörfler			be_app->PostMessage(B_QUIT_REQUESTED);
2175188c282SAxel Dörfler			break;
21831139022SAxel Dörfler
2195188c282SAxel Dörfler		// Edit menu
22031139022SAxel Dörfler
2215188c282SAxel Dörfler		case B_UNDO:
2225188c282SAxel Dörfler			ASSERT(fCanUndo || fCanRedo);
2235188c282SAxel Dörfler			ASSERT(!(fCanUndo && fCanRedo));
2245188c282SAxel Dörfler			if (fCanUndo)
2255188c282SAxel Dörfler				fUndoFlag = true;
2265188c282SAxel Dörfler			if (fCanRedo)
2275188c282SAxel Dörfler				fRedoFlag = true;
22831139022SAxel Dörfler
2295188c282SAxel Dörfler			fTextView->Undo(be_clipboard);
2305188c282SAxel Dörfler			break;
2315188c282SAxel Dörfler		case B_CUT:
2325188c282SAxel Dörfler			fTextView->Cut(be_clipboard);
2335188c282SAxel Dörfler			break;
2345188c282SAxel Dörfler		case B_COPY:
2355188c282SAxel Dörfler			fTextView->Copy(be_clipboard);
2365188c282SAxel Dörfler			break;
2375188c282SAxel Dörfler		case B_PASTE:
2385188c282SAxel Dörfler			fTextView->Paste(be_clipboard);
2395188c282SAxel Dörfler			break;
2405188c282SAxel Dörfler		case MENU_CLEAR:
2415188c282SAxel Dörfler			fTextView->Clear();
2425188c282SAxel Dörfler			break;
2435188c282SAxel Dörfler		case MENU_FIND:
2445188c282SAxel Dörfler		{
245579c4d6eSEzo			if (fFindWindow == NULL) {
246579c4d6eSEzo				BRect findWindowFrame(Frame());
247579c4d6eSEzo				findWindowFrame.InsetBy(
248579c4d6eSEzo					(findWindowFrame.Width() - 400) / 2,
249579c4d6eSEzo					(findWindowFrame.Height() - 235) / 2);
250579c4d6eSEzo
251579c4d6eSEzo				fFindWindow = new FindWindow(findWindowFrame, this,
252579c4d6eSEzo					&fStringToFind, fCaseSensitive, fWrapAround, fBackSearch);
253579c4d6eSEzo				fFindWindow->Show();
254579c4d6eSEzo
255579c4d6eSEzo			} else if (fFindWindow->IsHidden())
256579c4d6eSEzo				fFindWindow->Show();
257579c4d6eSEzo			else
258579c4d6eSEzo				fFindWindow->Activate();
2595188c282SAxel Dörfler			break;
2605188c282SAxel Dörfler		}
26185ce1385SRene Gollent		case MSG_FIND_WINDOW_QUIT:
26285ce1385SRene Gollent		{
26385ce1385SRene Gollent			fFindWindow = NULL;
26485ce1385SRene Gollent			break;
26585ce1385SRene Gollent		}
266da9188acSJanus		case MSG_REPLACE_WINDOW_QUIT:
267da9188acSJanus		{
268da9188acSJanus			fReplaceWindow = NULL;
269da9188acSJanus			break;
270da9188acSJanus		}
2715188c282SAxel Dörfler		case MSG_SEARCH:
2725188c282SAxel Dörfler			message->FindString("findtext", &fStringToFind);
2735188c282SAxel Dörfler			fFindAgainItem->SetEnabled(true);
2745188c282SAxel Dörfler			message->FindBool("casesens", &fCaseSensitive);
2755188c282SAxel Dörfler			message->FindBool("wrap", &fWrapAround);
2765188c282SAxel Dörfler			message->FindBool("backsearch", &fBackSearch);
27731139022SAxel Dörfler
2785188c282SAxel Dörfler			_Search(fStringToFind, fCaseSensitive, fWrapAround, fBackSearch);
2795188c282SAxel Dörfler			break;
2805188c282SAxel Dörfler		case MENU_FIND_AGAIN:
2815188c282SAxel Dörfler			_Search(fStringToFind, fCaseSensitive, fWrapAround, fBackSearch);
2825188c282SAxel Dörfler			break;
2835188c282SAxel Dörfler		case MENU_FIND_SELECTION:
2845188c282SAxel Dörfler			_FindSelection();
2855188c282SAxel Dörfler			break;
2865188c282SAxel Dörfler		case MENU_REPLACE:
2875188c282SAxel Dörfler		{
288579c4d6eSEzo			if (fReplaceWindow == NULL) {
289579c4d6eSEzo				BRect replaceWindowFrame(Frame());
290579c4d6eSEzo				replaceWindowFrame.InsetBy(
291579c4d6eSEzo					(replaceWindowFrame.Width() - 400) / 2,
292579c4d6eSEzo					(replaceWindowFrame.Height() - 284) / 2);
293579c4d6eSEzo
294579c4d6eSEzo				fReplaceWindow = new ReplaceWindow(replaceWindowFrame, this,
295579c4d6eSEzo					&fStringToFind, &fReplaceString, fCaseSensitive,
296579c4d6eSEzo					fWrapAround, fBackSearch);
297579c4d6eSEzo				fReplaceWindow->Show();
298579c4d6eSEzo
299579c4d6eSEzo			} else if (fReplaceWindow->IsHidden())
300579c4d6eSEzo				fReplaceWindow->Show();
301579c4d6eSEzo			else
302579c4d6eSEzo				fReplaceWindow->Activate();
3035188c282SAxel Dörfler			break;
3045188c282SAxel Dörfler		}
3055188c282SAxel Dörfler		case MSG_REPLACE:
3065188c282SAxel Dörfler		{
3075188c282SAxel Dörfler			message->FindBool("casesens", &fCaseSensitive);
3085188c282SAxel Dörfler			message->FindBool("wrap", &fWrapAround);
3095188c282SAxel Dörfler			message->FindBool("backsearch", &fBackSearch);
310f7afd44bSPhil Greenway
3115188c282SAxel Dörfler			message->FindString("FindText", &fStringToFind);
3125188c282SAxel Dörfler			message->FindString("ReplaceText", &fReplaceString);
313f7afd44bSPhil Greenway
3145188c282SAxel Dörfler			fFindAgainItem->SetEnabled(true);
3155188c282SAxel Dörfler			fReplaceSameItem->SetEnabled(true);
31631139022SAxel Dörfler
3175188c282SAxel Dörfler			_Replace(fStringToFind, fReplaceString, fCaseSensitive, fWrapAround,
3185188c282SAxel Dörfler				fBackSearch);
3195188c282SAxel Dörfler			break;
3205188c282SAxel Dörfler		}
3215188c282SAxel Dörfler		case MENU_REPLACE_SAME:
3225188c282SAxel Dörfler			_Replace(fStringToFind, fReplaceString, fCaseSensitive, fWrapAround,
3235188c282SAxel Dörfler				fBackSearch);
3245188c282SAxel Dörfler			break;
32531139022SAxel Dörfler
3265188c282SAxel Dörfler		case MSG_REPLACE_ALL:
3275188c282SAxel Dörfler		{
3285188c282SAxel Dörfler			message->FindBool("casesens", &fCaseSensitive);
3298a85cd4cSSiarzhuk Zharski			message->FindString("FindText", &fStringToFind);
3308a85cd4cSSiarzhuk Zharski			message->FindString("ReplaceText", &fReplaceString);
33131139022SAxel Dörfler
3325188c282SAxel Dörfler			bool allWindows;
3335188c282SAxel Dörfler			message->FindBool("allwindows", &allWindows);
33431139022SAxel Dörfler
3355188c282SAxel Dörfler			fFindAgainItem->SetEnabled(true);
3365188c282SAxel Dörfler			fReplaceSameItem->SetEnabled(true);
33731139022SAxel Dörfler
3385188c282SAxel Dörfler			if (allWindows)
3395188c282SAxel Dörfler				SearchAllWindows(fStringToFind, fReplaceString, fCaseSensitive);
3405188c282SAxel Dörfler			else
3415188c282SAxel Dörfler				_ReplaceAll(fStringToFind, fReplaceString, fCaseSensitive);
3425188c282SAxel Dörfler			break;
3435188c282SAxel Dörfler		}
34431139022SAxel Dörfler
3450cc8d8abSSiarzhuk Zharski		case B_NODE_MONITOR:
3460cc8d8abSSiarzhuk Zharski			_HandleNodeMonitorEvent(message);
3470cc8d8abSSiarzhuk Zharski			break;
3480cc8d8abSSiarzhuk Zharski
3495188c282SAxel Dörfler		// Font menu
35014ea5e5eSKarsten Heimrich
3515188c282SAxel Dörfler		case FONT_SIZE:
3525188c282SAxel Dörfler		{
3535188c282SAxel Dörfler			float fontSize;
3545188c282SAxel Dörfler			if (message->FindFloat("size", &fontSize) == B_OK)
3555188c282SAxel Dörfler				_SetFontSize(fontSize);
3565188c282SAxel Dörfler			break;
3575188c282SAxel Dörfler		}
3585188c282SAxel Dörfler		case FONT_FAMILY:
3595188c282SAxel Dörfler		{
3605188c282SAxel Dörfler			const char* fontFamily = NULL;
3615188c282SAxel Dörfler			const char* fontStyle = NULL;
3625188c282SAxel Dörfler			void* ptr;
3635188c282SAxel Dörfler			if (message->FindPointer("source", &ptr) == B_OK) {
3645188c282SAxel Dörfler				BMenuItem* item = static_cast<BMenuItem*>(ptr);
3655188c282SAxel Dörfler				fontFamily = item->Label();
3665188c282SAxel Dörfler			}
367d2ff9616SAxel Dörfler
368d2ff9616SAxel Dörfler			BFont font;
369d2ff9616SAxel Dörfler			font.SetFamilyAndStyle(fontFamily, fontStyle);
370d2ff9616SAxel Dörfler			fItalicItem->SetMarked((font.Face() & B_ITALIC_FACE) != 0);
371d2ff9616SAxel Dörfler			fBoldItem->SetMarked((font.Face() & B_BOLD_FACE) != 0);
372d2ff9616SAxel Dörfler
3735188c282SAxel Dörfler			_SetFontStyle(fontFamily, fontStyle);
3745188c282SAxel Dörfler			break;
3755188c282SAxel Dörfler		}
3765188c282SAxel Dörfler		case FONT_STYLE:
3775188c282SAxel Dörfler		{
3785188c282SAxel Dörfler			const char* fontFamily = NULL;
3795188c282SAxel Dörfler			const char* fontStyle = NULL;
3805188c282SAxel Dörfler			void* ptr;
3815188c282SAxel Dörfler			if (message->FindPointer("source", &ptr) == B_OK) {
3825188c282SAxel Dörfler				BMenuItem* item = static_cast<BMenuItem*>(ptr);
3835188c282SAxel Dörfler				fontStyle = item->Label();
3845188c282SAxel Dörfler				BMenu* menu = item->Menu();
3855188c282SAxel Dörfler				if (menu != NULL) {
3865188c282SAxel Dörfler					BMenuItem* super_item = menu->Superitem();
3875188c282SAxel Dörfler					if (super_item != NULL)
3885188c282SAxel Dörfler						fontFamily = super_item->Label();
3895188c282SAxel Dörfler				}
3905188c282SAxel Dörfler			}
391d2ff9616SAxel Dörfler
392d2ff9616SAxel Dörfler			BFont font;
393d2ff9616SAxel Dörfler			font.SetFamilyAndStyle(fontFamily, fontStyle);
394d2ff9616SAxel Dörfler			fItalicItem->SetMarked((font.Face() & B_ITALIC_FACE) != 0);
395d2ff9616SAxel Dörfler			fBoldItem->SetMarked((font.Face() & B_BOLD_FACE) != 0);
396d2ff9616SAxel Dörfler
3975188c282SAxel Dörfler			_SetFontStyle(fontFamily, fontStyle);
3985188c282SAxel Dörfler			break;
3995188c282SAxel Dörfler		}
400d2ff9616SAxel Dörfler		case kMsgSetItalic:
401d2ff9616SAxel Dörfler		{
402d2ff9616SAxel Dörfler			uint32 sameProperties;
403d2ff9616SAxel Dörfler			BFont font;
404d2ff9616SAxel Dörfler			fTextView->GetFontAndColor(&font, &sameProperties);
405d2ff9616SAxel Dörfler
406d2ff9616SAxel Dörfler			if (fItalicItem->IsMarked())
407d2ff9616SAxel Dörfler				font.SetFace(B_REGULAR_FACE);
408d2ff9616SAxel Dörfler			fItalicItem->SetMarked(!fItalicItem->IsMarked());
409d2ff9616SAxel Dörfler
410d2ff9616SAxel Dörfler			font_family family;
411d2ff9616SAxel Dörfler			font_style style;
412d2ff9616SAxel Dörfler			font.GetFamilyAndStyle(&family, &style);
413d2ff9616SAxel Dörfler
414d2ff9616SAxel Dörfler			_SetFontStyle(family, style);
415d2ff9616SAxel Dörfler			break;
416d2ff9616SAxel Dörfler		}
417d2ff9616SAxel Dörfler		case kMsgSetBold:
418d2ff9616SAxel Dörfler		{
419d2ff9616SAxel Dörfler			uint32 sameProperties;
420d2ff9616SAxel Dörfler			BFont font;
421d2ff9616SAxel Dörfler			fTextView->GetFontAndColor(&font, &sameProperties);
422d2ff9616SAxel Dörfler
423d2ff9616SAxel Dörfler			if (fBoldItem->IsMarked())
424d2ff9616SAxel Dörfler				font.SetFace(B_REGULAR_FACE);
425d2ff9616SAxel Dörfler			fBoldItem->SetMarked(!fBoldItem->IsMarked());
426d2ff9616SAxel Dörfler
427d2ff9616SAxel Dörfler			font_family family;
428d2ff9616SAxel Dörfler			font_style style;
429d2ff9616SAxel Dörfler			font.GetFamilyAndStyle(&family, &style);
430d2ff9616SAxel Dörfler
431d2ff9616SAxel Dörfler			_SetFontStyle(family, style);
432d2ff9616SAxel Dörfler			break;
433d2ff9616SAxel Dörfler		}
4345188c282SAxel Dörfler		case FONT_COLOR:
4355188c282SAxel Dörfler		{
436e62d9cf8SPhilippe Saint-Pierre			ssize_t colorLength;
437e62d9cf8SPhilippe Saint-Pierre			rgb_color* color;
438e62d9cf8SPhilippe Saint-Pierre			if (message->FindData("color", B_RGB_COLOR_TYPE,
439e62d9cf8SPhilippe Saint-Pierre					(const void**)&color, &colorLength) == B_OK
440e62d9cf8SPhilippe Saint-Pierre				&& colorLength == sizeof(rgb_color)) {
441e62d9cf8SPhilippe Saint-Pierre				/*
442e62d9cf8SPhilippe Saint-Pierre				 * TODO: Ideally, when selecting the default color,
443e62d9cf8SPhilippe Saint-Pierre				 * you wouldn't naively apply it; it shouldn't lose its nature.
444e62d9cf8SPhilippe Saint-Pierre				 * When reloaded with a different default color, it should
445e62d9cf8SPhilippe Saint-Pierre				 * reflect that different choice.
446e62d9cf8SPhilippe Saint-Pierre				 */
447e62d9cf8SPhilippe Saint-Pierre				_SetFontColor(color);
4485188c282SAxel Dörfler			}
4495188c282SAxel Dörfler			break;
4505188c282SAxel Dörfler		}
45131139022SAxel Dörfler
4525188c282SAxel Dörfler		// Document menu
4535188c282SAxel Dörfler
4545188c282SAxel Dörfler		case ALIGN_LEFT:
4555188c282SAxel Dörfler			fTextView->SetAlignment(B_ALIGN_LEFT);
4565188c282SAxel Dörfler			_UpdateCleanUndoRedoSaveRevert();
4575188c282SAxel Dörfler			break;
4585188c282SAxel Dörfler		case ALIGN_CENTER:
4595188c282SAxel Dörfler			fTextView->SetAlignment(B_ALIGN_CENTER);
4605188c282SAxel Dörfler			_UpdateCleanUndoRedoSaveRevert();
4615188c282SAxel Dörfler			break;
4625188c282SAxel Dörfler		case ALIGN_RIGHT:
4635188c282SAxel Dörfler			fTextView->SetAlignment(B_ALIGN_RIGHT);
4645188c282SAxel Dörfler			_UpdateCleanUndoRedoSaveRevert();
4655188c282SAxel Dörfler			break;
4665188c282SAxel Dörfler		case WRAP_LINES:
4675188c282SAxel Dörfler		{
4685188c282SAxel Dörfler			BRect textRect(fTextView->Bounds());
4695188c282SAxel Dörfler			textRect.OffsetTo(B_ORIGIN);
4705188c282SAxel Dörfler			textRect.InsetBy(TEXT_INSET, TEXT_INSET);
4715188c282SAxel Dörfler			if (fTextView->DoesWordWrap()) {
4725188c282SAxel Dörfler				fTextView->SetWordWrap(false);
4735188c282SAxel Dörfler				fWrapItem->SetMarked(false);
4745188c282SAxel Dörfler				// the width comes from stylededit R5. TODO: find a better way
4755188c282SAxel Dörfler				textRect.SetRightBottom(BPoint(1500.0, textRect.RightBottom().y));
4765188c282SAxel Dörfler			} else {
4775188c282SAxel Dörfler				fTextView->SetWordWrap(true);
4785188c282SAxel Dörfler				fWrapItem->SetMarked(true);
4795188c282SAxel Dörfler			}
4805188c282SAxel Dörfler			fTextView->SetTextRect(textRect);
4815188c282SAxel Dörfler
4825188c282SAxel Dörfler			_UpdateCleanUndoRedoSaveRevert();
4835188c282SAxel Dörfler			break;
4845188c282SAxel Dörfler		}
4855188c282SAxel Dörfler		case SHOW_STATISTICS:
4865188c282SAxel Dörfler			_ShowStatistics();
4875188c282SAxel Dörfler			break;
4885188c282SAxel Dörfler		case ENABLE_ITEMS:
4895188c282SAxel Dörfler			fCutItem->SetEnabled(true);
4905188c282SAxel Dörfler			fCopyItem->SetEnabled(true);
4915188c282SAxel Dörfler			break;
4925188c282SAxel Dörfler		case DISABLE_ITEMS:
4935188c282SAxel Dörfler			fCutItem->SetEnabled(false);
4945188c282SAxel Dörfler			fCopyItem->SetEnabled(false);
4955188c282SAxel Dörfler			break;
4965188c282SAxel Dörfler		case TEXT_CHANGED:
4975188c282SAxel Dörfler			if (fUndoFlag) {
4985188c282SAxel Dörfler				if (fUndoCleans) {
4995188c282SAxel Dörfler					// we cleaned!
5005188c282SAxel Dörfler					fClean = true;
5015188c282SAxel Dörfler					fUndoCleans = false;
5025188c282SAxel Dörfler				} else if (fClean) {
5035188c282SAxel Dörfler					// if we were clean
5045188c282SAxel Dörfler					// then a redo will make us clean again
5055188c282SAxel Dörfler					fRedoCleans = true;
5065188c282SAxel Dörfler					fClean = false;
5075188c282SAxel Dörfler				}
5085188c282SAxel Dörfler				// set mode
5095188c282SAxel Dörfler				fCanUndo = false;
5105188c282SAxel Dörfler				fCanRedo = true;
5115188c282SAxel Dörfler				fUndoItem->SetLabel(B_TRANSLATE("Redo typing"));
5125188c282SAxel Dörfler				fUndoItem->SetEnabled(true);
5135188c282SAxel Dörfler				fUndoFlag = false;
5145188c282SAxel Dörfler			} else {
5155188c282SAxel Dörfler				if (fRedoFlag && fRedoCleans) {
5165188c282SAxel Dörfler					// we cleaned!
5175188c282SAxel Dörfler					fClean = true;
5185188c282SAxel Dörfler					fRedoCleans = false;
5195188c282SAxel Dörfler				} else if (fClean) {
5205188c282SAxel Dörfler					// if we were clean
5215188c282SAxel Dörfler					// then an undo will make us clean again
5225188c282SAxel Dörfler					fUndoCleans = true;
5235188c282SAxel Dörfler					fClean = false;
5245188c282SAxel Dörfler				} else {
5255188c282SAxel Dörfler					// no more cleaning from undo now...
5265188c282SAxel Dörfler					fUndoCleans = false;
5275188c282SAxel Dörfler				}
5285188c282SAxel Dörfler				// set mode
5295188c282SAxel Dörfler				fCanUndo = true;
5305188c282SAxel Dörfler				fCanRedo = false;
5315188c282SAxel Dörfler				fUndoItem->SetLabel(B_TRANSLATE("Undo typing"));
5325188c282SAxel Dörfler				fUndoItem->SetEnabled(true);
5335188c282SAxel Dörfler				fRedoFlag = false;
5345188c282SAxel Dörfler			}
5355188c282SAxel Dörfler			if (fClean) {
5365188c282SAxel Dörfler				fSaveItem->SetEnabled(fSaveMessage == NULL);
5375188c282SAxel Dörfler			} else {
5385188c282SAxel Dörfler				fSaveItem->SetEnabled(true);
5395188c282SAxel Dörfler			}
5400cc8d8abSSiarzhuk Zharski			fReloadItem->SetEnabled(fSaveMessage != NULL);
5410cc8d8abSSiarzhuk Zharski			fEncodingItem->SetEnabled(fSaveMessage != NULL);
5425188c282SAxel Dörfler			break;
5435188c282SAxel Dörfler
5445188c282SAxel Dörfler		case SAVE_AS_ENCODING:
5455188c282SAxel Dörfler			void* ptr;
5465188c282SAxel Dörfler			if (message->FindPointer("source", &ptr) == B_OK
5475188c282SAxel Dörfler				&& fSavePanelEncodingMenu != NULL) {
5485188c282SAxel Dörfler				fTextView->SetEncoding(
5495188c282SAxel Dörfler					(uint32)fSavePanelEncodingMenu->IndexOf((BMenuItem*)ptr));
5505188c282SAxel Dörfler			}
5515188c282SAxel Dörfler			break;
5525188c282SAxel Dörfler
5530f4985d8SVlad Slepukhin		case UPDATE_STATUS:
55442cb481fSSiarzhuk Zharski		{
5550f4985d8SVlad Slepukhin			message->AddBool("modified", !fClean);
55642cb481fSSiarzhuk Zharski			bool readOnly = !fTextView->IsEditable();
55742cb481fSSiarzhuk Zharski			message->AddBool("readOnly", readOnly);
55842cb481fSSiarzhuk Zharski			if (readOnly) {
55942cb481fSSiarzhuk Zharski				BVolume volume(fNodeRef.device);
56042cb481fSSiarzhuk Zharski				message->AddBool("canUnlock", !volume.IsReadOnly());
56142cb481fSSiarzhuk Zharski			}
5620f4985d8SVlad Slepukhin			fStatusView->SetStatus(message);
5630f4985d8SVlad Slepukhin			break;
56442cb481fSSiarzhuk Zharski		}
5650f4985d8SVlad Slepukhin
5668914c88dSJanus		case UPDATE_STATUS_REF:
5678914c88dSJanus		{
5688914c88dSJanus			entry_ref ref;
5698914c88dSJanus			const char* name;
5708914c88dSJanus
5718914c88dSJanus			if (fSaveMessage != NULL
5728914c88dSJanus				&& fSaveMessage->FindRef("directory", &ref) == B_OK
5738914c88dSJanus				&& fSaveMessage->FindString("name", &name) == B_OK) {
5748914c88dSJanus
5758914c88dSJanus				BDirectory dir(&ref);
5768914c88dSJanus				status_t status = dir.InitCheck();
5778914c88dSJanus				BEntry entry;
5788914c88dSJanus				if (status == B_OK)
5798914c88dSJanus					status = entry.SetTo(&dir, name);
5808914c88dSJanus				if (status == B_OK)
5818914c88dSJanus					status = entry.GetRef(&ref);
5828914c88dSJanus			}
5838914c88dSJanus			fStatusView->SetRef(ref);
5848914c88dSJanus			break;
5858914c88dSJanus		}
5868914c88dSJanus
5870f4985d8SVlad Slepukhin		case UNLOCK_FILE:
5880f4985d8SVlad Slepukhin		{
5890f4985d8SVlad Slepukhin			status_t status = _UnlockFile();
5900f4985d8SVlad Slepukhin			if (status != B_OK) {
5910f4985d8SVlad Slepukhin				BString text;
5920f4985d8SVlad Slepukhin				bs_printf(&text,
5930f4985d8SVlad Slepukhin					B_TRANSLATE("Unable to unlock file\n\t%s"),
5940f4985d8SVlad Slepukhin					strerror(status));
5950f4985d8SVlad Slepukhin				_ShowAlert(text, B_TRANSLATE("OK"), "", "", B_STOP_ALERT);
5960f4985d8SVlad Slepukhin			}
5970f4985d8SVlad Slepukhin			PostMessage(UPDATE_STATUS);
5980f4985d8SVlad Slepukhin			break;
5990f4985d8SVlad Slepukhin		}
6000f4985d8SVlad Slepukhin
601c7087c91SSiarzhuk Zharski		case UPDATE_LINE_SELECTION:
60246f1daffSVlad Slepukhin		{
60346f1daffSVlad Slepukhin			int32 line;
60446f1daffSVlad Slepukhin			if (message->FindInt32("be:line", &line) == B_OK) {
60546f1daffSVlad Slepukhin				fTextView->GoToLine(line);
60646f1daffSVlad Slepukhin				fTextView->ScrollToSelection();
60746f1daffSVlad Slepukhin			}
60846f1daffSVlad Slepukhin
60946f1daffSVlad Slepukhin			int32 start, length;
61046f1daffSVlad Slepukhin			if (message->FindInt32("be:selection_offset", &start) == B_OK) {
61146f1daffSVlad Slepukhin				if (message->FindInt32("be:selection_length", &length) != B_OK)
61246f1daffSVlad Slepukhin					length = 0;
61346f1daffSVlad Slepukhin
61446f1daffSVlad Slepukhin				fTextView->Select(start, start + length);
61546f1daffSVlad Slepukhin				fTextView->ScrollToOffset(start);
61646f1daffSVlad Slepukhin			}
61746f1daffSVlad Slepukhin			break;
61846f1daffSVlad Slepukhin		}
6195188c282SAxel Dörfler		default:
6205188c282SAxel Dörfler			BWindow::MessageReceived(message);
6215188c282SAxel Dörfler			break;
62231139022SAxel Dörfler	}
6235188c282SAxel Dörfler}
62414ea5e5eSKarsten Heimrich
62514ea5e5eSKarsten Heimrich
6265188c282SAxel Dörflervoid
6275188c282SAxel DörflerStyledEditWindow::MenusBeginning()
6285188c282SAxel Dörfler{
6295188c282SAxel Dörfler	// update the font menu
6305188c282SAxel Dörfler	// unselect the old values
6315188c282SAxel Dörfler	if (fCurrentFontItem != NULL) {
6325188c282SAxel Dörfler		fCurrentFontItem->SetMarked(false);
6335188c282SAxel Dörfler		BMenu* menu = fCurrentFontItem->Submenu();
6345188c282SAxel Dörfler		if (menu != NULL) {
6355188c282SAxel Dörfler			BMenuItem* item = menu->FindMarked();
6362cfeb3caSJohn Scipione			if (item != NULL)
6375188c282SAxel Dörfler				item->SetMarked(false);
6385188c282SAxel Dörfler		}
6395188c282SAxel Dörfler	}
64031139022SAxel Dörfler
6415188c282SAxel Dörfler	if (fCurrentStyleItem != NULL) {
6425188c282SAxel Dörfler		fCurrentStyleItem->SetMarked(false);
6435188c282SAxel Dörfler	}
6445188c282SAxel Dörfler
6455188c282SAxel Dörfler	BMenuItem* oldColorItem = fFontColorMenu->FindMarked();
6465188c282SAxel Dörfler	if (oldColorItem != NULL)
6475188c282SAxel Dörfler		oldColorItem->SetMarked(false);
6485188c282SAxel Dörfler
6495188c282SAxel Dörfler	BMenuItem* oldSizeItem = fFontSizeMenu->FindMarked();
6505188c282SAxel Dörfler	if (oldSizeItem != NULL)
6515188c282SAxel Dörfler		oldSizeItem->SetMarked(false);
6525188c282SAxel Dörfler
6535188c282SAxel Dörfler	// find the current font, color, size
6545188c282SAxel Dörfler	BFont font;
6555188c282SAxel Dörfler	uint32 sameProperties;
656e62d9cf8SPhilippe Saint-Pierre	rgb_color color = ui_color(B_DOCUMENT_TEXT_COLOR);
6575188c282SAxel Dörfler	bool sameColor;
6585188c282SAxel Dörfler	fTextView->GetFontAndColor(&font, &sameProperties, &color, &sameColor);
6592cfeb3caSJohn Scipione	color.alpha = 255;
6605188c282SAxel Dörfler
6612cfeb3caSJohn Scipione	if (sameColor) {
662e62d9cf8SPhilippe Saint-Pierre		if (fDefaultFontColorItem->Color() == color)
663e62d9cf8SPhilippe Saint-Pierre			fDefaultFontColorItem->SetMarked(true);
664e62d9cf8SPhilippe Saint-Pierre		else {
665e62d9cf8SPhilippe Saint-Pierre			for (int i = 0; i < fFontColorMenu->CountItems(); i++) {
666e62d9cf8SPhilippe Saint-Pierre				ColorMenuItem* item = dynamic_cast<ColorMenuItem*>
667e62d9cf8SPhilippe Saint-Pierre					(fFontColorMenu->ItemAt(i));
668e62d9cf8SPhilippe Saint-Pierre				if (item != NULL && item->Color() == color) {
669e62d9cf8SPhilippe Saint-Pierre					item->SetMarked(true);
670e62d9cf8SPhilippe Saint-Pierre					break;
671f7afd44bSPhil Greenway				}
672f7afd44bSPhil Greenway			}
673f7afd44bSPhil Greenway		}
67431139022SAxel Dörfler	}
67531139022SAxel Dörfler
6765188c282SAxel Dörfler	if (sameProperties & B_FONT_SIZE) {
6775188c282SAxel Dörfler		if ((int)font.Size() == font.Size()) {
6785188c282SAxel Dörfler			// select the current font size
6795188c282SAxel Dörfler			char fontSizeStr[16];
6805188c282SAxel Dörfler			snprintf(fontSizeStr, 15, "%i", (int)font.Size());
6815188c282SAxel Dörfler			BMenuItem* item = fFontSizeMenu->FindItem(fontSizeStr);
6825188c282SAxel Dörfler			if (item != NULL)
6835188c282SAxel Dörfler				item->SetMarked(true);
6845188c282SAxel Dörfler		}
6855188c282SAxel Dörfler	}
6865188c282SAxel Dörfler
6875188c282SAxel Dörfler	font_family family;
6885188c282SAxel Dörfler	font_style style;
6895188c282SAxel Dörfler	font.GetFamilyAndStyle(&family, &style);
6905188c282SAxel Dörfler
6915188c282SAxel Dörfler	fCurrentFontItem = fFontMenu->FindItem(family);
6925188c282SAxel Dörfler
6935188c282SAxel Dörfler	if (fCurrentFontItem != NULL) {
6945188c282SAxel Dörfler		fCurrentFontItem->SetMarked(true);
6955188c282SAxel Dörfler		BMenu* menu = fCurrentFontItem->Submenu();
6965188c282SAxel Dörfler		if (menu != NULL) {
6975188c282SAxel Dörfler			BMenuItem* item = menu->FindItem(style);
6985188c282SAxel Dörfler			fCurrentStyleItem = item;
699d2ff9616SAxel Dörfler			if (fCurrentStyleItem != NULL)
7005188c282SAxel Dörfler				item->SetMarked(true);
7015188c282SAxel Dörfler		}
7025188c282SAxel Dörfler	}
7035188c282SAxel Dörfler
704d2ff9616SAxel Dörfler	fBoldItem->SetMarked((font.Face() & B_BOLD_FACE) != 0);
705d2ff9616SAxel Dörfler	fItalicItem->SetMarked((font.Face() & B_ITALIC_FACE) != 0);
706d2ff9616SAxel Dörfler
7075188c282SAxel Dörfler	switch (fTextView->Alignment()) {
7085188c282SAxel Dörfler		case B_ALIGN_LEFT:
7095188c282SAxel Dörfler		default:
7105188c282SAxel Dörfler			fAlignLeft->SetMarked(true);
7115188c282SAxel Dörfler			break;
7125188c282SAxel Dörfler		case B_ALIGN_CENTER:
7135188c282SAxel Dörfler			fAlignCenter->SetMarked(true);
7145188c282SAxel Dörfler			break;
7155188c282SAxel Dörfler		case B_ALIGN_RIGHT:
7165188c282SAxel Dörfler			fAlignRight->SetMarked(true);
7175188c282SAxel Dörfler			break;
7185188c282SAxel Dörfler	}
7190cc8d8abSSiarzhuk Zharski
7200cc8d8abSSiarzhuk Zharski	// text encoding
7210cc8d8abSSiarzhuk Zharski	const BCharacterSet* charset
7220cc8d8abSSiarzhuk Zharski		= BCharacterSetRoster::GetCharacterSetByFontID(fTextView->GetEncoding());
7230cc8d8abSSiarzhuk Zharski	BMenu* encodingMenu = fEncodingItem->Submenu();
7240cc8d8abSSiarzhuk Zharski	if (charset != NULL && encodingMenu != NULL) {
7250cc8d8abSSiarzhuk Zharski		const char* mime = charset->GetMIMEName();
7260cc8d8abSSiarzhuk Zharski		BString name(charset->GetPrintName());
7270cc8d8abSSiarzhuk Zharski		if (mime)
7280cc8d8abSSiarzhuk Zharski			name << " (" << mime << ")";
7290cc8d8abSSiarzhuk Zharski
7300cc8d8abSSiarzhuk Zharski		BMenuItem* item = encodingMenu->FindItem(name);
7310cc8d8abSSiarzhuk Zharski		if (item != NULL)
7320cc8d8abSSiarzhuk Zharski			item->SetMarked(true);
7330cc8d8abSSiarzhuk Zharski	}
7345188c282SAxel Dörfler}
7355188c282SAxel Dörfler
7365188c282SAxel Dörfler
737546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
738546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "SaveAlert"
7395188c282SAxel Dörfler
7405188c282SAxel Dörfler
7415188c282SAxel Dörflerstatus_t
7425188c282SAxel DörflerStyledEditWindow::Save(BMessage* message)
7435188c282SAxel Dörfler{
7440cc8d8abSSiarzhuk Zharski	_NodeMonitorSuspender nodeMonitorSuspender(this);
7450cc8d8abSSiarzhuk Zharski
7465188c282SAxel Dörfler	if (!message)
7475188c282SAxel Dörfler		message = fSaveMessage;
7485188c282SAxel Dörfler
7495188c282SAxel Dörfler	if (!message)
7505188c282SAxel Dörfler		return B_ERROR;
7515188c282SAxel Dörfler
7525188c282SAxel Dörfler	entry_ref dirRef;
7535188c282SAxel Dörfler	const char* name;
7545188c282SAxel Dörfler	if (message->FindRef("directory", &dirRef) != B_OK
7555188c282SAxel Dörfler		|| message->FindString("name", &name) != B_OK)
7565188c282SAxel Dörfler		return B_BAD_VALUE;
7575188c282SAxel Dörfler
7585188c282SAxel Dörfler	BDirectory dir(&dirRef);
7595188c282SAxel Dörfler	BEntry entry(&dir, name);
7605188c282SAxel Dörfler
7615188c282SAxel Dörfler	status_t status = B_ERROR;
7625188c282SAxel Dörfler	if (dir.InitCheck() == B_OK && entry.InitCheck() == B_OK) {
7635188c282SAxel Dörfler		struct stat st;
7645188c282SAxel Dörfler		BFile file(&entry, B_READ_WRITE | B_CREATE_FILE);
7655188c282SAxel Dörfler		if (file.InitCheck() == B_OK
7665188c282SAxel Dörfler			&& (status = file.GetStat(&st)) == B_OK) {
7675188c282SAxel Dörfler			// check the file permissions
7685188c282SAxel Dörfler			if (!((getuid() == st.st_uid && (S_IWUSR & st.st_mode))
7695188c282SAxel Dörfler				|| (getgid() == st.st_gid && (S_IWGRP & st.st_mode))
7705188c282SAxel Dörfler				|| (S_IWOTH & st.st_mode))) {
7715188c282SAxel Dörfler				BString alertText;
7725188c282SAxel Dörfler				bs_printf(&alertText, B_TRANSLATE("This file is marked "
773776c58b2SHumdinger					"read-only. Save changes to the document \"%s\"? "), name);
7745188c282SAxel Dörfler				switch (_ShowAlert(alertText, B_TRANSLATE("Cancel"),
7755188c282SAxel Dörfler						B_TRANSLATE("Don't save"),
7765188c282SAxel Dörfler						B_TRANSLATE("Save"), B_WARNING_ALERT)) {
7775188c282SAxel Dörfler					case 0:
7785188c282SAxel Dörfler						return B_CANCELED;
7795188c282SAxel Dörfler					case 1:
7805188c282SAxel Dörfler						return B_OK;
7815188c282SAxel Dörfler					default:
7825188c282SAxel Dörfler						break;
7835188c282SAxel Dörfler				}
7845188c282SAxel Dörfler			}
7855188c282SAxel Dörfler
7865188c282SAxel Dörfler			status = fTextView->WriteStyledEditFile(&file);
7875188c282SAxel Dörfler		}
7885188c282SAxel Dörfler	}
7895188c282SAxel Dörfler
7905188c282SAxel Dörfler	if (status != B_OK) {
7915188c282SAxel Dörfler		BString alertText;
7925188c282SAxel Dörfler		bs_printf(&alertText, B_TRANSLATE("Error saving \"%s\":\n%s"), name,
7935188c282SAxel Dörfler			strerror(st