diff --git a/src/add-ons/translators/rtf/RTFTranslator.cpp b/src/add-ons/translators/rtf/RTFTranslator.cpp index 1c107c9a4e..6c9d7854ea 100644 --- a/src/add-ons/translators/rtf/RTFTranslator.cpp +++ b/src/add-ons/translators/rtf/RTFTranslator.cpp @@ -21,6 +21,15 @@ #define DATA_BUFFER_SIZE 64 +#define TEXT_IN_QUALITY 0.4 +#define TEXT_IN_CAPABILITY 0.6 + +#define STXT_IN_QUALITY 0.5 +#define STXT_IN_CAPABILITY 0.5 + +#define RTF_OUT_QUALITY RTF_IN_QUALITY +#define RTF_OUT_CAPABILITY RTF_IN_CAPABILITY + // The input formats that this translator supports. static const translation_format sInputFormats[] = { { @@ -30,6 +39,22 @@ static const translation_format sInputFormats[] = { RTF_IN_CAPABILITY, "text/rtf", "RichTextFormat file" + }, + { + B_TRANSLATOR_TEXT, + B_TRANSLATOR_TEXT, + TEXT_IN_QUALITY, + TEXT_IN_CAPABILITY, + "text/plain", + "Plain text file" + }, + { + B_STYLED_TEXT_FORMAT, + B_TRANSLATOR_TEXT, + STXT_IN_QUALITY, + STXT_IN_CAPABILITY, + "text/x-vnd.Be-stxt", + "Be styled text file" } }; @@ -50,6 +75,14 @@ static const translation_format sOutputFormats[] = { STXT_OUT_CAPABILITY, "text/x-vnd.Be-stxt", "Be styled text file" + }, + { + RTF_TEXT_FORMAT, + B_TRANSLATOR_TEXT, + RTF_OUT_QUALITY, + RTF_OUT_CAPABILITY, + "text/rtf", + "RichTextFormat file" } }; @@ -118,27 +151,54 @@ status_t RTFTranslator::Identify(BPositionIO *stream, const translation_format *format, BMessage *ioExtension, translator_info *info, uint32 outType) -{ +{ if (!outType) outType = B_TRANSLATOR_TEXT; - if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT) + else if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT + && outType != RTF_TEXT_FORMAT) return B_NO_TRANSLATOR; + RTF::Parser parser(*stream); - status_t status = parser.Identify(); - if (status != B_OK) - return B_NO_TRANSLATOR; - - // return information about the data in the stream - info->type = B_TRANSLATOR_TEXT; //RTF_TEXT_FORMAT; - info->group = B_TRANSLATOR_TEXT; - info->quality = RTF_IN_QUALITY; - info->capability = RTF_IN_CAPABILITY; - strlcpy(info->name, B_TRANSLATE("RichTextFormat file"), - sizeof(info->name)); - strcpy(info->MIME, "text/rtf"); - + + if (status == B_OK) { + // return information about the data in the stream + info->type = B_TRANSLATOR_TEXT; //RTF_TEXT_FORMAT; + info->group = B_TRANSLATOR_TEXT; + info->quality = RTF_IN_QUALITY; + info->capability = RTF_IN_CAPABILITY; + strlcpy(info->name, B_TRANSLATE("RichTextFormat file"), + sizeof(info->name)); + strcpy(info->MIME, "text/rtf"); + } else { + stream->Seek(0, SEEK_SET); + TranslatorStyledTextStreamHeader header; + stream->Read(&header, sizeof(header)); + swap_data(B_UINT32_TYPE, &header, sizeof(header), + B_SWAP_BENDIAN_TO_HOST); + stream->Seek(0, SEEK_SET); + if (header.header.magic == B_STYLED_TEXT_FORMAT + && header.header.header_size == (int32)sizeof(header) + && header.header.data_size == 0 + && header.version == 100) { + info->type = B_STYLED_TEXT_FORMAT; + info->group = B_TRANSLATOR_TEXT; + info->quality = STXT_IN_QUALITY; + info->capability = STXT_IN_CAPABILITY; + strlcpy(info->name, B_TRANSLATE("Be style text file"), + sizeof(info->name)); + strcpy(info->MIME, "text/x-vnd.Be-stxt"); + } else { + info->type = B_TRANSLATOR_TEXT; + info->group = B_TRANSLATOR_TEXT; + info->quality = TEXT_IN_QUALITY; + info->capability = TEXT_IN_CAPABILITY; + strlcpy(info->name, B_TRANSLATE("Plain text file"), + sizeof(info->name)); + strcpy(info->MIME, "text/plain"); + } + } return B_OK; } @@ -153,22 +213,30 @@ RTFTranslator::Translate(BPositionIO *source, if (!outType) outType = B_TRANSLATOR_TEXT; - if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT) + if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT + && outType != RTF_TEXT_FORMAT) return B_NO_TRANSLATOR; + + if (strncmp(inInfo->MIME, "text/rtf", 8) == 0) { + RTF::Parser parser(*source); - RTF::Parser parser(*source); + RTF::Header header; + status_t status = parser.Parse(header); + if (status != B_OK) + return status; - RTF::Header header; - status_t status = parser.Parse(header); - if (status != B_OK) - return status; - - // we support two different output formats - - if (outType == B_TRANSLATOR_TEXT) - return convert_to_plain_text(header, *target); - - return convert_to_stxt(header, *target); + if (outType == B_TRANSLATOR_TEXT) + return convert_to_plain_text(header, *target); + else + return convert_to_stxt(header, *target); + + } else if (inInfo->type == B_TRANSLATOR_TEXT) { + return convert_plain_text_to_rtf(*source, *target); + } else if (inInfo->type == B_STYLED_TEXT_FORMAT) { + return convert_styled_text_to_rtf(source, target); + } else + return B_BAD_VALUE; + } diff --git a/src/add-ons/translators/rtf/convert.cpp b/src/add-ons/translators/rtf/convert.cpp index f1984764a0..bc8d12f4bd 100644 --- a/src/add-ons/translators/rtf/convert.cpp +++ b/src/add-ons/translators/rtf/convert.cpp @@ -21,7 +21,10 @@ #include #include #include +#include +#include +#define READ_BUFFER_SIZE 2048 struct conversion_context { conversion_context() @@ -645,3 +648,98 @@ convert_to_plain_text(RTF::Header &header, BPositionIO &target) free(flattenedRuns); return B_OK; } + + +status_t convert_styled_text_to_rtf( + BPositionIO* source, BPositionIO* target) +{ + if (source->Seek(0, SEEK_SET) != 0) + return B_ERROR; + + const ssize_t kstxtsize = sizeof(TranslatorStyledTextStreamHeader); + const ssize_t ktxtsize = sizeof(TranslatorStyledTextTextHeader); + TranslatorStyledTextStreamHeader stxtheader; + TranslatorStyledTextTextHeader txtheader; + char buffer[READ_BUFFER_SIZE]; + + if (source->Read(&stxtheader, kstxtsize) != kstxtsize) + return B_ERROR; + if (source->Read(&txtheader, ktxtsize) != ktxtsize) + return B_ERROR; + + + BString plainText; + ssize_t nread = 0, nreed = 0, ntotalread = 0; + nreed = min((size_t)READ_BUFFER_SIZE, + (size_t)txtheader.header.data_size - ntotalread); + nread = source->Read(buffer, nreed); + while (nread > 0) { + plainText << buffer; + + ntotalread += nread; + nreed = min((size_t)READ_BUFFER_SIZE, + (size_t)txtheader.header.data_size - ntotalread); + nread = source->Read(buffer, nreed); + } + if ((ssize_t)txtheader.header.data_size != ntotalread) + return B_NO_TRANSLATOR; + + BString rtfFile = + "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard "; + + rtfFile << plainText << " }"; + target->Write((const void*)rtfFile, rtfFile.Length()); + + + BNode* node = (BNode*)source; + const char* kAttrName = "styles"; + attr_info info; + + if (node->GetAttrInfo(kAttrName, &info) != B_OK + || info.type != B_RAW_TYPE || info.size < 160) + return B_ERROR; + + uint8* flatRunArray = new (std::nothrow) uint8[info.size]; + if (flatRunArray == NULL) + return B_NO_MEMORY; + + if (node->ReadAttr(kAttrName, B_RAW_TYPE, 0, flatRunArray, info.size + != info.size)) + return B_OK; + + //todo: convert stxt attributes to rtf commands + + //text_run_array* styles = (text_run_array*)flatRunArray; + size_t stylesSize = info.size / 3; + + for(uint32 i = 0; i < stylesSize; i++) { + + } + + delete[] flatRunArray; + return B_OK; +} + + +status_t convert_plain_text_to_rtf( + BPositionIO& source, BPositionIO& target) +{ + BString rtfFile = + "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard "; + + BFile* fileSource = (BFile*)&source; + off_t size; + fileSource->GetSize(&size); + char* sourceBuf = (char*)malloc(size); + fileSource->Read((void*)sourceBuf, size); + + BString sourceTxt = sourceBuf; + sourceTxt.CharacterEscape("\\{}", '\\'); + sourceTxt.ReplaceAll("\n", " \\par "); + rtfFile << sourceTxt << " }"; + + BFile* fileTarget = (BFile*)⌖ + fileTarget->Write((const void*)rtfFile, rtfFile.Length()); + + return B_OK; +} diff --git a/src/add-ons/translators/rtf/convert.h b/src/add-ons/translators/rtf/convert.h index 7bce2a9f65..76840572a6 100644 --- a/src/add-ons/translators/rtf/convert.h +++ b/src/add-ons/translators/rtf/convert.h @@ -12,5 +12,9 @@ extern status_t convert_to_stxt(RTF::Header &header, BDataIO &target); extern status_t convert_to_plain_text(RTF::Header &header, BPositionIO &target); - +extern status_t convert_styled_text_to_rtf( + BPositionIO* source, BPositionIO* target); +extern status_t convert_plain_text_to_rtf( + BPositionIO& source, BPositionIO& target); + #endif /* CONVERT_H */