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