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