/* This file is part of the KDE project Copyright (C) 2001 David Faure This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KWTextParag.h" #include "KWDocument.h" #include "KWAnchor.h" #include "KWTextImage.h" #include "KWTextFrameSet.h" #include "KWVariable.h" #include "KWLoadingInfo.h" #include #include #include #include #include #include #include #include #include //#define DEBUG_FORMATTING #undef S_NONE // Solaris defines it in sys/signal.h // Called by KoTextParag::drawParagString - all params are in pixel coordinates void KWTextParag::drawFormattingChars( TQPainter &painter, int start, int len, int lastY_pix, int baseLine_pix, int h_pix, // in pixels bool drawSelections, KoTextFormat *lastFormat, const TQMemArray &selectionStarts, const TQMemArray &selectionEnds, const TQColorGroup &cg, bool rightToLeft, int line, KoTextZoomHandler* zh, int whichFormattingChars ) { KWTextFrameSet * textfs = kwTextDocument()->textFrameSet(); if ( !textfs ) return; KWDocument * doc = textfs->kWordDocument(); if ( !doc || !doc->viewFormattingChars() ) return; // We set whichFormattingChars before calling KoTextFormat::drawFormattingChars whichFormattingChars = 0; if ( doc->viewFormattingSpace() ) whichFormattingChars |= FormattingSpace; if ( doc->viewFormattingBreak() ) whichFormattingChars |= FormattingBreak; if ( doc->viewFormattingEndParag() ) whichFormattingChars |= FormattingEndParag; if ( doc->viewFormattingTabs() ) whichFormattingChars |= FormattingTabs; if ( !whichFormattingChars ) return; if ( start + len == length() && (whichFormattingChars & FormattingBreak) && hardFrameBreakAfter() ) { painter.save(); TQPen pen( TDEGlobalSettings::linkColor() ); // #101820 painter.setPen( pen ); //kdDebug() << "KWTextParag::drawFormattingChars start=" << start << " len=" << len << " length=" << length() << endl; // keep in sync with KWTextFrameSet::formatVertically TQString str = i18n( "--- Frame Break ---" ); int width = 0; //width = lastFormat->screenStringWidth( zh, str ); width = lastFormat->screenFontMetrics( zh ).width( str ); TQColorGroup cg2( cg ); //cg2.setColor( TQColorGroup::Base, TQt::green ); // for debug int last = length() - 1; KoTextStringChar &ch = string()->at( last ); int x = zh->layoutUnitToPixelX( ch.x );// + ch.pixelxadj; KoTextFormat format( *lastFormat ); format.setColor( pen.color() ); // ### A bit slow, maybe pass the color to drawParagStringInternal ? KoTextParag::drawParagStringInternal( painter, str, 0, str.length(), x, lastY_pix, // startX and lastY zh->layoutUnitToPixelY( ch.ascent() ), // baseline width, zh->layoutUnitToPixelY( ch.height() ), // bw and h drawSelections, &format, selectionStarts, selectionEnds, cg2, rightToLeft, line, zh, false ); // Clear 'paint end of line' flag, we don't want it overwriting the above whichFormattingChars &= ~FormattingEndParag; painter.restore(); } KoTextParag::drawFormattingChars( painter, start, len, lastY_pix, baseLine_pix, h_pix, drawSelections, lastFormat, selectionStarts, selectionEnds, cg, rightToLeft, line, zh, whichFormattingChars ); } void KWTextParag::setPageBreaking( int pb ) { m_layout.pageBreaking = pb; invalidate(0); if ( next() && ( pb & KoParagLayout::HardFrameBreakAfter ) ) next()->invalidate(0); } KWTextDocument * KWTextParag::kwTextDocument() const { return static_cast( document() ); } //static TQDomElement KWTextParag::saveFormat( TQDomDocument & doc, KoTextFormat * curFormat, KoTextFormat * refFormat, int pos, int len ) { //kdDebug() << "KWTextParag::saveFormat refFormat=" << ( refFormat ? refFormat->key() : "none" ) // << " curFormat=" << curFormat->key() // << " pos=" << pos << " len=" << len << endl; TQDomElement formatElem = doc.createElement( "FORMAT" ); formatElem.setAttribute( "id", 1 ); // text format if ( len ) // 0 when saving the format of a style { formatElem.setAttribute( "pos", pos ); formatElem.setAttribute( "len", len ); } TQDomElement elem; if( !refFormat || curFormat->font().weight() != refFormat->font().weight() ) { elem = doc.createElement( "WEIGHT" ); formatElem.appendChild( elem ); elem.setAttribute( "value", curFormat->font().weight() ); } if( !refFormat || curFormat->color() != refFormat->color() ) { if ( curFormat->color().isValid() ) { elem = doc.createElement( "COLOR" ); formatElem.appendChild( elem ); elem.setAttribute( "red", curFormat->color().red() ); elem.setAttribute( "green", curFormat->color().green() ); elem.setAttribute( "blue", curFormat->color().blue() ); } else { if ( refFormat ) { elem = doc.createElement( "COLOR" ); formatElem.appendChild( elem ); elem.setAttribute( "red", -1 ); elem.setAttribute( "green", -1 ); elem.setAttribute( "blue", -1 ); } } } if( !refFormat || curFormat->font().family() != refFormat->font().family() ) { elem = doc.createElement( "FONT" ); formatElem.appendChild( elem ); elem.setAttribute( "name", curFormat->font().family() ); } if( !refFormat || curFormat->pointSize() != refFormat->pointSize() ) { elem = doc.createElement( "SIZE" ); formatElem.appendChild( elem ); elem.setAttribute( "value", curFormat->pointSize() ); } if( !refFormat || curFormat->font().italic() != refFormat->font().italic() ) { elem = doc.createElement( "ITALIC" ); formatElem.appendChild( elem ); elem.setAttribute( "value", static_cast(curFormat->font().italic()) ); } if( !refFormat || curFormat->underlineType() != refFormat->underlineType() || curFormat->textUnderlineColor() !=refFormat->textUnderlineColor() || curFormat->underlineStyle() !=refFormat->underlineStyle() || curFormat->wordByWord() != refFormat->wordByWord()) { elem = doc.createElement( "UNDERLINE" ); formatElem.appendChild( elem ); if ( curFormat->doubleUnderline() ) elem.setAttribute( "value", "double" ); else if ( curFormat->underlineType() == KoTextFormat::U_SIMPLE_BOLD) elem.setAttribute( "value", "single-bold" ); else if( curFormat->underlineType()==KoTextFormat::U_WAVE) elem.setAttribute( "value", "wave" ); else elem.setAttribute( "value", static_cast(curFormat->underline()) ); TQString strLineType=KoTextFormat::underlineStyleToString( curFormat->underlineStyle() ); elem.setAttribute( "styleline", strLineType ); if ( curFormat->textUnderlineColor().isValid() ) elem.setAttribute( "underlinecolor", curFormat->textUnderlineColor().name() ); elem.setAttribute( "wordbyword" , static_cast(curFormat->wordByWord())); } if( !refFormat || curFormat->strikeOutType() != refFormat->strikeOutType() || curFormat->strikeOutStyle()!= refFormat->strikeOutStyle() || curFormat->wordByWord() != refFormat->wordByWord()) { elem = doc.createElement( "STRIKEOUT" ); formatElem.appendChild( elem ); if ( curFormat->doubleStrikeOut() ) elem.setAttribute( "value", "double" ); else if ( curFormat->strikeOutType() == KoTextFormat::S_SIMPLE_BOLD) elem.setAttribute( "value", "single-bold" ); else elem.setAttribute( "value", static_cast(curFormat->strikeOut()) ); TQString strLineType=KoTextFormat::strikeOutStyleToString( curFormat->strikeOutStyle() ); elem.setAttribute( "styleline", strLineType ); elem.setAttribute( "wordbyword" , static_cast(curFormat->wordByWord())); } if( !refFormat || (curFormat->vAlign() != refFormat->vAlign()) || (curFormat->relativeTextSize() != refFormat->relativeTextSize())) { elem = doc.createElement( "VERTALIGN" ); formatElem.appendChild( elem ); elem.setAttribute( "value", static_cast(curFormat->vAlign()) ); if ( curFormat->relativeTextSize()!=0.66) elem.setAttribute( "relativetextsize", curFormat->relativeTextSize() ); } if( !refFormat || curFormat->textBackgroundColor() != refFormat->textBackgroundColor() ) { if ( curFormat->textBackgroundColor().isValid()) { elem = doc.createElement( "TEXTBACKGROUNDCOLOR" ); formatElem.appendChild( elem ); elem.setAttribute( "red", curFormat->textBackgroundColor().red() ); elem.setAttribute( "green", curFormat->textBackgroundColor().green() ); elem.setAttribute( "blue", curFormat->textBackgroundColor().blue() ); } else { if ( refFormat ) { elem = doc.createElement( "TEXTBACKGROUNDCOLOR" ); formatElem.appendChild( elem ); elem.setAttribute( "red", -1 ); elem.setAttribute( "green", -1 ); elem.setAttribute( "blue", -1 ); } } } if( !refFormat || ( curFormat->shadowDistanceX() != refFormat->shadowDistanceX() || ( curFormat->shadowDistanceY() != refFormat->shadowDistanceY() ) || ( curFormat->shadowColor() != refFormat->shadowColor() ) ) ) { elem = doc.createElement( "SHADOW" ); formatElem.appendChild( elem ); elem.setAttribute( "text-shadow", curFormat->shadowAsCss() ); } if( !refFormat || curFormat->offsetFromBaseLine() != refFormat->offsetFromBaseLine()) { elem = doc.createElement( "OFFSETFROMBASELINE" ); formatElem.appendChild( elem ); elem.setAttribute( "value", curFormat->offsetFromBaseLine() ); } if( !refFormat || curFormat->attributeFont() != refFormat->attributeFont()) { elem = doc.createElement( "FONTATTRIBUTE" ); formatElem.appendChild( elem ); elem.setAttribute( "value", KoTextFormat::attributeFontToString(curFormat->attributeFont()) ); } if( !refFormat || curFormat->language() != refFormat->language()) { elem = doc.createElement( "LANGUAGE" ); formatElem.appendChild( elem ); elem.setAttribute( "value", curFormat->language() ); } return formatElem; } void KWTextParag::save( TQDomElement &parentElem, bool saveAnchorsFramesets ) { // The TQMAX below ensures that although we don't save the trailing space // in the normal case, we do save it for empty paragraphs (#30336) save( parentElem, 0, TQMAX( 0, length()-2 ), saveAnchorsFramesets ); } void KWTextParag::save( TQDomElement &parentElem, int from /* default 0 */, int to /* default length()-2 */, bool saveAnchorsFramesets /* default false */ ) { TQDomDocument doc = parentElem.ownerDocument(); TQDomElement paragElem = doc.createElement( "PARAGRAPH" ); parentElem.appendChild( paragElem ); TQDomElement textElem = doc.createElement( "TEXT" ); textElem.setAttribute("xml:space", "preserve"); paragElem.appendChild( textElem ); if ( partOfTableOfContents() ) paragElem.setAttribute( "toc", "true" ); TQString text = string()->toString(); Q_ASSERT( text.right(1)[0] == ' ' ); textElem.appendChild( doc.createTextNode( text.mid( from, to - from + 1 ) ) ); TQDomElement formatsElem = doc.createElement( "FORMATS" ); int startPos = -1; int index = 0; // Usually same as 'i' but if from>0, 'i' indexes the parag's text and this one indexes the output KoTextFormat *curFormat = paragraphFormat(); for ( int i = from; i <= to; ++i, ++index ) { KoTextStringChar & ch = string()->at(i); KoTextFormat * newFormat = static_cast( ch.format() ); if ( ch.isCustom() ) { if ( startPos > -1 && curFormat) { // Save former format TQDomElement formatElem = saveFormat( doc, curFormat, paragraphFormat(), startPos, index-startPos ); if ( !formatElem.firstChild().isNull() ) // Don't save an empty format tag formatsElem.appendChild( formatElem ); } TQDomElement formatElem = saveFormat( doc, newFormat, paragraphFormat(), index, 1 ); formatsElem.appendChild( formatElem ); KoTextCustomItem* customItem = ch.customItem(); formatElem.setAttribute( "id", customItem->typeId() ); customItem->save( formatElem ); startPos = -1; curFormat = paragraphFormat(); // Save the contents of the frameset inside the anchor // This is NOT used when saving, but it is used when copying an inline frame if ( saveAnchorsFramesets ) { KWFrameSet* inlineFs = 0L; if ( dynamic_cast( customItem ) ) inlineFs = static_cast( customItem )->frameSet(); else if ( dynamic_cast( customItem ) ) inlineFs = static_cast( customItem )->frameSet(); if ( inlineFs ) { // Save inline framesets at the toplevel. Necessary when copying a textframeset that // itself includes an inline frameset - we want all frameset tags at the toplevel. TQDomElement elem = doc.documentElement(); kdDebug() << " saving into " << elem.tagName() << endl; inlineFs->toXML( elem ); } } } else { if ( newFormat != curFormat ) { // Format changed. if ( startPos > -1 && curFormat) { // Save former format TQDomElement formatElem = saveFormat( doc, curFormat, paragraphFormat(), startPos, index-startPos ); if ( !formatElem.firstChild().isNull() ) // Don't save an empty format tag formatsElem.appendChild( formatElem ); } // Format different from paragraph's format ? if( newFormat != paragFormat() ) { startPos = index; curFormat = newFormat; } else { startPos = -1; curFormat = paragraphFormat(); } } } } if ( startPos > -1 && index > startPos && curFormat) { // Save last format TQDomElement formatElem = saveFormat( doc, curFormat, paragraphFormat(), startPos, index-startPos ); if ( !formatElem.firstChild().isNull() ) // Don't save an empty format tag formatsElem.appendChild( formatElem ); } if (!formatsElem.firstChild().isNull()) // Do we have formats to save ? paragElem.appendChild( formatsElem ); TQDomElement layoutElem = doc.createElement( "LAYOUT" ); paragElem.appendChild( layoutElem ); // save with the real alignment (left or right, not auto) m_layout.saveParagLayout( layoutElem, resolveAlignment() ); // Paragraph's format // ## Maybe we should have a "default format" somewhere and // pass it instead of 0L, to only save the non-default attributes // But this would break all export filters again. TQDomElement paragFormatElement = saveFormat( doc, paragraphFormat(), 0L, 0, to - from + 1 ); layoutElem.appendChild( paragFormatElement ); } //static KoTextFormat KWTextParag::loadFormat( TQDomElement &formatElem, KoTextFormat * refFormat, const TQFont & defaultFont, const TQString & defaultLanguage, bool hyphanation ) { KoTextFormat format; //todo fixme !!!!!!!!!!!! format.setHyphenation( hyphanation ); TQFont font; if ( refFormat ) { format = *refFormat; format.setCollection( 0 ); // Out of collection copy font = format.font(); } else { font = defaultFont; } TQDomElement elem; elem = formatElem.namedItem( "FONT" ).toElement(); if ( !elem.isNull() ) { font.setFamily( elem.attribute("name") ); } else if ( !refFormat ) { // No reference format and no FONT tag -> use default font font = defaultFont; } elem = formatElem.namedItem( "WEIGHT" ).toElement(); if ( !elem.isNull() ) font.setWeight( elem.attribute( "value" ).toInt() ); elem = formatElem.namedItem( "SIZE" ).toElement(); if ( !elem.isNull() ) font.setPointSize( elem.attribute("value").toInt() ); elem = formatElem.namedItem( "ITALIC" ).toElement(); if ( !elem.isNull() ) font.setItalic( elem.attribute("value").toInt() == 1 ); elem = formatElem.namedItem( "UNDERLINE" ).toElement(); if ( !elem.isNull() ) { TQString value = elem.attribute("value"); if ( value == "0" || value == "1" ) format.setUnderlineType( (value.toInt() == 1)?KoTextFormat::U_SIMPLE: KoTextFormat::U_NONE ); else if ( value == "single" ) // value never used when saving, but why not support it? ;) format.setUnderlineType ( KoTextFormat::U_SIMPLE); else if ( value == "double" ) format.setUnderlineType ( KoTextFormat::U_DOUBLE); else if ( value == "single-bold" ) format.setUnderlineType ( KoTextFormat::U_SIMPLE_BOLD); else if( value =="wave") format.setUnderlineType ( KoTextFormat::U_WAVE); if ( elem.hasAttribute("styleline" )) { TQString strLineType = elem.attribute("styleline"); format.setUnderlineStyle( KoTextFormat::stringToUnderlineStyle( strLineType )); } if ( elem.hasAttribute("underlinecolor")) { TQColor col( TQColor(elem.attribute("underlinecolor"))); format.setTextUnderlineColor( col ); } if ( elem.hasAttribute( "wordbyword" )) format.setWordByWord( elem.attribute("wordbyword").toInt()==1); } elem = formatElem.namedItem( "STRIKEOUT" ).toElement(); if ( !elem.isNull() ) { TQString value = elem.attribute("value"); if ( value == "0" || value == "1" ) format.setStrikeOutType( (value.toInt() == 1)?KoTextFormat::S_SIMPLE: KoTextFormat::S_NONE ); else if ( value == "single" ) // value never used when saving, but why not support it? ;) format.setStrikeOutType ( KoTextFormat::S_SIMPLE); else if ( value == "double" ) format.setStrikeOutType ( KoTextFormat::S_DOUBLE); else if ( value =="single-bold" ) format.setStrikeOutType ( KoTextFormat::S_SIMPLE_BOLD); if ( elem.hasAttribute("styleline" )) { TQString strLineType = elem.attribute("styleline"); format.setStrikeOutStyle( KoTextFormat::stringToStrikeOutStyle( strLineType )); } if ( elem.hasAttribute( "wordbyword" )) format.setWordByWord( elem.attribute("wordbyword").toInt()==1); } // ######## Not needed in 3.0? /* elem = formatElem.namedItem( "CHARSET" ).toElement(); if ( !elem.isNull() ) font.setCharSet( (TQFont::CharSet) elem.attribute("value").toInt() ); */ format.setFont( font ); elem = formatElem.namedItem( "VERTALIGN" ).toElement(); if ( !elem.isNull() ) { format.setVAlign( static_cast( elem.attribute("value").toInt() ) ); if (elem.hasAttribute("relativetextsize")) format.setRelativeTextSize(elem.attribute("relativetextsize").toDouble()); } elem = formatElem.namedItem( "COLOR" ).toElement(); if ( !elem.isNull() ) { int red = elem.attribute("red").toInt(); int green = elem.attribute("green").toInt(); int blue = elem.attribute("blue").toInt(); if ( red == -1 && blue == -1 && green == -1 ) format.setColor( TQColor() ); else format.setColor( TQColor(red,green,blue) ); } elem = formatElem.namedItem( "TEXTBACKGROUNDCOLOR" ).toElement(); if ( !elem.isNull() ) { int red = elem.attribute("red").toInt(); int green = elem.attribute("green").toInt(); int blue = elem.attribute("blue").toInt(); if ( red == -1 && blue == -1 && green == -1 ) format.setTextBackgroundColor( TQColor() ); else format.setTextBackgroundColor( TQColor(red,green,blue) ); } elem = formatElem.namedItem( "SHADOW" ).toElement(); if ( !elem.isNull() ) { format.parseShadowFromCss( elem.attribute( "text-shadow" ) ); } else { // Compat with koffice-1.2 elem = formatElem.namedItem( "SHADOWTEXT" ).toElement(); if ( !elem.isNull() && elem.attribute("value").toInt() && KoParagLayout::shadowCssCompat ) { // Retrieve shadow attributes from KoParagLayout // We don't have its pointer, so shadowCssCompat is static. format.parseShadowFromCss( *KoParagLayout::shadowCssCompat ); } } elem = formatElem.namedItem( "OFFSETFROMBASELINE" ).toElement(); if ( !elem.isNull() ) format.setOffsetFromBaseLine( elem.attribute("value").toInt()); elem = formatElem.namedItem( "FONTATTRIBUTE" ).toElement(); if ( !elem.isNull() ) format.setAttributeFont( KoTextFormat::stringToAttributeFont(elem.attribute("value"))); elem = formatElem.namedItem( "LANGUAGE" ).toElement(); if ( !elem.isNull() ) format.setLanguage( elem.attribute("value") ); else if ( !refFormat )// No reference format and no LANGUAGE tag -> use default font format.setLanguage( defaultLanguage ); //kdDebug() << "KWTextParag::loadFormat format=" << format.key() << endl; return format; } void KWTextParag::loadLayout( TQDomElement & attributes ) { TQDomElement layout = attributes.namedItem( "LAYOUT" ).toElement(); if ( !layout.isNull() ) { KWDocument * doc = kwTextDocument()->textFrameSet()->kWordDocument(); KoParagLayout paragLayout = loadParagLayout( layout, doc, true ); setParagLayout( paragLayout ); // Load default format from style. KoTextFormat *defaultFormat = style() ? &style()->format() : 0L; TQDomElement formatElem = layout.namedItem( "FORMAT" ).toElement(); if ( !formatElem.isNull() ) { // Load paragraph format KoTextFormat f = loadFormat( formatElem, defaultFormat, doc->defaultFont(), doc->globalLanguage(), doc->globalHyphenation() ); setFormat( document()->formatCollection()->format( &f ) ); } else // No paragraph format { if ( defaultFormat ) // -> use the one from the style setFormat( document()->formatCollection()->format( defaultFormat ) ); } } else { // Even the simplest import filter should do kdWarning(32001) << "No LAYOUT tag in PARAGRAPH, dunno what layout to apply" << endl; } } void KWTextParag::load( TQDomElement &attributes ) { loadLayout( attributes ); // Set the text after setting the paragraph format - so that the format applies TQDomElement element = attributes.namedItem( "TEXT" ).toElement(); if ( !element.isNull() ) { //kdDebug() << "KWTextParag::load '" << element.text() << "'" << endl; append( element.text() ); // Apply default format - this should be automatic !! setFormat( 0, string()->length(), paragFormat(), TRUE ); } if ( attributes.attribute( "toc" ) == "true" ) setPartOfTableOfContents( true ); loadFormatting( attributes ); setChanged( true ); invalidate( 0 ); } void KWTextParag::loadFormatting( TQDomElement &attributes, int offset, bool loadFootNote ) { TQValueList removeLenList; TQValueList removePosList; KWDocument * doc = kwTextDocument()->textFrameSet()->kWordDocument(); TQDomElement formatsElem = attributes.namedItem( "FORMATS" ).toElement(); if ( !formatsElem.isNull() ) { TQDomElement formatElem = formatsElem.firstChild().toElement(); for ( ; !formatElem.isNull() ; formatElem = formatElem.nextSibling().toElement() ) { if ( formatElem.tagName() == "FORMAT" ) { int index = formatElem.attribute( "pos" ).toInt() + offset; int len = formatElem.attribute( "len" ).toInt(); int id = formatElem.attribute( "id" ).toInt(); switch( id ) { case 1: // Normal text { KoTextFormat f = loadFormat( formatElem, paragraphFormat(), doc->defaultFont(),doc->globalLanguage(), doc->globalHyphenation() ); //kdDebug(32002) << "KWTextParag::loadFormatting applying formatting from " << index << " to " << index+len << endl; setFormat( index, len, document()->formatCollection()->format( &f ) ); break; } case 2: // Picture { len = 1; // it was missing from old 1.0 files // The character matching this format is probably a TQChar(1) // However, as it is an invalid XML character, we must replace it // or it will be written out while save the file. KoTextStringChar& ch = string()->at(index); if (ch.c.unicode()==1) { kdDebug() << "Replacing TQChar(1) (in KWTextParag::loadFormatting)" << endl; ch.c='#'; } KWTextImage * custom = new KWTextImage( kwTextDocument(), TQString() ); kdDebug() << "KWTextParag::loadFormatting insertCustomItem" << endl; paragFormat()->addRef(); setCustomItem( index, custom, paragFormat() ); custom->load( formatElem ); break; } case 3: // Tabulator { len = 1; // it was missing from old 1.0 files // We have to replace the # or TQChar(1) by a tabulator KoTextStringChar& ch = string()->at(index); ch.c='\t'; // I assume that we need the same treatment as for id == 1 KoTextFormat f = loadFormat( formatElem, paragraphFormat(), doc->defaultFont(),doc->globalLanguage(), doc->globalHyphenation() ); //kdDebug(32002) << "KWTextParag::loadFormatting applying formatting from " << index << " to " << index+len << endl; setFormat( index, len, document()->formatCollection()->format( &f ) ); break; } case 4: // Variable { TQDomElement varElem = formatElem.namedItem( "VARIABLE" ).toElement(); bool oldDoc = false; if ( varElem.isNull() ) { // Not found, must be an old document -> the tags were directly // under the FORMAT tag. varElem = formatElem; oldDoc = true; } TQDomElement typeElem = varElem.namedItem( "TYPE" ).toElement(); if ( typeElem.isNull() ) kdWarning(32001) << ( oldDoc ? "No in with id=4, for a variable [old document assumed] !" : "No found in tag!" ) << endl; else { int type = typeElem.attribute( "type" ).toInt(); TQString key = typeElem.attribute( "key" ); kdDebug() << "KWTextParag::loadFormatting variable type=" << type << " key=" << key << endl; KoVariableFormat * varFormat = key.isEmpty() ? 0 : doc->variableFormatCollection()->format( key.latin1() ); // If varFormat is 0 (no key specified), the default format will be used. int correct = 0; if (typeElem.hasAttribute( "correct" )) correct = typeElem.attribute("correct").toInt(); KoVariable * var =doc->variableCollection()->createVariable( type, -1, doc->variableFormatCollection(), varFormat,kwTextDocument(),doc, correct, true , loadFootNote); if ( var ) { var->load( varElem ); KoTextFormat f = loadFormat( formatElem, paragraphFormat(), doc->defaultFont(),doc->globalLanguage(), doc->globalHyphenation() ); setCustomItem( index, var, document()->formatCollection()->format( &f ) ); } if(len>1) { removePosList.append(index+1); removeLenList.append(len-1); } } break; } case 6: // Anchor { Q_ASSERT( len == 1 ); TQDomElement anchorElem = formatElem.namedItem( "ANCHOR" ).toElement(); if ( !anchorElem.isNull() ) { TQString type = anchorElem.attribute( "type" ); if ( type == "grpMgr" /* old syntax */ || type == "frameset" ) { TQString framesetName = anchorElem.attribute( "instance" ); KWAnchorPosition pos; pos.textfs = kwTextDocument()->textFrameSet(); pos.paragId = paragId(); pos.index = index; doc->addAnchorRequest( framesetName, pos ); } else kdWarning() << "Anchor type not supported: " << type << endl; } else kdWarning() << "Missing ANCHOR tag" << endl; break; } default: kdWarning() << "KWTextParag::loadFormatting id=" << id << " not supported" << endl; break; } } } } for(unsigned int i=0; i < removeLenList.count(); i++) { remove(*removePosList.at(i), *removeLenList.at(i)); } } void KWTextParag::setParagLayout( const KoParagLayout & layout, int flags, int marginIndex ) { KoTextParag::setParagLayout( layout, flags, marginIndex ); if ( flags & KoParagLayout::PageBreaking ) setPageBreaking( layout.pageBreaking ); } ////////// // Create a KoParagLayout from XML. KoParagLayout KWTextParag::loadParagLayout( TQDomElement & parentElem, KWDocument *doc, bool findStyle ) { KoParagLayout layout; // Only when loading paragraphs, not when loading styles if ( findStyle ) { KoParagStyle *style; // Name of the style. If there is no style, then we do not supply // any default! TQDomElement element = parentElem.namedItem( "NAME" ).toElement(); if ( !element.isNull() ) { TQString styleName = element.attribute( "value" ); style = doc->styleCollection()->findStyle( styleName ); if (!style) { kdError(32001) << "Cannot find style \"" << styleName << "\" specified in paragraph LAYOUT - using Standard" << endl; style = doc->styleCollection()->findStyle( "Standard" ); } //else kdDebug() << "KoParagLayout::KoParagLayout setting style to " << style << " " << style->name() << endl; } else { kdError(32001) << "Missing NAME tag in paragraph LAYOUT - using Standard" << endl; style = doc->styleCollection()->findStyle( "Standard" ); } Q_ASSERT(style); layout.style = style; } KoParagLayout::loadParagLayout( layout, parentElem, doc->syntaxVersion() ); return layout; } void KWTextParag::join( KoTextParag *parag ) { m_layout.pageBreaking &= ~(KoParagLayout::HardFrameBreakBefore|KoParagLayout::HardFrameBreakAfter); KoTextParag::join( parag ); } void KWTextParag::loadOasis( const TQDomElement& paragElement, KoOasisContext& context, KoStyleCollection *styleCollection, uint& pos ) { KoTextParag::loadOasis( paragElement, context, styleCollection, pos ); KWTextFrameSet* textfs = kwTextDocument()->textFrameSet(); if ( textfs->isMainFrameset() && textfs->kWordDocument()->isLoading() /*not during copy/paste*/ ) { KWDocument * doc = textfs->kWordDocument(); TQString& currentMasterPageRef = doc->loadingInfo()->m_currentMasterPage; const TQString styleName = paragElement.attributeNS( KoXmlNS::text, "style-name", TQString() ); if ( !styleName.isEmpty() ) { const TQDomElement* paragraphStyle = context.oasisStyles().findStyle( styleName, "paragraph" ); TQString masterPageName = paragraphStyle ? paragraphStyle->attributeNS( KoXmlNS::style, "master-page-name", TQString() ) : TQString(); // In KWord we don't support sections so the first paragraph is the one that determines the page layout. if ( prev() == 0 ) { if ( masterPageName.isEmpty() ) masterPageName = "Standard"; // Seems to be a builtin name for the default layout... currentMasterPageRef = masterPageName; // do this first to avoid recursion context.styleStack().save(); context.styleStack().setTypeProperties( "paragraph" ); context.addStyles( paragraphStyle, "paragraph" ); // This is quite ugly... OOo stores the starting page-number in the first paragraph style... TQString pageNumber = context.styleStack().attributeNS( KoXmlNS::style, "page-number" ); if ( !pageNumber.isEmpty() ) doc->variableCollection()->variableSetting()->setStartingPageNumber( pageNumber.toInt() ); context.styleStack().restore(); doc->loadOasisPageLayout( masterPageName, context ); // page layout } else if ( !masterPageName.isEmpty() // empty means no change && masterPageName != currentMasterPageRef ) { // Detected a change in the master page -> this means we have to use a new page layout // and insert a frame break if not on the first paragraph. kdDebug(32001) << "KWTextParag::loadOasis: change of master page detected: from " << currentMasterPageRef << " to " << masterPageName << " -> inserting page break" << endl; currentMasterPageRef = masterPageName; // [see also KoParagLayout for the 'normal' way to insert page breaks] m_layout.pageBreaking |= KoParagLayout::HardFrameBreakBefore; // We have no way to load/use the new page layout, KWord doesn't have "sections". } } } } void KWTextParag::saveOasis( KoXmlWriter& writer, KoSavingContext& context, int from, int to, bool saveAnchorsFramesets ) const { // Special case for inline tables that are alone in their paragraph: // save instead of

. if ( string()->length() == 2 /*&& saveAnchorsFramesets*/ ) { KoTextStringChar &ch = string()->at( 0 ); if ( ch.isCustom() && dynamic_cast( ch.customItem() )) { KWFrameSet* fs = static_cast( ch.customItem() )->frameSet(); if ( fs->type() == FT_TABLE ) { // TODO maybe save parag style? extract a common method out of KoTextStringChar::saveOasis fs->saveOasis( writer, context, true ); return; } } } KoTextParag::saveOasis( writer, context, from, to, saveAnchorsFramesets ); }