xref: /haiku/src/apps/stylededit/StyledEditView.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Mattias Sundblad
7  *		Andrew Bachmann
8  *		Axel Dörfler, axeld@pinc-software.de
9  */
10 
11 
12 #include "Constants.h"
13 #include "StyledEditView.h"
14 
15 #include <CharacterSet.h>
16 #include <CharacterSetRoster.h>
17 #include <DataIO.h>
18 #include <File.h>
19 #include <Message.h>
20 #include <Messenger.h>
21 #include <Node.h>
22 #include <Rect.h>
23 #include <TranslationUtils.h>
24 #include <UTF8.h>
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 
29 
30 using namespace BPrivate;
31 
32 
33 StyledEditView::StyledEditView(BRect viewFrame, BRect textBounds,
34 	BHandler* handler)
35 	:
36 	BTextView(viewFrame, "textview", textBounds, NULL,
37 		&(fInitialColor = ui_color(B_DOCUMENT_TEXT_COLOR)),
38 		B_FOLLOW_ALL, B_FRAME_EVENTS | B_WILL_DRAW)
39 {
40 	SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR);
41 	SetLowUIColor(ViewUIColor());
42 
43 	fMessenger = new BMessenger(handler);
44 	fSuppressChanges = false;
45 }
46 
47 
48 StyledEditView::~StyledEditView()
49 {
50 	delete fMessenger;
51 }
52 
53 
54 
55 void
56 StyledEditView::FrameResized(float width, float height)
57 {
58 	BTextView::FrameResized(width, height);
59 
60 	if (DoesWordWrap()) {
61 		BRect textRect;
62 		textRect = Bounds();
63 		textRect.OffsetTo(B_ORIGIN);
64 		textRect.InsetBy(TEXT_INSET, TEXT_INSET);
65 		SetTextRect(textRect);
66 	}
67 }
68 
69 
70 void
71 StyledEditView::DeleteText(int32 start, int32 finish)
72 {
73 	if (!fSuppressChanges)
74 		fMessenger-> SendMessage(TEXT_CHANGED);
75 
76 	BTextView::DeleteText(start, finish);
77 	_UpdateStatus();
78 }
79 
80 
81 void
82 StyledEditView::InsertText(const char* text, int32 length, int32 offset,
83 	const text_run_array* runs)
84 {
85 	if (!fSuppressChanges)
86 		fMessenger->SendMessage(TEXT_CHANGED);
87 
88 	BTextView::InsertText(text, length, offset, runs);
89 	_UpdateStatus();
90 }
91 
92 
93 void
94 StyledEditView::Select(int32 start, int32 finish)
95 {
96 	fMessenger->SendMessage(start == finish ? DISABLE_ITEMS : ENABLE_ITEMS);
97 	BTextView::Select(start, finish);
98 	_UpdateStatus();
99 }
100 
101 
102 void
103 StyledEditView::Reset()
104 {
105 	fSuppressChanges = true;
106 	SetText("");
107 	fEncoding = "";
108 	fSuppressChanges = false;
109 }
110 
111 
112 void
113 StyledEditView::SetSuppressChanges(bool suppressChanges)
114 {
115 	fSuppressChanges = suppressChanges;
116 }
117 
118 
119 status_t
120 StyledEditView::GetStyledText(BPositionIO* stream, const char* forceEncoding)
121 {
122 	if (forceEncoding != NULL)
123 		fEncoding = strcmp(forceEncoding, "auto") != 0 ? forceEncoding : "";
124 
125 	fSuppressChanges = true;
126 	status_t result = BTranslationUtils::GetStyledText(stream, this,
127 		fEncoding.String());
128 	fSuppressChanges = false;
129 
130 	if (result != B_OK)
131 		return result;
132 
133 	BNode* node = dynamic_cast<BNode*>(stream);
134 	if (node != NULL) {
135 		if (forceEncoding == NULL) {
136 			// get encoding
137 			if (node->ReadAttrString("be:encoding", &fEncoding) != B_OK) {
138 				// try to read as "int32"
139 				int32 encoding;
140 				ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0,
141 					&encoding, sizeof(encoding));
142 				if (bytesRead == (ssize_t)sizeof(encoding)) {
143 					if (encoding == 65535) {
144 						fEncoding = "UTF-8";
145 					} else {
146 						const BCharacterSet* characterSet
147 							= BCharacterSetRoster::GetCharacterSetByConversionID(encoding);
148 						if (characterSet != NULL)
149 							fEncoding = characterSet->GetName();
150 					}
151 				}
152 			}
153 		}
154 		// TODO: move those into BTranslationUtils::GetStyledText() as well?
155 
156 		// restore alignment
157 		int32 align;
158 		ssize_t bytesRead = node->ReadAttr("alignment", 0, 0, &align, sizeof(align));
159 		if (bytesRead == (ssize_t)sizeof(align))
160 			SetAlignment((alignment)align);
161 
162 		// restore wrapping
163 		bool wrap;
164 		bytesRead = node->ReadAttr("wrap", 0, 0, &wrap, sizeof(wrap));
165 		if (bytesRead == (ssize_t)sizeof(wrap)) {
166 			SetWordWrap(wrap);
167 			if (wrap == false) {
168 				BRect textRect;
169 				textRect = Bounds();
170 				textRect.OffsetTo(B_ORIGIN);
171 				textRect.InsetBy(TEXT_INSET, TEXT_INSET);
172 					// the width comes from stylededit R5. TODO: find a better way
173 				textRect.SetRightBottom(BPoint(1500.0, textRect.RightBottom().y));
174 				SetTextRect(textRect);
175 			}
176 		}
177 	}
178 
179 	return result;
180 }
181 
182 
183 status_t
184 StyledEditView::WriteStyledEditFile(BFile* file)
185 {
186 	return BTranslationUtils::WriteStyledEditFile(this, file,
187 		fEncoding.String());
188 }
189 
190 
191 void
192 StyledEditView::SetEncoding(uint32 encoding)
193 {
194 	fEncoding = "";
195 	if (encoding == 0)
196 		return;
197 
198 	const BCharacterSet* set
199 		= BCharacterSetRoster::GetCharacterSetByFontID(encoding);
200 
201 	if (set != NULL)
202 		fEncoding = set->GetName();
203 }
204 
205 
206 uint32
207 StyledEditView::GetEncoding() const
208 {
209 	if (fEncoding == "")
210 		return 0;
211 
212 	const BCharacterSet* set =
213 		BCharacterSetRoster::FindCharacterSetByName(fEncoding.String());
214 	if (set != NULL)
215 		return set->GetFontID();
216 
217 	return 0;
218 }
219 
220 
221 void
222 StyledEditView::_UpdateStatus()
223 {
224 	int32 selStart, selFinish;
225 	GetSelection(&selStart, &selFinish);
226 
227 	int32 line = CurrentLine();
228 	int32 lineStart = OffsetAt(line);
229 
230 	int32 column = 1;
231 	int32 tabSize = (int32)ceilf(TabWidth() / StringWidth("s"));
232 	for (int i = lineStart; i < selStart; i++) {
233 		unsigned char ch = ByteAt(i);
234 		if ((ch & 0xC0) != 0x80) {
235 			if (ch == '\t')
236 				while (column % tabSize)
237 					column++;
238 			column++;
239 		}
240 	}
241 
242 	BMessage* message = new BMessage(UPDATE_STATUS);
243 	message->AddInt32("line", line + 1);
244 	message->AddInt32("column", column);
245 	message->AddString("encoding", fEncoding.String());
246 	fMessenger->SendMessage(message);
247 }
248