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 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 107 RTFTranslator::~RTFTranslator() 108 { 109 free(fInfo); 110 } 111 112 113 const char * 114 RTFTranslator::TranslatorName() const 115 { 116 return B_TRANSLATE("RTF text files"); 117 } 118 119 120 const char * 121 RTFTranslator::TranslatorInfo() const 122 { 123 return B_TRANSLATE("Rich Text Format translator"); 124 } 125 126 127 int32 128 RTFTranslator::TranslatorVersion() const 129 { 130 return RTF_TRANSLATOR_VERSION; 131 } 132 133 134 const translation_format * 135 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 * 146 RTFTranslator::OutputFormats(int32 *_outCount) const 147 { 148 *_outCount = sizeof(sOutputFormats) / sizeof(translation_format); 149 return sOutputFormats; 150 } 151 152 153 status_t 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 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 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 * 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