StyledEditView.cpp revision 3f7e8e7395428cadab1afd6bd54906e8b481e404
1#include <Message.h>
2#include <Messenger.h>
3#include <Rect.h>
4#include <Region.h>
5#include <TranslationUtils.h>
6#include <Node.h>
7#include <stdio.h>
8#include <CharacterSet.h>
9#include <CharacterSetRoster.h>
10#include <UTF8.h>
11
12#include <StyledEditView.h>
13#include <Constants.h>
14
15using namespace BPrivate;
16
17StyledEditView::StyledEditView(BRect viewFrame, BRect textBounds, BHandler *handler)
18	: BTextView(viewFrame, "textview", textBounds,
19			    B_FOLLOW_ALL, B_FRAME_EVENTS|B_WILL_DRAW)
20{
21	fHandler= handler;
22	fMessenger= new BMessenger(handler);
23	fSuppressChanges = false;
24	fEncoding = 0;
25}
26
27StyledEditView::~StyledEditView()
28{
29	delete fMessenger;
30}
31
32void
33StyledEditView::FrameResized(float width, float height)
34{
35	BTextView::FrameResized(width, height);
36
37	if (DoesWordWrap()) {
38		BRect textRect;
39		textRect = Bounds();
40		textRect.OffsetTo(B_ORIGIN);
41		textRect.InsetBy(TEXT_INSET,TEXT_INSET);
42		SetTextRect(textRect);
43	}
44/*	// I tried to do some sort of intelligent resize thing but it just doesn't work
45	// so we revert to the R5 stylededit yucky practice of setting the text rect to
46	// some crazy large number when word wrap is turned off :-(
47	 else if (textRect.Width() > TextRect().Width()) {
48		SetTextRect(textRect);
49	}
50
51	BRegion region;
52	GetTextRegion(0,TextLength(),&region);
53	float textWidth = region.Frame().Width();
54	if (textWidth < textRect.Width()) {
55		BRect textRect(B_ORIGIN,BPoint(textWidth+TEXT_INSET*2,Bounds().Height()));
56		textRect.InsetBy(TEXT_INSET,TEXT_INSET);
57		SetTextRect(textRect);
58	}
59	*/
60}
61
62status_t
63StyledEditView::GetStyledText(BPositionIO * stream)
64{
65	status_t result = B_OK;
66
67	fSuppressChanges = true;
68	result = BTranslationUtils::GetStyledText(stream, this, NULL);
69	fSuppressChanges = false;
70	if (result != B_OK) {
71		return result;
72	}
73
74	BNode * node = dynamic_cast<BNode*>(stream);
75	if (node != 0) {
76		ssize_t bytesRead;
77		// decode encoding
78		int32 encoding;
79		bytesRead = node->ReadAttr("be:encoding",0,0,&encoding,sizeof(encoding));
80		if (bytesRead > 0) {
81			if (encoding == 65535) {
82				fEncoding = 0;
83			} else {
84				const BCharacterSet * cs = BCharacterSetRoster::GetCharacterSetByConversionID(encoding);
85				if (cs != 0) {
86					fEncoding = cs->GetFontID();
87				}
88			}
89		}
90
91		// restore alignment
92		alignment align;
93		bytesRead = node->ReadAttr("alignment",0,0,&align,sizeof(align));
94		if (bytesRead > 0) {
95			SetAlignment(align);
96		}
97		// restore wrapping
98		bool wrap;
99		bytesRead = node->ReadAttr("wrap",0,0,&wrap,sizeof(wrap));
100		if (bytesRead > 0) {
101			SetWordWrap(wrap);
102		}
103		if (wrap == false) {
104			BRect textRect;
105			textRect = Bounds();
106			textRect.OffsetTo(B_ORIGIN);
107			textRect.InsetBy(TEXT_INSET,TEXT_INSET);
108				// the width comes from stylededit R5. TODO: find a better way
109			textRect.SetRightBottom(BPoint(1500.0,textRect.RightBottom().y));
110			SetTextRect(textRect);
111		}
112	}
113	if (fEncoding != 0) {
114		int32 length = stream->Seek(0,SEEK_END);
115		text_run_array * run_array = RunArray(0,length);
116		uint32 id = BCharacterSetRoster::GetCharacterSetByFontID(fEncoding)->GetConversionID();
117		fSuppressChanges = true;
118		SetText("");
119		fSuppressChanges = false;
120		char inBuffer[32768];
121		off_t location = 0;
122		int32 textOffset = 0;
123		int32 state = 0;
124		int32 bytesRead;
125		while ((bytesRead = stream->ReadAt(location,inBuffer,32768)) > 0) {
126			char * inPtr = inBuffer;
127			char textBuffer[32768];
128			int32 textLength = 32768;
129			int32 bytes = bytesRead;
130			while ((textLength > 0) && (bytes > 0)) {
131				result = convert_to_utf8(id,inPtr,&bytes,textBuffer,&textLength,&state);
132				if (result != B_OK) {
133					return result;
134				}
135				fSuppressChanges = true;
136				InsertText(textBuffer,textLength,textOffset);
137				fSuppressChanges = false;
138				textOffset += textLength;
139				inPtr += bytes;
140				location += bytes;
141				bytesRead -= bytes;
142				bytes = bytesRead;
143				if (textLength > 0) {
144					textLength = 32768;
145				}
146			}
147		}
148		SetRunArray(0,length,run_array);
149	}
150	return result;
151}
152
153status_t
154StyledEditView::WriteStyledEditFile(BFile * file)
155{
156	status_t result = B_OK;
157	result = BTranslationUtils::WriteStyledEditFile(this,file);
158	if (result != B_OK) {
159		return result;
160	}
161	if (fEncoding == 0) {
162		int32 encoding = 65535;
163		file->WriteAttr("be:encoding",B_INT32_TYPE,0,&encoding,sizeof(encoding));
164	} else {
165		result = file->SetSize(0);
166		if (result != B_OK) {
167			return result;
168		}
169		result = file->Seek(0,SEEK_SET);
170		if (result != B_OK) {
171			return result;
172		}
173		const BCharacterSet * cs = BCharacterSetRoster::GetCharacterSetByFontID(fEncoding);
174		if (cs != 0) {
175			uint32 id = cs->GetConversionID();
176			const char * outText = Text();
177			int32 sourceLength = TextLength();
178			int32 state = 0;
179			char buffer[32768];
180			while (sourceLength > 0) {
181				int32 length = sourceLength;
182				int32 written = 32768;
183				result = convert_from_utf8(id,outText,&length,buffer,&written,&state);
184				if (result != B_OK) {
185					return result;
186				}
187				file->Write(buffer,written);
188				sourceLength -= length;
189				outText += length;
190			}
191			file->WriteAttr("be:encoding",B_INT32_TYPE,0,&id,sizeof(id));
192		}
193	}
194
195	alignment align = Alignment();
196	file->WriteAttr("alignment",B_INT32_TYPE,0,&align,sizeof(align));
197	bool wrap = DoesWordWrap();
198	file->WriteAttr("wrap",B_BOOL_TYPE,0,&wrap,sizeof(wrap));
199	return result;
200}
201
202void
203StyledEditView::Reset()
204{
205	fSuppressChanges = true;
206	SetText("");
207	fSuppressChanges = false;
208}
209
210void
211StyledEditView::Select(int32 start, int32 finish)
212{
213	if(start==finish)
214		fChangeMessage= new BMessage(DISABLE_ITEMS);
215	else
216		fChangeMessage= new BMessage(ENABLE_ITEMS);
217
218	fMessenger->SendMessage(fChangeMessage);
219
220	BTextView::Select(start, finish);
221}
222
223void
224StyledEditView::SetEncoding(uint32 encoding)
225{
226	fEncoding = encoding;
227}
228
229uint32
230StyledEditView::GetEncoding() const
231{
232	return fEncoding;
233}
234
235void
236StyledEditView::InsertText(const char *text, int32 length, int32 offset, const text_run_array *runs)
237{
238	if (!fSuppressChanges)
239		fMessenger-> SendMessage(new BMessage(TEXT_CHANGED));
240
241	BTextView::InsertText(text, length, offset, runs);
242
243}/****StyledEditView::InsertText()***/
244
245void
246StyledEditView::DeleteText(int32 start, int32 finish)
247{
248	if (!fSuppressChanges)
249		fMessenger-> SendMessage(new BMessage(TEXT_CHANGED));
250
251	BTextView::DeleteText(start, finish);
252
253}/***StyledEditView::DeleteText***/
254