Example #1
0
/*
 * Convert Teach Text into formatted text.
 *
 * The text is in the data fork and the formatting is in the resource fork.
 */
int
ReformatTeach::Process(const ReformatHolder* pHolder,
    ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part,
    ReformatOutput* pOutput)
{
    const uint8_t* dataBuf;
    const uint8_t* rsrcBuf;
    long dataLen, rsrcLen;
    const uint8_t* styleBlock;
    long styleLen;

    if (part != ReformatHolder::kPartData)
        return -1;

    dataBuf = pHolder->GetSourceBuf(ReformatHolder::kPartData);
    dataLen = pHolder->GetSourceLen(ReformatHolder::kPartData);
    rsrcBuf = pHolder->GetSourceBuf(ReformatHolder::kPartRsrc);
    rsrcLen = pHolder->GetSourceLen(ReformatHolder::kPartRsrc);
    if (dataBuf == NULL || rsrcBuf == NULL || dataLen <= 0 || rsrcLen <= 0) {
        LOGI("Teach reformatter missing one fork of the file");
        return -1;
    }
    CheckGSCharConv();

    /* find the rStyleBlock */
    if (!ReformatResourceFork::GetResource(rsrcBuf, rsrcLen, 0x8012, 0x0001,
        &styleBlock, &styleLen))
    {
        LOGI("Resource fork of Teach Text file not found");
        return -1;
    }

    RStyleBlock rStyleBlock;
    if (!rStyleBlock.Create(styleBlock, styleLen)) {
        LOGI("Unable to unpack rStyleBlock");
        return -1;
    }

    fUseRTF = true;
    RTFBegin();

    /*
     * Configure ruler options.  The format allows us to have more than one
     * ruler, but doesn't provide a way to select between them, so we have
     * to assume that the first ruler is global.
     *
     * In practice, the Teach application doesn't provide a way to set
     * margins or tab stops, so there's really not much to do.  It seems to
     * create tab stops with 64-pixel widths, which translates to 10 tab
     * stops per page.  WordPad seems to default to 12, so I figure there's
     * not much point in futzing with it since the fonts are all different
     * anyway.
     */
    RStyleBlock::TERuler* pRuler = rStyleBlock.GetRuler(0);
    assert(pRuler != NULL);
    if (pRuler->GetJustification() != RStyleBlock::TERuler::kJustLeft) {
        LOGI("WARNING: not using left justified Teach text");
        /* ignore it */
    }

    for (int style = 0; style < rStyleBlock.GetNumStyleItems(); style++) {
        RStyleBlock::StyleItem* pStyleItem;
        RStyleBlock::TEStyle* pStyle;
        int numBytes;

        /* set up the style */
        pStyleItem = rStyleBlock.GetStyleItem(style);
        assert(pStyleItem != NULL);
        if (pStyleItem->GetLength() == RStyleBlock::StyleItem::kUnusedItem)
            continue;
        numBytes = pStyleItem->GetLength();
        pStyle = rStyleBlock.GetStyle(pStyleItem->GetStyleIndex());

        /*
         * Set the font first; that defines the point size multiplier.  Set
         * the size second, because the point size determines whether we
         * show underline.  Set the style last.
         */
        RTFSetGSFont(pStyle->GetFontFamily());
        RTFSetGSFontSize(pStyle->GetFontSize());
        RTFSetGSFontStyle(pStyle->GetTextStyle());

        /*
         * The Teach app doesn't let you set text colors, but it appears
         * there's a way to do it, since the SpyHunterGS Read.Me file has
         * a bit of red in it.
         */
        if (pStyle->GetTextColor() != 0) {
            // do something with color, someday
        }

        /* output the characters */
        uint8_t uch;
        while (numBytes--) {
            if (!dataLen) {
                LOGI("WARNING: Teach underrun (%ld wanted)", numBytes);
                break;
            }
            uch = *dataBuf;
            if (uch == '\r') {
                RTFNewPara();
            } else if (uch == '\t') {
                RTFTab();
            } else {
                RTFPrintExtChar(ConvertGSChar(uch));
            }
            dataBuf++;
            dataLen--;
        }
    }
    if (dataLen) {
        LOGI("WARNING: Teach overrun (%ld remain)", dataLen);
        /* no big deal */
    }


    RTFEnd();

    SetResultBuffer(pOutput, true);
    return 0;
}
Example #2
0
/*
 * Print one paragraph.
 *
 * Stop when we hit '\r'.  We watch "maxLen" just to be safe.
 *
 * Returns the #of bytes consumed.
 */
int ReformatAWGS_WP::PrintParagraph(const uint8_t* ptr, long maxLen)
{
    const uint8_t* startPtr = ptr;
    uint16_t firstFont;
    uint8_t firstStyle, firstSize, firstColor;
    uint8_t uch;

    if (maxLen < 7) {
        LOGI("AWGS_WP GLITCH: not enough storage for para header (%d)",
            maxLen);
        return 1;   // don't return zero or we might loop forever
    }
    /* pull out the paragraph header */
    firstFont = Get16LE(ptr);
    firstStyle = *(ptr + 2);
    firstSize = *(ptr + 3);
    firstColor = *(ptr + 4);

    ptr += 7;
    maxLen -= 7;

    /*
     * Set the font first; that defines the point size multiplier.  Set
     * the size second, because the point size determines whether we
     * show underline.  Set the style last.
     */
    //LOGI("+++ Para start: font=0x%04x size=%d style=0x%02x",
    //  firstFont, firstSize, firstStyle);
    RTFSetGSFont(firstFont);
    RTFSetGSFontSize(firstSize);
    RTFSetGSFontStyle(firstStyle);

    while (maxLen > 0) {
        uch = *ptr++;
        maxLen--;
        switch (uch) {
        case 0x01:      // font change - two bytes follow
            if (maxLen >= 2) {
                RTFSetGSFont(Get16LE(ptr));
                ptr += 2;
                maxLen -= 2;
            }
            break;
        case 0x02:      // text style change
            if (maxLen >= 1) {
                RTFSetGSFontStyle(*ptr++);
                maxLen--;
            }
            break;
        case 0x03:      // text size change
            if (maxLen >= 1) {
                RTFSetGSFontSize(*ptr++);
                maxLen--;
            }
            break;
        case 0x04:      // color change (0-15)
            if (maxLen >= 1) {
                ptr++;
                maxLen--;
            }
            break;
        case 0x05:      // page token (replace with page #)
        case 0x06:      // date token (replace with date)
        case 0x07:      // time token (replace with time)
            RTFSetColor(kColorMediumBlue);
            if (uch == 0x05)
                BufPrintf("<page>");
            else if (uch == 0x06)
                BufPrintf("<date>");
            else
                BufPrintf("<time>");
            RTFSetColor(kColorNone);
            break;
        case '\r':
            RTFNewPara();
            return ptr - startPtr;
        case '\t':
            RTFTab();
            break;
        default:
            RTFPrintUTF16Char(Charset::ConvertMacRomanToUTF16(uch));
            break;
        }
    }

    LOGI("AWGS_WP: WARNING: ran out of data before hitting '\r'");
    return ptr - startPtr;
}