<commit_before>/*
   RTFProducer.j

   Serialize CPAttributedString to a RTF String

   Copyright (C) 2014 <NAME>
   This file is based on the RTFProducer from GNUStep
   (which i co-authored with <NAME> in 1999)

 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

@import <Foundation/CPAttributedString.j>
@import "CPParagraphStyle.j"
@import "CPColor.j"
@import "CPGraphics.j"
@import "CPFontManager.j"

@global CPForegroundColorAttributeName
@global CPBackgroundColorAttributeName
@global CPUnderlineStyleAttributeName
@global CPSuperscriptAttributeName
@global CPBaselineOffsetAttributeName
@global CPAttachmentAttributeName
@global CPLigatureAttributeName
@global CPKernAttributeName

@global CPLeftTextAlignment
@global CPRightTextAlignment
@global CPCenterTextAlignment
@global CPJustifiedTextAlignment
@global CPNaturalTextAlignment

var PAPERSIZE = @"PaperSize",
    LEFTMARGIN = @"LeftMargin",
    RIGHTMARGIN = @"RightMargin",
    TOPMARGIN = @"TopMargin",
    BUTTOMMARGIN = @"ButtomMargin";

function _points2twips(a) { return (a) * 20.0; }

@implementation _CPRTFProducer : CPObject
{
    CPAttributedString  text;
    CPMutableDictionary fontDict;
    CPMutableDictionary colorDict;
    CPDictionary        docDict;
    CPMutableArray      attachments;
    CPFont              currentFont;
    CPColor             fgColor;
    CPColor             bgColor;
    CPColor             ulColor;
}

#pragma mark -
#pragma mark Class methods


+ (CPString)produceRTF:(CPAttributedString)aText documentAttributes:(CPDictionary)dict
{
    var mynew = [self new];

    return [mynew RTFDStringFromAttributedString:aText documentAttributes:dict];
}


#pragma mark -
#pragma mark init methods

- (id)init
{
    if (self = [super init])
    {
        // maintain a dictionary for the used colours
        // (for rtf-header generation)
        colorDict = [CPMutableDictionary new];

        //maintain a dictionary for the used fonts
        //(for rtf-header generation)
        fontDict = [CPMutableDictionary new];

        fgColor = [CPColor blackColor];
        bgColor= [CPColor whiteColor];
    }

    return self;
}

// private stuff follows
- (CPString)fontTable
{
    if (![fontDict count])
        return @"";

    var fontlistString = "",
        fontEnum,
        currFont,
        keyArray;

    keyArray = [fontDict allKeys];
    keyArray = [keyArray sortedArrayUsingSelector:@selector(compare:)];
    fontEnum = [keyArray objectEnumerator];

    while ((currFont = [fontEnum nextObject]) !== nil)
    {
        var fontFamily,
            detail;

        if ([currFont isEqualToString:@"Symbol"])
            fontFamily = @"tech";
        else if ([currFont isEqualToString:@"Helvetica"])
            fontFamily = @"swiss";
        else if ([currFont isEqualToString:@"Arial"])
            fontFamily = @"swiss";
        else if ([currFont isEqualToString:@"Courier"])
            fontFamily = @"modern";
        else if ([currFont isEqualToString:@"Times"])
            fontFamily = @"roman";
        else fontFamily = @"nil";

        detail = [CPString stringWithFormat:@"%@\\f%@ %@;", [fontDict objectForKey:currFont], fontFamily, currFont];
        fontlistString += detail;
    }

    return [CPString stringWithFormat:@"{\\fonttbl%@}\n", fontlistString];
}

- (CPString)colorTable
{
    if (![fontDict count])
        return @"";

    var result,
        count = [colorDict count],
        list = [CPMutableArray arrayWithCapacity:count],
        keyEnum = [colorDict keyEnumerator],
        next,
        i;

    while ((next = [keyEnum nextObject]) != nil)
    {
        var cn = [colorDict objectForKey:next];

        [list insertObject:next atIndex:[cn intValue] - 1];
    }

    result = [CPString stringWithString:@"{\\colortbl;"];

    for (i = 0; i < count; i++)
    {
        var color = [[list objectAtIndex:i]
                           colorUsingColorSpaceName:CPCalibratedRGBColorSpace];

        result += [CPString stringWithFormat:@"\\red%d\\green%d\\blue%d;",
                                             ([color redComponent] * 255),
                                             ([color greenComponent] * 255),
                                             ([color blueComponent] * 255)];
    }

    result += @"}\n";

    return result;
}

- (CPString)documentAttributes
{
    if (!docDict)
        return @"";

    var result,
        detail,
        val,
        num;

    result = [CPString string];

    val = [docDict objectForKey:PAPERSIZE];

    if (val)
    {
        var size = [val sizeValue];

        detail = [CPString stringWithFormat:@"\\paperw%d \\paperh%d",
                         _points2twips(size.width),
                         _points2twips(size.height)];

        result += detail;
    }

    num = [docDict objectForKey:LEFTMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margl%d", _points2twips(f)];
        result += detail;
    }

    num = [docDict objectForKey:RIGHTMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margr%d", _points2twips(f)];
        result += detail;
    }

    num = [docDict objectForKey:TOPMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margt%d", _points2twips(f)];
        result += detail;
    }

    num = [docDict objectForKey:BUTTOMMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margb%d", _points2twips(f)];
        result += detail;
    }

    return result;
}

- (CPString)headerString
{
    var result;

    result = [CPString stringWithString:@"{\\rtf1\\ansi"];
    result += [self fontTable];
    result += [self colorTable];
    result += [self documentAttributes];

    return result;
}

- (CPString)trailerString
{
    return @"}";
}

- (CPString)fontToken:(CPString) fontName
{
    var fCount = [fontDict objectForKey:fontName];

    if (fCount == nil)
    {
        var count = [fontDict count];

        fCount = [CPString stringWithFormat:@"\\f%d", count];
        [fontDict setObject:fCount forKey:fontName];
    }

    return fCount;
}

- (int)numberForColor:(CPColor)color
{
    var cn,
        num = [colorDict objectForKey:color];

    if (num == nil)
    {
        cn = [colorDict count] + 1;
        [colorDict setObject:[CPNumber numberWithInt:cn] forKey:color];
    }

    return [num intValue] + 1;
}

- (CPString)paragraphStyle:(CPParagraphStyle)paraStyle
{
    var headerString = [CPString stringWithString:@"\\pard\\plain"],
        twips;

    if (paraStyle == nil)
        return headerString;<commit_msg>fixed: _RTFProducer was referencing wrong colortbl entries<commit_after>/*
   RTFProducer.j

   Serialize CPAttributedString to a RTF String

   Copyright (C) 2014 <NAME>
   This file is based on the RTFProducer from GNUStep
   (which i co-authored with <NAME> in 1999)

 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

@import <Foundation/CPAttributedString.j>
@import "CPParagraphStyle.j"
@import "CPColor.j"
@import "CPGraphics.j"
@import "CPFontManager.j"

@global CPForegroundColorAttributeName
@global CPBackgroundColorAttributeName
@global CPUnderlineStyleAttributeName
@global CPSuperscriptAttributeName
@global CPBaselineOffsetAttributeName
@global CPAttachmentAttributeName
@global CPLigatureAttributeName
@global CPKernAttributeName

@global CPLeftTextAlignment
@global CPRightTextAlignment
@global CPCenterTextAlignment
@global CPJustifiedTextAlignment
@global CPNaturalTextAlignment

var PAPERSIZE = @"PaperSize",
    LEFTMARGIN = @"LeftMargin",
    RIGHTMARGIN = @"RightMargin",
    TOPMARGIN = @"TopMargin",
    BUTTOMMARGIN = @"ButtomMargin";

function _points2twips(a) { return (a) * 20.0; }

@implementation _CPRTFProducer : CPObject
{
    CPAttributedString  text;
    CPMutableDictionary fontDict;
    CPMutableDictionary colorDict;
    CPDictionary        docDict;
    CPMutableArray      attachments;
    CPFont              currentFont;
    CPColor             fgColor;
    CPColor             bgColor;
    CPColor             ulColor;
}

#pragma mark -
#pragma mark Class methods


+ (CPString)produceRTF:(CPAttributedString)aText documentAttributes:(CPDictionary)dict
{
    var mynew = [self new];

    return [mynew RTFDStringFromAttributedString:aText documentAttributes:dict];
}


#pragma mark -
#pragma mark init methods

- (id)init
{
    if (self = [super init])
    {
        // maintain a dictionary for the used colours
        // (for rtf-header generation)
        colorDict = [CPMutableDictionary new];

        //maintain a dictionary for the used fonts
        //(for rtf-header generation)
        fontDict = [CPMutableDictionary new];

        fgColor = [CPColor blackColor];
        bgColor= [CPColor whiteColor];
    }

    return self;
}

// private stuff follows
- (CPString)fontTable
{
    if (![fontDict count])
        return @"";

    var fontlistString = "",
        fontEnum,
        currFont,
        keyArray;

    keyArray = [fontDict allKeys];
    keyArray = [keyArray sortedArrayUsingSelector:@selector(compare:)];
    fontEnum = [keyArray objectEnumerator];

    while ((currFont = [fontEnum nextObject]) !== nil)
    {
        var fontFamily,
            detail;

        if ([currFont isEqualToString:@"Symbol"])
            fontFamily = @"tech";
        else if ([currFont isEqualToString:@"Helvetica"])
            fontFamily = @"swiss";
        else if ([currFont isEqualToString:@"Arial"])
            fontFamily = @"swiss";
        else if ([currFont isEqualToString:@"Courier"])
            fontFamily = @"modern";
        else if ([currFont isEqualToString:@"Times"])
            fontFamily = @"roman";
        else fontFamily = @"nil";

        detail = [CPString stringWithFormat:@"%@\\f%@ %@;", [fontDict objectForKey:currFont], fontFamily, currFont];
        fontlistString += detail;
    }

    return [CPString stringWithFormat:@"{\\fonttbl%@}\n", fontlistString];
}

- (CPString)colorTable
{
    if (![fontDict count])
        return @"";

    var result,
        count = [colorDict count],
        list = [CPMutableArray arrayWithCapacity:count],
        keyEnum = [colorDict keyEnumerator],
        next,
        i;

    while ((next = [keyEnum nextObject]) != nil)
    {
        var cn = [colorDict objectForKey:next];

        [list insertObject:next atIndex:[cn intValue] - 1];
    }

    result = [CPString stringWithString:@"{\\colortbl;"];

    for (i = 0; i < count; i++)
    {
        var color = [[list objectAtIndex:i]
                           colorUsingColorSpaceName:CPCalibratedRGBColorSpace];

        result += [CPString stringWithFormat:@"\\red%d\\green%d\\blue%d;",
                                             ([color redComponent] * 255),
                                             ([color greenComponent] * 255),
                                             ([color blueComponent] * 255)];
    }

    result += @"}\n";

    return result;
}

- (CPString)documentAttributes
{
    if (!docDict)
        return @"";

    var result,
        detail,
        val,
        num;

    result = [CPString string];

    val = [docDict objectForKey:PAPERSIZE];

    if (val)
    {
        var size = [val sizeValue];

        detail = [CPString stringWithFormat:@"\\paperw%d \\paperh%d",
                         _points2twips(size.width),
                         _points2twips(size.height)];

        result += detail;
    }

    num = [docDict objectForKey:LEFTMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margl%d", _points2twips(f)];
        result += detail;
    }

    num = [docDict objectForKey:RIGHTMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margr%d", _points2twips(f)];
        result += detail;
    }

    num = [docDict objectForKey:TOPMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margt%d", _points2twips(f)];
        result += detail;
    }

    num = [docDict objectForKey:BUTTOMMARGIN];

    if (num)
    {
        var f = [num floatValue];

        detail = [CPString stringWithFormat:@"\\margb%d", _points2twips(f)];
        result += detail;
    }

    return result;
}

- (CPString)headerString
{
    var result;

    result = [CPString stringWithString:@"{\\rtf1\\ansi"];
    result += [self fontTable];
    result += [self colorTable];
    result += [self documentAttributes];

    return result;
}

- (CPString)trailerString
{
    return @"}";
}

- (CPString)fontToken:(CPString) fontName
{
    var fCount = [fontDict objectForKey:fontName];

    if (fCount == nil)
    {
        var count = [fontDict count];

        fCount = [CPString stringWithFormat:@"\\f%d", count];
        [fontDict setObject:fCount forKey:fontName];
    }

    return fCount;
}

- (int)numberForColor:(CPColor)color
{
    var cn,
        num = [colorDict objectForKey:color];

    if (num === nil)
    {
        cn = [colorDict count];
        [colorDict setObject:[CPNumber numberWithInt:cn + 1] forKey:color];
    }
    else
        cn = [num intValue];

    return cn + 1;
}

- (CPString)paragraphStyle:(CPParagraphStyle)paraStyle
{
    var headerString = [CPString stringWithString:@"\\pard\\plain"],
        twips;

    if (paraStyle == nil)
        return headerString;
{'fraction_non_alphanumeric': 0.11117100121277455, 'fraction_numerical': 0.0060638727934240666, 'mean_word_length': 2.5983030303030303, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6181426', 'n_tokens_mistral': 4652, 'n_tokens_neox': 4280, 'n_words': 1166}