19949213aSStephan Aßmus /*
29949213aSStephan Aßmus * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
39949213aSStephan Aßmus * Distributed under the terms of the MIT License.
49949213aSStephan Aßmus */
59949213aSStephan Aßmus
69949213aSStephan Aßmus
79949213aSStephan Aßmus #include "RTFTranslator.h"
828e5604cSJérôme Duval
928e5604cSJérôme Duval #include <stdio.h>
1028e5604cSJérôme Duval #include <stdlib.h>
1128e5604cSJérôme Duval #include <string.h>
129949213aSStephan Aßmus
1370d59669SSiarzhuk Zharski #include <Catalog.h>
1428e5604cSJérôme Duval
1528e5604cSJérôme Duval #include "ConfigView.h"
1628e5604cSJérôme Duval #include "convert.h"
1728e5604cSJérôme Duval #include "RTF.h"
1828e5604cSJérôme Duval
199949213aSStephan Aßmus
20546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
21546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "RTFTranslator"
229949213aSStephan Aßmus
239949213aSStephan Aßmus #define READ_BUFFER_SIZE 2048
249949213aSStephan Aßmus #define DATA_BUFFER_SIZE 64
259949213aSStephan Aßmus
269949213aSStephan Aßmus
27fa267963SEzo #define TEXT_IN_QUALITY 0.4
28fa267963SEzo #define TEXT_IN_CAPABILITY 0.6
29fa267963SEzo
30fa267963SEzo #define STXT_IN_QUALITY 0.5
31fa267963SEzo #define STXT_IN_CAPABILITY 0.5
32fa267963SEzo
33fa267963SEzo #define RTF_OUT_QUALITY RTF_IN_QUALITY
34fa267963SEzo #define RTF_OUT_CAPABILITY RTF_IN_CAPABILITY
35fa267963SEzo
369949213aSStephan Aßmus // The input formats that this translator supports.
37bf243977SPhilippe Houdoin static const translation_format sInputFormats[] = {
389949213aSStephan Aßmus {
399949213aSStephan Aßmus RTF_TEXT_FORMAT,
409949213aSStephan Aßmus B_TRANSLATOR_TEXT,
419949213aSStephan Aßmus RTF_IN_QUALITY,
429949213aSStephan Aßmus RTF_IN_CAPABILITY,
439949213aSStephan Aßmus "text/rtf",
449949213aSStephan Aßmus "RichTextFormat file"
45fa267963SEzo },
46fa267963SEzo {
47fa267963SEzo B_TRANSLATOR_TEXT,
48fa267963SEzo B_TRANSLATOR_TEXT,
49fa267963SEzo TEXT_IN_QUALITY,
50fa267963SEzo TEXT_IN_CAPABILITY,
51fa267963SEzo "text/plain",
52fa267963SEzo "Plain text file"
53fa267963SEzo },
54fa267963SEzo {
55fa267963SEzo B_STYLED_TEXT_FORMAT,
56fa267963SEzo B_TRANSLATOR_TEXT,
57fa267963SEzo STXT_IN_QUALITY,
58fa267963SEzo STXT_IN_CAPABILITY,
59fa267963SEzo "text/x-vnd.Be-stxt",
60fa267963SEzo "Be styled text file"
61bf243977SPhilippe Houdoin }
629949213aSStephan Aßmus };
639949213aSStephan Aßmus
649949213aSStephan Aßmus // The output formats that this translator supports.
65bf243977SPhilippe Houdoin static const translation_format sOutputFormats[] = {
669949213aSStephan Aßmus {
679949213aSStephan Aßmus B_TRANSLATOR_TEXT,
689949213aSStephan Aßmus B_TRANSLATOR_TEXT,
699949213aSStephan Aßmus TEXT_OUT_QUALITY,
709949213aSStephan Aßmus TEXT_OUT_CAPABILITY,
719949213aSStephan Aßmus "text/plain",
729949213aSStephan Aßmus "Plain text file"
739949213aSStephan Aßmus },
749949213aSStephan Aßmus {
759949213aSStephan Aßmus B_STYLED_TEXT_FORMAT,
769949213aSStephan Aßmus B_TRANSLATOR_TEXT,
779949213aSStephan Aßmus STXT_OUT_QUALITY,
789949213aSStephan Aßmus STXT_OUT_CAPABILITY,
799949213aSStephan Aßmus "text/x-vnd.Be-stxt",
809949213aSStephan Aßmus "Be styled text file"
81fa267963SEzo },
82fa267963SEzo {
83fa267963SEzo RTF_TEXT_FORMAT,
84fa267963SEzo B_TRANSLATOR_TEXT,
85fa267963SEzo RTF_OUT_QUALITY,
86fa267963SEzo RTF_OUT_CAPABILITY,
87fa267963SEzo "text/rtf",
88fa267963SEzo "RichTextFormat file"
899949213aSStephan Aßmus }
909949213aSStephan Aßmus };
919949213aSStephan Aßmus
929949213aSStephan Aßmus
RTFTranslator()939949213aSStephan Aßmus RTFTranslator::RTFTranslator()
949949213aSStephan Aßmus {
959949213aSStephan Aßmus char info[256];
9670d59669SSiarzhuk Zharski sprintf(info, B_TRANSLATE("Rich Text Format translator v%d.%d.%d %s"),
9770d59669SSiarzhuk Zharski static_cast<int>(B_TRANSLATION_MAJOR_VERSION(RTF_TRANSLATOR_VERSION)),
9870d59669SSiarzhuk Zharski static_cast<int>(B_TRANSLATION_MINOR_VERSION(RTF_TRANSLATOR_VERSION)),
9970d59669SSiarzhuk Zharski static_cast<int>(B_TRANSLATION_REVISION_VERSION(
10070d59669SSiarzhuk Zharski RTF_TRANSLATOR_VERSION)),
1019949213aSStephan Aßmus __DATE__);
1029949213aSStephan Aßmus
1039949213aSStephan Aßmus fInfo = strdup(info);
1049949213aSStephan Aßmus }
1059949213aSStephan Aßmus
1069949213aSStephan Aßmus
~RTFTranslator()1079949213aSStephan Aßmus RTFTranslator::~RTFTranslator()
1089949213aSStephan Aßmus {
1099949213aSStephan Aßmus free(fInfo);
1109949213aSStephan Aßmus }
1119949213aSStephan Aßmus
1129949213aSStephan Aßmus
1139949213aSStephan Aßmus const char *
TranslatorName() const1149949213aSStephan Aßmus RTFTranslator::TranslatorName() const
1159949213aSStephan Aßmus {
11670d59669SSiarzhuk Zharski return B_TRANSLATE("RTF text files");
1179949213aSStephan Aßmus }
1189949213aSStephan Aßmus
1199949213aSStephan Aßmus
1209949213aSStephan Aßmus const char *
TranslatorInfo() const1219949213aSStephan Aßmus RTFTranslator::TranslatorInfo() const
1229949213aSStephan Aßmus {
123e8eb40f7SHumdinger return B_TRANSLATE("Rich Text Format translator");
1249949213aSStephan Aßmus }
1259949213aSStephan Aßmus
1269949213aSStephan Aßmus
1279949213aSStephan Aßmus int32
TranslatorVersion() const1289949213aSStephan Aßmus RTFTranslator::TranslatorVersion() const
1299949213aSStephan Aßmus {
1309949213aSStephan Aßmus return RTF_TRANSLATOR_VERSION;
1319949213aSStephan Aßmus }
1329949213aSStephan Aßmus
1339949213aSStephan Aßmus
1349949213aSStephan Aßmus const translation_format *
InputFormats(int32 * _outCount) const1359949213aSStephan Aßmus RTFTranslator::InputFormats(int32 *_outCount) const
1369949213aSStephan Aßmus {
1379949213aSStephan Aßmus if (_outCount == NULL)
1389949213aSStephan Aßmus return NULL;
1399949213aSStephan Aßmus
1409949213aSStephan Aßmus *_outCount = sizeof(sInputFormats) / sizeof(translation_format);
1419949213aSStephan Aßmus return sInputFormats;
1429949213aSStephan Aßmus }
1439949213aSStephan Aßmus
1449949213aSStephan Aßmus
1459949213aSStephan Aßmus const translation_format *
OutputFormats(int32 * _outCount) const1469949213aSStephan Aßmus RTFTranslator::OutputFormats(int32 *_outCount) const
1479949213aSStephan Aßmus {
1489949213aSStephan Aßmus *_outCount = sizeof(sOutputFormats) / sizeof(translation_format);
1499949213aSStephan Aßmus return sOutputFormats;
1509949213aSStephan Aßmus }
1519949213aSStephan Aßmus
1529949213aSStephan Aßmus
1539949213aSStephan Aßmus status_t
Identify(BPositionIO * stream,const translation_format * format,BMessage * ioExtension,translator_info * info,uint32 outType)1549949213aSStephan Aßmus RTFTranslator::Identify(BPositionIO *stream,
1559949213aSStephan Aßmus const translation_format *format, BMessage *ioExtension,
1569949213aSStephan Aßmus translator_info *info, uint32 outType)
1579949213aSStephan Aßmus {
1589949213aSStephan Aßmus if (!outType)
1599949213aSStephan Aßmus outType = B_TRANSLATOR_TEXT;
160fa267963SEzo else if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT
161fa267963SEzo && outType != RTF_TEXT_FORMAT)
1629949213aSStephan Aßmus return B_NO_TRANSLATOR;
1639949213aSStephan Aßmus
164fa267963SEzo
1659949213aSStephan Aßmus RTF::Parser parser(*stream);
1669949213aSStephan Aßmus status_t status = parser.Identify();
1679949213aSStephan Aßmus
168fa267963SEzo if (status == B_OK) {
169*06221356SAdrien Destugues // Source data is RTF. We can translate to RTF (no-op), plaintext, or
170*06221356SAdrien Destugues // styled text.
171*06221356SAdrien Destugues
1729949213aSStephan Aßmus // return information about the data in the stream
1739949213aSStephan Aßmus info->type = B_TRANSLATOR_TEXT; //RTF_TEXT_FORMAT;
1749949213aSStephan Aßmus info->group = B_TRANSLATOR_TEXT;
1759949213aSStephan Aßmus info->quality = RTF_IN_QUALITY;
1769949213aSStephan Aßmus info->capability = RTF_IN_CAPABILITY;
177aec33db1SPhilippe Saint-Pierre strlcpy(info->name, B_TRANSLATE("RichTextFormat file"),
1783927bd3cSPhilippe Saint-Pierre sizeof(info->name));
1799949213aSStephan Aßmus strcpy(info->MIME, "text/rtf");
180fa267963SEzo } else {
181*06221356SAdrien Destugues // Not an RTF file. We can only work with it if we are translating to
182*06221356SAdrien Destugues // RTF.
183*06221356SAdrien Destugues if (outType != RTF_TEXT_FORMAT)
184*06221356SAdrien Destugues return B_NO_TRANSLATOR;
185*06221356SAdrien Destugues
186fa267963SEzo stream->Seek(0, SEEK_SET);
187fa267963SEzo TranslatorStyledTextStreamHeader header;
188fa267963SEzo stream->Read(&header, sizeof(header));
189fa267963SEzo swap_data(B_UINT32_TYPE, &header, sizeof(header),
190fa267963SEzo B_SWAP_BENDIAN_TO_HOST);
191fa267963SEzo stream->Seek(0, SEEK_SET);
192fa267963SEzo if (header.header.magic == B_STYLED_TEXT_FORMAT
193fa267963SEzo && header.header.header_size == (int32)sizeof(header)
194fa267963SEzo && header.header.data_size == 0
195fa267963SEzo && header.version == 100) {
196fa267963SEzo info->type = B_STYLED_TEXT_FORMAT;
197fa267963SEzo info->group = B_TRANSLATOR_TEXT;
198fa267963SEzo info->quality = STXT_IN_QUALITY;
199fa267963SEzo info->capability = STXT_IN_CAPABILITY;
200fa267963SEzo strlcpy(info->name, B_TRANSLATE("Be style text file"),
201fa267963SEzo sizeof(info->name));
202fa267963SEzo strcpy(info->MIME, "text/x-vnd.Be-stxt");
203fa267963SEzo } else {
204fa267963SEzo info->type = B_TRANSLATOR_TEXT;
205fa267963SEzo info->group = B_TRANSLATOR_TEXT;
206fa267963SEzo info->quality = TEXT_IN_QUALITY;
207fa267963SEzo info->capability = TEXT_IN_CAPABILITY;
208fa267963SEzo strlcpy(info->name, B_TRANSLATE("Plain text file"),
209fa267963SEzo sizeof(info->name));
210fa267963SEzo strcpy(info->MIME, "text/plain");
211fa267963SEzo }
212fa267963SEzo }
2139949213aSStephan Aßmus return B_OK;
2149949213aSStephan Aßmus }
2159949213aSStephan Aßmus
2169949213aSStephan Aßmus
2179949213aSStephan Aßmus status_t
Translate(BPositionIO * source,const translator_info * inInfo,BMessage * ioExtension,uint32 outType,BPositionIO * target)2189949213aSStephan Aßmus RTFTranslator::Translate(BPositionIO *source,
2199949213aSStephan Aßmus const translator_info *inInfo, BMessage *ioExtension,
2209949213aSStephan Aßmus uint32 outType, BPositionIO *target)
2219949213aSStephan Aßmus {
2229949213aSStephan Aßmus if (target == NULL || source == NULL)
2239949213aSStephan Aßmus return B_BAD_VALUE;
2249949213aSStephan Aßmus
2259949213aSStephan Aßmus if (!outType)
2269949213aSStephan Aßmus outType = B_TRANSLATOR_TEXT;
227fa267963SEzo if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT
228fa267963SEzo && outType != RTF_TEXT_FORMAT)
2299949213aSStephan Aßmus return B_NO_TRANSLATOR;
2309949213aSStephan Aßmus
231fa267963SEzo if (strncmp(inInfo->MIME, "text/rtf", 8) == 0) {
2329949213aSStephan Aßmus RTF::Parser parser(*source);
2339949213aSStephan Aßmus
2349949213aSStephan Aßmus RTF::Header header;
2359949213aSStephan Aßmus status_t status = parser.Parse(header);
2369949213aSStephan Aßmus if (status != B_OK)
2379949213aSStephan Aßmus return status;
2389949213aSStephan Aßmus
2399949213aSStephan Aßmus if (outType == B_TRANSLATOR_TEXT)
2409949213aSStephan Aßmus return convert_to_plain_text(header, *target);
241fa267963SEzo else
2429949213aSStephan Aßmus return convert_to_stxt(header, *target);
243fa267963SEzo
244fa267963SEzo } else if (inInfo->type == B_TRANSLATOR_TEXT) {
245fa267963SEzo return convert_plain_text_to_rtf(*source, *target);
246fa267963SEzo } else if (inInfo->type == B_STYLED_TEXT_FORMAT) {
247fa267963SEzo return convert_styled_text_to_rtf(source, target);
248fa267963SEzo } else
249fa267963SEzo return B_BAD_VALUE;
250fa267963SEzo
2519949213aSStephan Aßmus }
2529949213aSStephan Aßmus
2539949213aSStephan Aßmus
2549949213aSStephan Aßmus status_t
MakeConfigurationView(BMessage * ioExtension,BView ** _view,BRect * _extent)25570d59669SSiarzhuk Zharski RTFTranslator::MakeConfigurationView(BMessage *ioExtension, BView **_view,
25670d59669SSiarzhuk Zharski BRect *_extent)
2579949213aSStephan Aßmus {
2589949213aSStephan Aßmus if (_view == NULL || _extent == NULL)
2599949213aSStephan Aßmus return B_BAD_VALUE;
2609949213aSStephan Aßmus
2619949213aSStephan Aßmus BView *view = new ConfigView(BRect(0, 0, 225, 175));
2629949213aSStephan Aßmus if (view == NULL)
2639949213aSStephan Aßmus return BTranslator::MakeConfigurationView(ioExtension, _view, _extent);
2649949213aSStephan Aßmus
2659949213aSStephan Aßmus *_view = view;
2669949213aSStephan Aßmus *_extent = view->Bounds();
2679949213aSStephan Aßmus return B_OK;
2689949213aSStephan Aßmus }
2699949213aSStephan Aßmus
2709949213aSStephan Aßmus
2719949213aSStephan Aßmus // #pragma mark -
2729949213aSStephan Aßmus
2739949213aSStephan Aßmus
2749949213aSStephan Aßmus BTranslator *
make_nth_translator(int32 n,image_id you,uint32 flags,...)2759949213aSStephan Aßmus make_nth_translator(int32 n, image_id you, uint32 flags, ...)
2769949213aSStephan Aßmus {
2779949213aSStephan Aßmus if (n != 0)
2789949213aSStephan Aßmus return NULL;
2799949213aSStephan Aßmus
2809949213aSStephan Aßmus return new RTFTranslator();
2819949213aSStephan Aßmus }
2829949213aSStephan Aßmus
283