1 /*****************************************************************************/ 2 // STXTTranslator 3 // Written by Michael Wilber, OBOS Translation Kit Team 4 // 5 // STXTTranslator.cpp 6 // 7 // This BTranslator based object is for opening and writing 8 // StyledEdit (STXT) files. 9 // 10 // 11 // Copyright (c) 2002 OpenBeOS Project 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a 14 // copy of this software and associated documentation files (the "Software"), 15 // to deal in the Software without restriction, including without limitation 16 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 // and/or sell copies of the Software, and to permit persons to whom the 18 // Software is furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included 21 // in all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 // DEALINGS IN THE SOFTWARE. 30 /*****************************************************************************/ 31 32 #include <string.h> 33 #include <stdio.h> 34 #include "STXTTranslator.h" 35 #include "STXTView.h" 36 37 #define READ_BUFFER_SIZE 2048 38 #define DATA_BUFFER_SIZE 256 39 40 // The input formats that this translator supports. 41 translation_format gInputFormats[] = { 42 { 43 B_TRANSLATOR_TEXT, 44 B_TRANSLATOR_TEXT, 45 TEXT_IN_QUALITY, 46 TEXT_IN_CAPABILITY, 47 "text/plain", 48 "Plain text file" 49 }, 50 { 51 B_STYLED_TEXT_FORMAT, 52 B_TRANSLATOR_TEXT, 53 STXT_IN_QUALITY, 54 STXT_IN_CAPABILITY, 55 "text/x-vnd.Be-stxt", 56 "Be styled text file" 57 } 58 }; 59 60 // The output formats that this translator supports. 61 translation_format gOutputFormats[] = { 62 { 63 B_TRANSLATOR_TEXT, 64 B_TRANSLATOR_TEXT, 65 TEXT_OUT_QUALITY, 66 TEXT_OUT_CAPABILITY, 67 "text/plain", 68 "Plain text file" 69 }, 70 { 71 B_STYLED_TEXT_FORMAT, 72 B_TRANSLATOR_TEXT, 73 STXT_OUT_QUALITY, 74 STXT_OUT_CAPABILITY, 75 "text/x-vnd.Be-stxt", 76 "Be styled text file" 77 } 78 }; 79 80 // Default settings for the Translator 81 TranSetting gDefaultSettings[] = { 82 {B_TRANSLATOR_EXT_HEADER_ONLY, TRAN_SETTING_BOOL, false}, 83 {B_TRANSLATOR_EXT_DATA_ONLY, TRAN_SETTING_BOOL, false} 84 }; 85 86 // --------------------------------------------------------------- 87 // make_nth_translator 88 // 89 // Creates a STXTTranslator object to be used by BTranslatorRoster 90 // 91 // Preconditions: 92 // 93 // Parameters: n, The translator to return. Since 94 // STXTTranslator only publishes one 95 // translator, it only returns a 96 // STXTTranslator if n == 0 97 // 98 // you, The image_id of the add-on that 99 // contains code (not used). 100 // 101 // flags, Has no meaning yet, should be 0. 102 // 103 // Postconditions: 104 // 105 // Returns: NULL if n is not zero, 106 // a new STXTTranslator if n is zero 107 // --------------------------------------------------------------- 108 BTranslator * 109 make_nth_translator(int32 n, image_id you, uint32 flags, ...) 110 { 111 if (!n) 112 return new STXTTranslator(); 113 else 114 return NULL; 115 } 116 117 // --------------------------------------------------------------- 118 // Constructor 119 // 120 // Sets up the version info and the name of the translator so that 121 // these values can be returned when they are requested. 122 // 123 // Preconditions: 124 // 125 // Parameters: 126 // 127 // Postconditions: 128 // 129 // Returns: 130 // --------------------------------------------------------------- 131 STXTTranslator::STXTTranslator() 132 : BaseTranslator("StyledEdit Files", "StyledEdit files translator", 133 STXT_TRANSLATOR_VERSION, 134 gInputFormats, sizeof(gInputFormats) / sizeof(translation_format), 135 gOutputFormats, sizeof(gOutputFormats) / sizeof(translation_format), 136 "STXTTranslator_Settings", 137 gDefaultSettings, sizeof(gDefaultSettings) / sizeof(TranSetting), 138 B_TRANSLATOR_TEXT, B_STYLED_TEXT_FORMAT) 139 { 140 } 141 142 // --------------------------------------------------------------- 143 // Destructor 144 // 145 // Does nothing 146 // 147 // Preconditions: 148 // 149 // Parameters: 150 // 151 // Postconditions: 152 // 153 // Returns: 154 // --------------------------------------------------------------- 155 STXTTranslator::~STXTTranslator() 156 { 157 } 158 159 // --------------------------------------------------------------- 160 // identify_stxt_header 161 // 162 // Determines if the data in inSource is of the STXT format. 163 // 164 // Preconditions: 165 // 166 // Parameters: header, the STXT stream header read in by 167 // Identify() or Translate() 168 // 169 // inSource, The stream with the STXT data 170 // 171 // outInfo, information about the type of data 172 // from inSource is stored here 173 // 174 // outType, the desired output type for the 175 // data in inSource 176 // 177 // ptxtheader if this is not NULL, the TEXT 178 // header from inSource is copied 179 // to it 180 // 181 // Postconditions: 182 // 183 // Returns: B_OK, if the data appears to be in the STXT format, 184 // B_NO_TRANSLATOR, if the data is not in the STXT format or 185 // returns B_ERROR if errors were encountered in trying to 186 // determine the format, or another error code if there was an 187 // error calling BPostionIO::Read() 188 // --------------------------------------------------------------- 189 status_t 190 identify_stxt_header(const TranslatorStyledTextStreamHeader &header, 191 BPositionIO *inSource, translator_info *outInfo, uint32 outType, 192 TranslatorStyledTextTextHeader *ptxtheader = NULL) 193 { 194 const ssize_t ktxtsize = sizeof(TranslatorStyledTextTextHeader); 195 const ssize_t kstylsize = sizeof(TranslatorStyledTextStyleHeader); 196 197 uint8 buffer[max(ktxtsize, kstylsize)]; 198 199 // Check the TEXT header 200 TranslatorStyledTextTextHeader txtheader; 201 if (inSource->Read(buffer, ktxtsize) != ktxtsize) 202 return B_NO_TRANSLATOR; 203 204 memcpy(&txtheader, buffer, ktxtsize); 205 if (swap_data(B_UINT32_TYPE, &txtheader, ktxtsize, 206 B_SWAP_BENDIAN_TO_HOST) != B_OK) 207 return B_ERROR; 208 209 if (txtheader.header.magic != 'TEXT' 210 || txtheader.header.header_size != sizeof(TranslatorStyledTextTextHeader) 211 || txtheader.charset != B_UNICODE_UTF8) 212 return B_NO_TRANSLATOR; 213 214 // skip the text data 215 off_t seekresult, pos; 216 pos = header.header.header_size + txtheader.header.header_size 217 + txtheader.header.data_size; 218 seekresult = inSource->Seek(txtheader.header.data_size, 219 SEEK_CUR); 220 if (seekresult < pos) 221 return B_NO_TRANSLATOR; 222 if (seekresult > pos) 223 return B_ERROR; 224 225 // check the STYL header (not all STXT files have this) 226 ssize_t read = 0; 227 TranslatorStyledTextStyleHeader stylheader; 228 read = inSource->Read(buffer, kstylsize); 229 if (read < 0) 230 return read; 231 if (read != kstylsize && read != 0) 232 return B_NO_TRANSLATOR; 233 234 // If there is a STYL header 235 if (read == kstylsize) { 236 memcpy(&stylheader, buffer, kstylsize); 237 if (swap_data(B_UINT32_TYPE, &stylheader, kstylsize, 238 B_SWAP_BENDIAN_TO_HOST) != B_OK) 239 return B_ERROR; 240 241 if (stylheader.header.magic != 'STYL' 242 || stylheader.header.header_size != 243 sizeof(TranslatorStyledTextStyleHeader)) 244 return B_NO_TRANSLATOR; 245 } 246 247 // if output TEXT header is supplied, fill it with data 248 if (ptxtheader) { 249 ptxtheader->header.magic = txtheader.header.magic; 250 ptxtheader->header.header_size = txtheader.header.header_size; 251 ptxtheader->header.data_size = txtheader.header.data_size; 252 ptxtheader->charset = txtheader.charset; 253 } 254 255 // return information about the data in the stream 256 outInfo->type = B_STYLED_TEXT_FORMAT; 257 outInfo->group = B_TRANSLATOR_TEXT; 258 outInfo->quality = STXT_IN_QUALITY; 259 outInfo->capability = STXT_IN_CAPABILITY; 260 strcpy(outInfo->name, "Be styled text file"); 261 strcpy(outInfo->MIME, "text/x-vnd.Be-stxt"); 262 263 return B_OK; 264 } 265 266 267 static bool 268 valid_utf8_char(const uint8* bytes, size_t& length) 269 { 270 length = 1; 271 272 if (bytes[0] & 0x80) { 273 if (bytes[0] & 0x40) { 274 if (bytes[0] & 0x20) { 275 if (bytes[0] & 0x10) { 276 if (bytes[0] & 0x08) { 277 // A five byte char?! 278 return false; 279 } 280 281 // A four byte char 282 length = 4; 283 return true; 284 } 285 286 /* A three byte char */ 287 length = 3; 288 return true; 289 } 290 291 /* A two byte char */ 292 length = 2; 293 return true; 294 } 295 296 return false; 297 } 298 299 if (bytes[0] == 0) 300 return false; 301 302 return true; 303 } 304 305 306 // --------------------------------------------------------------- 307 // identify_txt_header 308 // 309 // Determines if the data in inSource is of the UTF8 plain 310 // text format. 311 // 312 // Preconditions: data must point to a buffer at least 313 // DATA_BUFFER_SIZE bytes long 314 // 315 // Parameters: data, buffer containing data already read 316 // from the stream 317 // 318 // nread, number of bytes that have already 319 // been read from the stream 320 // 321 // header, the STXT stream header read in by 322 // Identify() or Translate() 323 // 324 // inSource, The stream with the STXT data 325 // 326 // outInfo, information about the type of data 327 // from inSource is stored here 328 // 329 // outType the desired output type for the 330 // data in inSource 331 // 332 // 333 // Postconditions: 334 // 335 // Returns: B_OK, if the data appears to be in the STXT format, 336 // B_NO_TRANSLATOR, if the data is not in the STXT format or 337 // returns B_ERROR if errors were encountered in trying to 338 // determine the format 339 // --------------------------------------------------------------- 340 status_t 341 identify_txt_header(uint8 *data, int32 bytesRead, 342 BPositionIO *inSource, translator_info *outInfo, uint32 outType) 343 { 344 ssize_t readLater = inSource->Read(data + bytesRead, DATA_BUFFER_SIZE - bytesRead); 345 if (readLater < 0) 346 return B_NO_TRANSLATOR; 347 348 bytesRead += readLater; 349 float capability = TEXT_IN_CAPABILITY; 350 int32 bad = 0; 351 352 // TODO: use the same mechanism as the TextSnifferAddon class in the registrar 353 // and add support for indicating other character sets as well 354 for (int32 i = 0; i < bytesRead; i++) { 355 uint8 c = data[i]; 356 size_t length; 357 358 // if any null characters or control characters 359 // are found, reduce our ability to handle the data 360 if (c < 0x20 361 && c != 0x08 // backspace 362 && c != 0x09 // tab 363 && c != 0x0A // line feed 364 && c != 0x0C // form feed 365 && c != 0x0D) { // carriage return 366 bad++; 367 } else if ((c & 0x80) != 0 && valid_utf8_char(data + i, length)) { 368 int32 j = 1; 369 for (; j < (int32)length && i + j < bytesRead; j++) { 370 if ((data[i + j] & 0xc0) != 0x80) { 371 bad++; 372 break; 373 } 374 } 375 376 i += j - 1; 377 } else if (c & 0x80) 378 bad++; 379 } 380 381 // TODO: enable me once bug #675 is fixed 382 #if 0 383 // if more than 1/3 of the characters are bad, we don't accept the text 384 if (bad > bytesRead / 3) 385 return B_NO_TRANSLATOR; 386 #endif 387 388 capability *= (bytesRead - bad) / (float)bytesRead; 389 390 // return information about the data in the stream 391 outInfo->type = B_TRANSLATOR_TEXT; 392 outInfo->group = B_TRANSLATOR_TEXT; 393 outInfo->quality = TEXT_IN_QUALITY; 394 outInfo->capability = capability; 395 strcpy(outInfo->name, "Plain text file"); 396 strcpy(outInfo->MIME, "text/plain"); 397 398 return B_OK; 399 } 400 401 // --------------------------------------------------------------- 402 // Identify 403 // 404 // Examines the data from inSource and determines if it is in a 405 // format that this translator knows how to work with. 406 // 407 // Preconditions: 408 // 409 // Parameters: inSource, where the data to examine is 410 // 411 // inFormat, a hint about the data in inSource, 412 // it is ignored since it is only a hint 413 // 414 // ioExtension, configuration settings for the 415 // translator (not used) 416 // 417 // outInfo, information about what data is in 418 // inSource and how well this translator 419 // can handle that data is stored here 420 // 421 // outType, The format that the user wants 422 // the data in inSource to be 423 // converted to 424 // 425 // Postconditions: 426 // 427 // Returns: B_NO_TRANSLATOR, if this translator can't handle 428 // the data in inSource 429 // 430 // B_ERROR, if there was an error converting the data to the host 431 // format 432 // 433 // B_BAD_VALUE, if the settings in ioExtension are bad 434 // 435 // B_OK, if this translator understand the data and there were 436 // no errors found 437 // 438 // Other errors if BPositionIO::Read() returned an error value 439 // --------------------------------------------------------------- 440 status_t 441 STXTTranslator::Identify(BPositionIO *inSource, 442 const translation_format *inFormat, BMessage *ioExtension, 443 translator_info *outInfo, uint32 outType) 444 { 445 if (!outType) 446 outType = B_TRANSLATOR_TEXT; 447 if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT) 448 return B_NO_TRANSLATOR; 449 450 const ssize_t kstxtsize = sizeof(TranslatorStyledTextStreamHeader); 451 452 uint8 buffer[DATA_BUFFER_SIZE]; 453 status_t nread = 0; 454 // Read in the header to determine 455 // if the data is supported 456 nread = inSource->Read(buffer, kstxtsize); 457 if (nread < 0) 458 return nread; 459 460 // read in enough data to fill the stream header 461 if (nread == kstxtsize) { 462 TranslatorStyledTextStreamHeader header; 463 memcpy(&header, buffer, kstxtsize); 464 if (swap_data(B_UINT32_TYPE, &header, kstxtsize, 465 B_SWAP_BENDIAN_TO_HOST) != B_OK) 466 return B_ERROR; 467 468 if (header.header.magic == B_STYLED_TEXT_FORMAT 469 && header.header.header_size == (int32)kstxtsize 470 && header.header.data_size == 0 471 && header.version == 100) 472 return identify_stxt_header(header, inSource, outInfo, outType); 473 } 474 475 // if the data is not styled text, check if it is plain text 476 return identify_txt_header(buffer, nread, inSource, outInfo, outType); 477 } 478 479 // --------------------------------------------------------------- 480 // translate_from_stxt 481 // 482 // Translates the data in inSource to the type outType and stores 483 // the translated data in outDestination. 484 // 485 // Preconditions: 486 // 487 // Parameters: inSource, the data to be translated 488 // 489 // outDestination, where the translated data is 490 // put 491 // 492 // outType, the type to convert inSource to 493 // 494 // txtheader, the TEXT header from inSource 495 // 496 // 497 // Postconditions: 498 // 499 // Returns: B_BAD_VALUE, if outType is invalid 500 // 501 // B_NO_TRANSLATOR, if this translator doesn't understand the data 502 // 503 // B_ERROR, if there was an error allocating memory or converting 504 // data 505 // 506 // B_OK, if all went well 507 // --------------------------------------------------------------- 508 status_t 509 translate_from_stxt(BPositionIO *inSource, BPositionIO *outDestination, 510 uint32 outType, const TranslatorStyledTextTextHeader &txtheader) 511 { 512 if (inSource->Seek(0, SEEK_SET) != 0) 513 return B_ERROR; 514 515 const ssize_t kstxtsize = sizeof(TranslatorStyledTextStreamHeader); 516 const ssize_t ktxtsize = sizeof(TranslatorStyledTextTextHeader); 517 518 bool btoplain; 519 if (outType == B_TRANSLATOR_TEXT) 520 btoplain = true; 521 else if (outType == B_STYLED_TEXT_FORMAT) 522 btoplain = false; 523 else 524 return B_BAD_VALUE; 525 526 uint8 buffer[READ_BUFFER_SIZE]; 527 ssize_t nread = 0, nwritten = 0, nreed = 0, ntotalread = 0; 528 529 // skip to the actual text data when outputting a 530 // plain text file 531 if (btoplain) { 532 if (inSource->Seek(kstxtsize + ktxtsize, SEEK_CUR) != 533 kstxtsize + ktxtsize) 534 return B_ERROR; 535 } 536 537 // Read data from inSource 538 // When outputing B_TRANSLATOR_TEXT, the loop stops when all of 539 // the text data has been read and written. 540 // When outputting B_STYLED_TEXT_FORMAT, the loop stops when all 541 // of the data from inSource has been read and written. 542 if (btoplain) 543 nreed = min(READ_BUFFER_SIZE, 544 txtheader.header.data_size - ntotalread); 545 else 546 nreed = READ_BUFFER_SIZE; 547 nread = inSource->Read(buffer, nreed); 548 while (nread > 0) { 549 nwritten = outDestination->Write(buffer, nread); 550 if (nwritten != nread) 551 return B_ERROR; 552 553 if (btoplain) { 554 ntotalread += nread; 555 nreed = min(READ_BUFFER_SIZE, 556 txtheader.header.data_size - ntotalread); 557 } else 558 nreed = READ_BUFFER_SIZE; 559 nread = inSource->Read(buffer, nreed); 560 } 561 562 if (btoplain && static_cast<ssize_t>(txtheader.header.data_size) != 563 ntotalread) 564 // If not all of the text data was able to be read... 565 return B_NO_TRANSLATOR; 566 else 567 return B_OK; 568 } 569 570 // --------------------------------------------------------------- 571 // output_headers 572 // 573 // Outputs the Stream and Text headers from the B_STYLED_TEXT_FORMAT 574 // to outDestination, setting the data_size member of the text header 575 // to text_data_size 576 // 577 // Preconditions: 578 // 579 // Parameters: outDestination, where the translated data is 580 // put 581 // 582 // text_data_size, number of bytes in data section 583 // of the TEXT header 584 // 585 // 586 // Postconditions: 587 // 588 // Returns: 589 // 590 // B_ERROR, if there was an error writing to outDestination or 591 // an error with converting the byte order 592 // 593 // B_OK, if all went well 594 // --------------------------------------------------------------- 595 status_t 596 output_headers(BPositionIO *outDestination, uint32 text_data_size) 597 { 598 const int32 kHeadersSize = sizeof(TranslatorStyledTextStreamHeader) + 599 sizeof(TranslatorStyledTextTextHeader); 600 status_t result; 601 TranslatorStyledTextStreamHeader stxtheader; 602 TranslatorStyledTextTextHeader txtheader; 603 604 uint8 buffer[kHeadersSize]; 605 606 stxtheader.header.magic = 'STXT'; 607 stxtheader.header.header_size = sizeof(TranslatorStyledTextStreamHeader); 608 stxtheader.header.data_size = 0; 609 stxtheader.version = 100; 610 memcpy(buffer, &stxtheader, stxtheader.header.header_size); 611 612 txtheader.header.magic = 'TEXT'; 613 txtheader.header.header_size = sizeof(TranslatorStyledTextTextHeader); 614 txtheader.header.data_size = text_data_size; 615 txtheader.charset = B_UNICODE_UTF8; 616 memcpy(buffer + stxtheader.header.header_size, &txtheader, 617 txtheader.header.header_size); 618 619 // write out headers in Big Endian byte order 620 result = swap_data(B_UINT32_TYPE, buffer, kHeadersSize, 621 B_SWAP_HOST_TO_BENDIAN); 622 if (result == B_OK) { 623 ssize_t nwritten = 0; 624 nwritten = outDestination->Write(buffer, kHeadersSize); 625 if (nwritten != kHeadersSize) 626 return B_ERROR; 627 else 628 return B_OK; 629 } 630 631 return result; 632 } 633 634 // --------------------------------------------------------------- 635 // output_styles 636 // 637 // Writes out the actual style information into outDestination 638 // using the data from pflatRunArray 639 // 640 // Preconditions: 641 // 642 // Parameters: outDestination, where the translated data is 643 // put 644 // 645 // text_size, size in bytes of the text in 646 // outDestination 647 // 648 // data_size, size of pflatRunArray 649 // 650 // Postconditions: 651 // 652 // Returns: 653 // 654 // B_ERROR, if there was an error writing to outDestination or 655 // an error with converting the byte order 656 // 657 // B_OK, if all went well 658 // --------------------------------------------------------------- 659 status_t 660 output_styles(BPositionIO *outDestination, uint32 text_size, 661 uint8 *pflatRunArray, ssize_t data_size) 662 { 663 const ssize_t kstylsize = sizeof(TranslatorStyledTextStyleHeader); 664 665 uint8 buffer[kstylsize]; 666 667 // output STYL header 668 TranslatorStyledTextStyleHeader stylheader; 669 stylheader.header.magic = 'STYL'; 670 stylheader.header.header_size = 671 sizeof(TranslatorStyledTextStyleHeader); 672 stylheader.header.data_size = data_size; 673 stylheader.apply_offset = 0; 674 stylheader.apply_length = text_size; 675 676 memcpy(buffer, &stylheader, kstylsize); 677 if (swap_data(B_UINT32_TYPE, buffer, kstylsize, 678 B_SWAP_HOST_TO_BENDIAN) != B_OK) 679 return B_ERROR; 680 if (outDestination->Write(buffer, kstylsize) != kstylsize) 681 return B_ERROR; 682 683 // output actual style information 684 if (outDestination->Write(pflatRunArray, 685 data_size) != data_size) 686 return B_ERROR; 687 688 return B_OK; 689 } 690 691 // --------------------------------------------------------------- 692 // translate_from_text 693 // 694 // Convert the plain text (UTF8) from inSource to plain or 695 // styled text in outDestination 696 // 697 // Preconditions: 698 // 699 // Parameters: inSource, the data to be translated 700 // 701 // outDestination, where the translated data is 702 // put 703 // 704 // outType, the type to convert inSource to 705 // 706 // Postconditions: 707 // 708 // Returns: B_BAD_VALUE, if outType is not supported 709 // 710 // B_NO_MEMORY, if couldn't allocate enough memory to read in 711 // the styled text run array 712 // 713 // B_NO_TRANSLATOR, if this translator doesn't understand the data 714 // 715 // B_ERROR, if there was an error reading or writing data or 716 // converting data 717 // 718 // B_OK, if all went well 719 // --------------------------------------------------------------- 720 status_t 721 translate_from_text(BPositionIO *inSource, BPositionIO *outDestination, 722 uint32 outType) 723 { 724 // find the length of the text 725 off_t size = 0; 726 size = inSource->Seek(0, SEEK_END); 727 if (size < 0) 728 return B_ERROR; 729 730 if (inSource->Seek(0, SEEK_SET) != 0) 731 return B_ERROR; 732 733 bool btoplain; 734 if (outType == B_TRANSLATOR_TEXT) 735 btoplain = true; 736 else if (outType == B_STYLED_TEXT_FORMAT) 737 btoplain = false; 738 else 739 return B_BAD_VALUE; 740 741 // output styled text headers if outputting 742 // in the B_STYLED_TEXT_FORMAT 743 if (!btoplain) { 744 status_t headresult; 745 headresult = output_headers(outDestination, 746 static_cast<uint32>(size)); 747 if (headresult != B_OK) 748 return headresult; 749 } 750 751 uint8 buffer[READ_BUFFER_SIZE]; 752 ssize_t nread = 0, nwritten = 0; 753 754 // output the actual text part of the data 755 nread = inSource->Read(buffer, READ_BUFFER_SIZE); 756 while (nread > 0) { 757 nwritten = outDestination->Write(buffer, nread); 758 if (nwritten != nread) 759 return B_ERROR; 760 761 nread = inSource->Read(buffer, READ_BUFFER_SIZE); 762 } 763 764 // Read file attributes if outputting styled data 765 // and inSource is a BFile object 766 status_t result = B_OK; 767 if (!btoplain) { 768 BFile *pfile = NULL; 769 pfile = dynamic_cast<BFile *>(inSource); 770 if (pfile) { 771 const char *kAttrName = "styles"; 772 attr_info info; 773 if (pfile->GetAttrInfo(kAttrName, &info) == B_OK) { 774 if (info.type != B_RAW_TYPE) 775 return B_NO_TRANSLATOR; 776 if (info.size < 160) 777 return B_NO_TRANSLATOR; 778 779 uint8 *pflatRunArray = new uint8[info.size]; 780 if (pflatRunArray) { 781 ssize_t amtread = pfile->ReadAttr(kAttrName, 782 B_RAW_TYPE, 0, pflatRunArray, info.size); 783 784 // write style data 785 if (amtread == info.size) { 786 result = output_styles(outDestination, 787 size, pflatRunArray, info.size); 788 } else 789 result = B_ERROR; 790 791 delete[] pflatRunArray; 792 pflatRunArray = NULL; 793 794 } else 795 result = B_NO_MEMORY; 796 } 797 } 798 } 799 800 return result; 801 } 802 803 // --------------------------------------------------------------- 804 // Translate 805 // 806 // Translates the data in inSource to the type outType and stores 807 // the translated data in outDestination. 808 // 809 // Preconditions: 810 // 811 // Parameters: inSource, the data to be translated 812 // 813 // inInfo, hint about the data in inSource (not used) 814 // 815 // ioExtension, configuration options for the 816 // translator 817 // 818 // outType, the type to convert inSource to 819 // 820 // outDestination, where the translated data is 821 // put 822 // 823 // Postconditions: 824 // 825 // Returns: B_BAD_VALUE, if the options in ioExtension are bad 826 // 827 // B_NO_TRANSLATOR, if this translator doesn't understand the data 828 // 829 // B_ERROR, if there was an error allocating memory or converting 830 // data 831 // 832 // B_OK, if all went well 833 // --------------------------------------------------------------- 834 status_t 835 STXTTranslator::Translate(BPositionIO *inSource, 836 const translator_info *inInfo, BMessage *ioExtension, 837 uint32 outType, BPositionIO *outDestination) 838 { 839 if (!outType) 840 outType = B_TRANSLATOR_TEXT; 841 if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT) 842 return B_NO_TRANSLATOR; 843 844 const ssize_t kstxtsize = sizeof(TranslatorStyledTextStreamHeader); 845 uint8 buffer[DATA_BUFFER_SIZE]; 846 status_t nread = 0, result; 847 translator_info outInfo; 848 // Read in the header to determine 849 // if the data is supported 850 nread = inSource->Read(buffer, kstxtsize); 851 if (nread < 0) 852 return nread; 853 854 // read in enough data to fill the stream header 855 if (nread == kstxtsize) { 856 TranslatorStyledTextStreamHeader header; 857 memcpy(&header, buffer, kstxtsize); 858 if (swap_data(B_UINT32_TYPE, &header, kstxtsize, 859 B_SWAP_BENDIAN_TO_HOST) != B_OK) 860 return B_ERROR; 861 862 if (header.header.magic == B_STYLED_TEXT_FORMAT && 863 header.header.header_size == 864 sizeof(TranslatorStyledTextStreamHeader) && 865 header.header.data_size == 0 && 866 header.version == 100) { 867 868 TranslatorStyledTextTextHeader txtheader; 869 result = identify_stxt_header(header, inSource, &outInfo, outType, 870 &txtheader); 871 return translate_from_stxt(inSource, outDestination, outType, 872 txtheader); 873 } 874 } 875 876 // if the data is not styled text, check if it is ASCII text 877 result = identify_txt_header(buffer, nread, inSource, &outInfo, outType); 878 if (result == B_OK) 879 return translate_from_text(inSource, outDestination, outType); 880 else 881 return result; 882 } 883 884 BView * 885 STXTTranslator::NewConfigView(TranslatorSettings *settings) 886 { 887 return new STXTView(BRect(0, 0, 225, 175), "STXTTranslator Settings", 888 B_FOLLOW_ALL, B_WILL_DRAW, settings); 889 } 890 891