xref: /haiku/src/apps/stylededit/StyledEditView.cpp (revision db10640de90f7f9519ba2da9577b7c1af3c64f6b)
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 
15 using namespace BPrivate;
16 
17 StyledEditView::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 
27 StyledEditView::~StyledEditView()
28 {
29 	delete fMessenger;
30 }
31 
32 void
33 StyledEditView::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 
62 status_t
63 StyledEditView::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 			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 	}
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 
153 status_t
154 StyledEditView::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 
202 void
203 StyledEditView::Reset()
204 {
205 	fSuppressChanges = true;
206 	SetText("");
207 	fSuppressChanges = false;
208 }
209 
210 void
211 StyledEditView::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 
223 void
224 StyledEditView::SetEncoding(uint32 encoding)
225 {
226 	fEncoding = encoding;
227 }
228 
229 uint32
230 StyledEditView::GetEncoding() const
231 {
232 	return fEncoding;
233 }
234 
235 void
236 StyledEditView::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 
245 void
246 StyledEditView::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