xref: /haiku/src/add-ons/translators/rtf/RTFTranslator.cpp (revision 0622135673834fe8fb554c0b973651264b9e7baf)
1 /*
2  * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "RTFTranslator.h"
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 #include <Catalog.h>
14 
15 #include "ConfigView.h"
16 #include "convert.h"
17 #include "RTF.h"
18 
19 
20 #undef B_TRANSLATION_CONTEXT
21 #define B_TRANSLATION_CONTEXT "RTFTranslator"
22 
23 #define READ_BUFFER_SIZE 2048
24 #define DATA_BUFFER_SIZE 64
25 
26 
27 #define TEXT_IN_QUALITY 0.4
28 #define TEXT_IN_CAPABILITY 0.6
29 
30 #define STXT_IN_QUALITY 0.5
31 #define STXT_IN_CAPABILITY 0.5
32 
33 #define RTF_OUT_QUALITY RTF_IN_QUALITY
34 #define RTF_OUT_CAPABILITY RTF_IN_CAPABILITY
35 
36 // The input formats that this translator supports.
37 static const translation_format sInputFormats[] = {
38 	{
39 		RTF_TEXT_FORMAT,
40 		B_TRANSLATOR_TEXT,
41 		RTF_IN_QUALITY,
42 		RTF_IN_CAPABILITY,
43 		"text/rtf",
44 		"RichTextFormat file"
45 	},
46 	{
47 		B_TRANSLATOR_TEXT,
48 		B_TRANSLATOR_TEXT,
49 		TEXT_IN_QUALITY,
50 		TEXT_IN_CAPABILITY,
51 		"text/plain",
52 		"Plain text file"
53 	},
54 	{
55 		B_STYLED_TEXT_FORMAT,
56 		B_TRANSLATOR_TEXT,
57 		STXT_IN_QUALITY,
58 		STXT_IN_CAPABILITY,
59 		"text/x-vnd.Be-stxt",
60 		"Be styled text file"
61 	}
62 };
63 
64 // The output formats that this translator supports.
65 static const translation_format sOutputFormats[] = {
66 	{
67 		B_TRANSLATOR_TEXT,
68 		B_TRANSLATOR_TEXT,
69 		TEXT_OUT_QUALITY,
70 		TEXT_OUT_CAPABILITY,
71 		"text/plain",
72 		"Plain text file"
73 	},
74 	{
75 		B_STYLED_TEXT_FORMAT,
76 		B_TRANSLATOR_TEXT,
77 		STXT_OUT_QUALITY,
78 		STXT_OUT_CAPABILITY,
79 		"text/x-vnd.Be-stxt",
80 		"Be styled text file"
81 	},
82 	{
83 		RTF_TEXT_FORMAT,
84 		B_TRANSLATOR_TEXT,
85 		RTF_OUT_QUALITY,
86 		RTF_OUT_CAPABILITY,
87 		"text/rtf",
88 		"RichTextFormat file"
89 	}
90 };
91 
92 
RTFTranslator()93 RTFTranslator::RTFTranslator()
94 {
95 	char info[256];
96 	sprintf(info, B_TRANSLATE("Rich Text Format translator v%d.%d.%d %s"),
97 		static_cast<int>(B_TRANSLATION_MAJOR_VERSION(RTF_TRANSLATOR_VERSION)),
98 		static_cast<int>(B_TRANSLATION_MINOR_VERSION(RTF_TRANSLATOR_VERSION)),
99 		static_cast<int>(B_TRANSLATION_REVISION_VERSION(
100 			RTF_TRANSLATOR_VERSION)),
101 		__DATE__);
102 
103 	fInfo = strdup(info);
104 }
105 
106 
~RTFTranslator()107 RTFTranslator::~RTFTranslator()
108 {
109 	free(fInfo);
110 }
111 
112 
113 const char *
TranslatorName() const114 RTFTranslator::TranslatorName() const
115 {
116 	return B_TRANSLATE("RTF text files");
117 }
118 
119 
120 const char *
TranslatorInfo() const121 RTFTranslator::TranslatorInfo() const
122 {
123 	return B_TRANSLATE("Rich Text Format translator");
124 }
125 
126 
127 int32
TranslatorVersion() const128 RTFTranslator::TranslatorVersion() const
129 {
130 	return RTF_TRANSLATOR_VERSION;
131 }
132 
133 
134 const translation_format *
InputFormats(int32 * _outCount) const135 RTFTranslator::InputFormats(int32 *_outCount) const
136 {
137 	if (_outCount == NULL)
138 		return NULL;
139 
140 	*_outCount = sizeof(sInputFormats) / sizeof(translation_format);
141 	return sInputFormats;
142 }
143 
144 
145 const translation_format *
OutputFormats(int32 * _outCount) const146 RTFTranslator::OutputFormats(int32 *_outCount) const
147 {
148 	*_outCount = sizeof(sOutputFormats) / sizeof(translation_format);
149 	return sOutputFormats;
150 }
151 
152 
153 status_t
Identify(BPositionIO * stream,const translation_format * format,BMessage * ioExtension,translator_info * info,uint32 outType)154 RTFTranslator::Identify(BPositionIO *stream,
155 	const translation_format *format, BMessage *ioExtension,
156 	translator_info *info, uint32 outType)
157 {
158 	if (!outType)
159 		outType = B_TRANSLATOR_TEXT;
160 	else if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT
161 		&& outType != RTF_TEXT_FORMAT)
162 		return B_NO_TRANSLATOR;
163 
164 
165 	RTF::Parser parser(*stream);
166 	status_t status = parser.Identify();
167 
168 	if (status == B_OK) {
169 		// Source data is RTF. We can translate to RTF (no-op), plaintext, or
170 		// styled text.
171 
172 		// return information about the data in the stream
173 		info->type = B_TRANSLATOR_TEXT; //RTF_TEXT_FORMAT;
174 		info->group = B_TRANSLATOR_TEXT;
175 		info->quality = RTF_IN_QUALITY;
176 		info->capability = RTF_IN_CAPABILITY;
177 		strlcpy(info->name, B_TRANSLATE("RichTextFormat file"),
178 			sizeof(info->name));
179 		strcpy(info->MIME, "text/rtf");
180 	} else {
181 		// Not an RTF file. We can only work with it if we are translating to
182 		// RTF.
183 		if (outType != RTF_TEXT_FORMAT)
184 			return B_NO_TRANSLATOR;
185 
186 		stream->Seek(0, SEEK_SET);
187 		TranslatorStyledTextStreamHeader header;
188 		stream->Read(&header, sizeof(header));
189 		swap_data(B_UINT32_TYPE, &header, sizeof(header),
190 			B_SWAP_BENDIAN_TO_HOST);
191 		stream->Seek(0, SEEK_SET);
192 		if (header.header.magic == B_STYLED_TEXT_FORMAT
193 			&& header.header.header_size == (int32)sizeof(header)
194 			&& header.header.data_size == 0
195 			&& header.version == 100) {
196 			info->type = B_STYLED_TEXT_FORMAT;
197 			info->group = B_TRANSLATOR_TEXT;
198 			info->quality = STXT_IN_QUALITY;
199 			info->capability = STXT_IN_CAPABILITY;
200 			strlcpy(info->name, B_TRANSLATE("Be style text file"),
201 				sizeof(info->name));
202 			strcpy(info->MIME, "text/x-vnd.Be-stxt");
203 		} else {
204 			info->type = B_TRANSLATOR_TEXT;
205 			info->group = B_TRANSLATOR_TEXT;
206 			info->quality = TEXT_IN_QUALITY;
207 			info->capability = TEXT_IN_CAPABILITY;
208 			strlcpy(info->name, B_TRANSLATE("Plain text file"),
209 				sizeof(info->name));
210 			strcpy(info->MIME, "text/plain");
211 		}
212 	}
213 	return B_OK;
214 }
215 
216 
217 status_t
Translate(BPositionIO * source,const translator_info * inInfo,BMessage * ioExtension,uint32 outType,BPositionIO * target)218 RTFTranslator::Translate(BPositionIO *source,
219 	const translator_info *inInfo, BMessage *ioExtension,
220 	uint32 outType, BPositionIO *target)
221 {
222 	if (target == NULL || source == NULL)
223 		return B_BAD_VALUE;
224 
225 	if (!outType)
226 		outType = B_TRANSLATOR_TEXT;
227 	if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT
228 		&& outType != RTF_TEXT_FORMAT)
229 		return B_NO_TRANSLATOR;
230 
231 	if (strncmp(inInfo->MIME, "text/rtf", 8) == 0) {
232 		RTF::Parser parser(*source);
233 
234 		RTF::Header header;
235 		status_t status = parser.Parse(header);
236 		if (status != B_OK)
237 			return status;
238 
239 		if (outType == B_TRANSLATOR_TEXT)
240 			return convert_to_plain_text(header, *target);
241 		else
242 			return convert_to_stxt(header, *target);
243 
244 	} else if (inInfo->type == B_TRANSLATOR_TEXT) {
245 		return convert_plain_text_to_rtf(*source, *target);
246 	} else if (inInfo->type == B_STYLED_TEXT_FORMAT) {
247 		return convert_styled_text_to_rtf(source, target);
248 	} else
249 		return B_BAD_VALUE;
250 
251 }
252 
253 
254 status_t
MakeConfigurationView(BMessage * ioExtension,BView ** _view,BRect * _extent)255 RTFTranslator::MakeConfigurationView(BMessage *ioExtension, BView **_view,
256 	BRect *_extent)
257 {
258 	if (_view == NULL || _extent == NULL)
259 		return B_BAD_VALUE;
260 
261 	BView *view = new ConfigView(BRect(0, 0, 225, 175));
262 	if (view == NULL)
263 		return BTranslator::MakeConfigurationView(ioExtension, _view, _extent);
264 
265 	*_view = view;
266 	*_extent = view->Bounds();
267 	return B_OK;
268 }
269 
270 
271 //	#pragma mark -
272 
273 
274 BTranslator *
make_nth_translator(int32 n,image_id you,uint32 flags,...)275 make_nth_translator(int32 n, image_id you, uint32 flags, ...)
276 {
277 	if (n != 0)
278 		return NULL;
279 
280 	return new RTFTranslator();
281 }
282 
283