// -*-c++-*-

// fixg2sxd - a utility to convert fig to sxd format

// Copyright (C) 2003-2008 Alexander Bürger, acfb@users.sourceforge.net

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program 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
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "xfigobjects.h"

#include "xmlwrite.h"
#include "misc.h"

#include <iomanip>

// TODO: non-ps fonts?
// TODO: symbol font does not show anything

istream& Text::read( istream& figfile )
{
    int unused_pen_style; // (enumeration , not used)
    TextStyle ts;
    figfile >> ts.justification >> ts.color >> depth >> unused_pen_style
            >> ts.font >> ts.font_size >> angle >> ts.font_flags
            >> height >> length >> x >> y;
    textstyle = textstyles.insert( ts ).first;
    textstyle->stylenumber();

    // read the string characterwise
    char ch;
    figfile.get( ch ); // skip initial space
    while( true ) {
        figfile.get( ch );
        if( ch == '\\' ) {
            figfile.get( ch );
            if( ch != '\\' ) {
                int ch2 = figfile.get();
                int ch3 = figfile.get();
                int value = 64*(ch-'0') + 8*(ch2-'0') + (ch3-'0');
                if( value == 1 )
                    break;
                ch = char(value);
            }
        }
        text += ch;
    }
    return figfile;
}

ostream& Text::write( ostream& out )
{
    // --------- use line to position text -------------
    // extracted from creating text with OOo draw, printing as ps,
    // converting to fig with pstoedit and making linear regression;
    // finally for small fonts, a correction was done
    const float length = 50;
    const float fs = textstyle->font_size;
    const float off = -( 0.23 + 6.63*fs );

    float justify = (textstyle->justification==0) ? 0 :
        ((textstyle->justification==1) ? -length/2.0 : -length);
    float x1 = x  + sin(angle)*off + cos(angle)*justify;
    float y1 = y  + cos(angle)*off - sin(angle)*justify;
    float x2 = x1 + cos(angle)*length;
    float y2 = y1 - sin(angle)*length;
    Node line("draw:line");
    line["draw:layer"] << "layout";
    line["draw:z-index"] << depth2z(depth);
    line["draw:style-name"] << textstyle->stylenumber();
    line["svg:x1"] << tr(x1) << "cm";
    line["svg:y1"] << tr(y1) << "cm";
    line["svg:x2"] << tr(x2) << "cm";
    line["svg:y2"] << tr(y2) << "cm";
    Node& textp=line.subnode("text:p");
    if( textstyle->font/4 == 5 )
        textp["text:style-name"] << "P1";
    ostringstream& txt = textp.text().t();
    unsigned char last=0;
    for( unsigned i=0; i<text.length(); ++i ) {
        unsigned char ch = text[i];
        if( (ch>' '  && ch < 128) || (ch==' '&&last!=' ') ) {
            switch( ch ) {
            case '<':  txt << "&lt;";   break;
            case '>':  txt << "&gt;";   break;
            case '\'': txt << "&apos;"; break;
            case '\"': txt << "&quot;"; break;
            case '&':  txt << "&amp;";  break;
            default:
                txt << text[i];
            }
        } else if( ch == '\n' ) { // line break
            txt << "<text:line-break/>";
        } else if( ch == ' ' ) { // multiple spaces
            unsigned secondspace = i;
            while( i<text.length() && text[i] == ' ' )
                ++i;
            txt << "<text:s text:c=\"" << ( i-secondspace ) << "\"/>";
            if( text[i] != ' ' )
                --i;
        } else if( ch>=' ') {
            txt << "&#" << setw(4) << setfill('0') << unsigned(ch) << ";";
        }
        last = ch;
    }
    return out << line;
}

