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