/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.hslf.usermodel;

import static org.apache.poi.sl.usermodel.BaseTestSlideShow.getColor;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.awt.Color;
import java.io.IOException;
import java.util.List;

import org.apache.poi.hslf.HSLFTestDataSamples;
import org.apache.poi.hslf.model.textproperties.TextPropCollection;
import org.apache.poi.hslf.record.TextBytesAtom;
import org.apache.poi.hslf.record.TextCharsAtom;
import org.apache.poi.hslf.record.TextHeaderAtom;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

/**
 * Tests for TextRuns
 */
@SuppressWarnings("UnusedAssignment")
public final class TestTextRun {
	// SlideShow primed on the test data
	private HSLFSlideShow ss;
	private HSLFSlideShow ssRich;

	@BeforeEach
	void setUp() throws IOException {
		// Basic (non rich) test file
		ss = HSLFTestDataSamples.getSlideShow("basic_test_ppt_file.ppt");

		// Rich test file
		ssRich = HSLFTestDataSamples.getSlideShow("Single_Coloured_Page.ppt");
	}

	@AfterEach
	void tearDown() throws IOException {
	    ssRich.close();
	    ss.close();
	}

	/**
	 * Test to ensure that getting the text works correctly
	 */
	@Test
	void testGetText() {
		HSLFSlide slideOne = ss.getSlides().get(0);
		List<List<HSLFTextParagraph>> textParas = slideOne.getTextParagraphs();

		assertEquals(2, textParas.size());

		// Get text works with \n
		assertEquals("This is a test title", HSLFTextParagraph.getText(textParas.get(0)));
		assertEquals("This is a test subtitle\nThis is on page 1", HSLFTextParagraph.getText(textParas.get(1)));

		// Raw text has \r instead
		assertEquals("This is a test title", HSLFTextParagraph.getRawText(textParas.get(0)));
		assertEquals("This is a test subtitle\rThis is on page 1", HSLFTextParagraph.getRawText(textParas.get(1)));


		// Now check on a rich text run
		HSLFSlide slideOneR = ssRich.getSlides().get(0);
		textParas = slideOneR.getTextParagraphs();

		assertEquals(2, textParas.size());
		assertEquals("This is a title, it\u2019s in black", HSLFTextParagraph.getText(textParas.get(0)));
		assertEquals("This is the subtitle, in bold\nThis bit is blue and italic\nThis bit is red (normal)", HSLFTextParagraph.getText(textParas.get(1)));
		assertEquals("This is a title, it\u2019s in black", HSLFTextParagraph.getRawText(textParas.get(0)));
		assertEquals("This is the subtitle, in bold\rThis bit is blue and italic\rThis bit is red (normal)", HSLFTextParagraph.getRawText(textParas.get(1)));
	}

	/**
	 * Test to ensure changing non rich text bytes->bytes works correctly
	 */
	@Test
	void testSetText() {
		HSLFSlide slideOne = ss.getSlides().get(0);
		List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs();
		HSLFTextParagraph run = textRuns.get(0).get(0);
		HSLFTextRun tr =  run.getTextRuns().get(0);

		// Check current text
		assertEquals("This is a test title", tr.getRawText());

		// Change
		String changeTo = "New test title";
		tr.setText(changeTo);
		assertEquals(changeTo, tr.getRawText());

		// Ensure trailing \n's are NOT stripped, it is legal to set a text with a trailing '\r'
		tr.setText(changeTo + "\n");
		assertEquals(changeTo + "\r", tr.getRawText());
	}

	/**
	 * Test to ensure that changing non rich text between bytes and
	 *  chars works correctly
	 */
	@SuppressWarnings("unused")
    @Test
	void testAdvancedSetText() {
		HSLFSlide slideOne = ss.getSlides().get(0);
		List<HSLFTextParagraph> paras = slideOne.getTextParagraphs().get(0);
		HSLFTextParagraph para = paras.get(0);

        TextHeaderAtom tha = null;
        TextBytesAtom tba = null;
        TextCharsAtom tca = null;
		for ( org.apache.poi.hslf.record.Record r : para.getRecords()) {
		    if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
		    else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
		    else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
		}

		// Bytes -> Bytes
		assertNull(tca);
		assertNotNull(tba);
		// assertFalse(run._isUnicode);
		assertEquals("This is a test title", para.getTextRuns().get(0).getRawText());

		String changeBytesOnly = "New Test Title";
		HSLFTextParagraph.setText(paras, changeBytesOnly);
		para = paras.get(0);
		tha = null; tba = null; tca = null;
        for ( org.apache.poi.hslf.record.Record r : para.getRecords()) {
            if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
            else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
            else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
        }

		assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras));
		assertNull(tca);
		assertNotNull(tba);

		// Bytes -> Chars
		assertEquals(changeBytesOnly, HSLFTextParagraph.getRawText(paras));

		String changeByteChar = "This is a test title with a '\u0121' g with a dot";
		HSLFTextParagraph.setText(paras, changeByteChar);
		para = paras.get(0);
        tha = null; tba = null; tca = null;
        for ( org.apache.poi.hslf.record.Record r : para.getRecords()) {
            if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
            else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
            else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
        }

		assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras));
		assertNotNull(tca);
		assertNull(tba);

		// Chars -> Chars
		assertNotNull(tca);
		assertEquals(changeByteChar, HSLFTextParagraph.getRawText(paras));

		String changeCharChar = "This is a test title with a '\u0147' N with a hat";
		HSLFTextParagraph.setText(paras, changeCharChar);
        para = paras.get(0);
        tha = null; tba = null; tca = null;
        for ( org.apache.poi.hslf.record.Record r : para.getRecords()) {
            if (r instanceof TextHeaderAtom) tha = (TextHeaderAtom)r;
            else if (r instanceof TextBytesAtom) tba = (TextBytesAtom)r;
            else if (r instanceof TextCharsAtom) tca = (TextCharsAtom)r;
        }

		assertEquals(changeCharChar, HSLFTextParagraph.getRawText(paras));
		assertNotNull(tca);
		assertNull(tba);
	}

	/**
	 * Tests to ensure that non rich text has the right default rich text run
	 *  set up for it
	 */
	@Test
	void testGetRichTextNonRich() {
		HSLFSlide slideOne = ss.getSlides().get(0);
		List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs();

		assertEquals(2, textParass.size());

		List<HSLFTextParagraph> trA = textParass.get(0);
		List<HSLFTextParagraph> trB = textParass.get(1);

		assertEquals(1, trA.size());
		assertEquals(2, trB.size());

		HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0);
		HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);

		assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText());
		assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText());
	}

	/**
	 * Tests to ensure that the rich text runs are built up correctly
	 */
	@Test
	void testGetRichText() {
		HSLFSlide slideOne = ssRich.getSlides().get(0);
		List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs();

		assertEquals(2, textParass.size());

		List<HSLFTextParagraph> trA = textParass.get(0);
		List<HSLFTextParagraph> trB = textParass.get(1);

		assertEquals(1, trA.size());
		assertEquals(3, trB.size());

		HSLFTextRun rtrA = trA.get(0).getTextRuns().get(0);
		HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
		HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
		HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);

		assertEquals(HSLFTextParagraph.getRawText(trA), rtrA.getRawText());

		String trBstr = HSLFTextParagraph.getRawText(trB);
		assertEquals(trBstr.substring(0, 30), rtrB.getRawText());
		assertEquals(trBstr.substring(30,58), rtrC.getRawText());
		assertEquals(trBstr.substring(58,82), rtrD.getRawText());

		// Same paragraph styles
		assertEquals(trB.get(0).getParagraphStyle(), trB.get(1).getParagraphStyle());
		assertEquals(trB.get(0).getParagraphStyle(), trB.get(2).getParagraphStyle());

		// Different char styles
		assertNotEquals(rtrB.getCharacterStyle(), rtrC.getCharacterStyle());
        assertNotEquals(rtrB.getCharacterStyle(), rtrD.getCharacterStyle());
        assertNotEquals(rtrC.getCharacterStyle(), rtrD.getCharacterStyle());
	}

	/**
	 * Tests to ensure that setting the text where the text isn't rich,
	 *  ensuring that everything stays with the same default styling
	 */
	@Test
	void testSetTextWhereNotRich() {
		HSLFSlide slideOne = ss.getSlides().get(0);
		List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs();
		List<HSLFTextParagraph> trB = textParass.get(0);
		assertEquals(1, trB.size());

		HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
		assertEquals(HSLFTextParagraph.getText(trB), rtrB.getRawText());

		// Change text via normal
		HSLFTextParagraph.setText(trB, "Test Foo Test");
		rtrB = trB.get(0).getTextRuns().get(0);
		assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB));
		assertEquals("Test Foo Test", rtrB.getRawText());
	}

	/**
	 * Tests to ensure that setting the text where the text is rich
	 *  sets everything to the same styling
	 */
	@Test
	void testSetTextWhereRich() {
		HSLFSlide slideOne = ssRich.getSlides().get(0);
		List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs();
		List<HSLFTextParagraph> trB = textParass.get(1);
		assertEquals(3, trB.size());

		HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
		HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
		HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);
		TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle();
		TextPropCollection tpBC = rtrB.getCharacterStyle();
		TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle();
		TextPropCollection tpCC = rtrC.getCharacterStyle();
		TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle();
		TextPropCollection tpDC = rtrD.getCharacterStyle();

//		assertEquals(trB.getRawText().substring(0, 30), rtrB.getRawText());
		assertNotNull(tpBP);
		assertNotNull(tpBC);
		assertNotNull(tpCP);
		assertNotNull(tpCC);
		assertNotNull(tpDP);
		assertNotNull(tpDC);
		assertEquals(tpBP,tpCP);
		assertEquals(tpBP,tpDP);
		assertEquals(tpCP,tpDP);
		assertNotEquals(tpBC,tpCC);
		assertNotEquals(tpBC,tpDC);
		assertNotEquals(tpCC,tpDC);

		// Change text via normal
		HSLFTextParagraph.setText(trB, "Test Foo Test");

		// Ensure now have first style
		assertEquals(1, trB.get(0).getTextRuns().size());
		rtrB = trB.get(0).getTextRuns().get(0);
		assertEquals("Test Foo Test", HSLFTextParagraph.getRawText(trB));
		assertEquals("Test Foo Test", rtrB.getRawText());
		assertNotNull(rtrB.getCharacterStyle());
		assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
		assertEquals( tpBP, rtrB.getTextParagraph().getParagraphStyle() );
		assertEquals( tpBC, rtrB.getCharacterStyle() );
	}

	/**
	 * Test to ensure the right stuff happens if we change the text
	 *  in a rich text run, that doesn't happen to actually be rich
	 */
	@Test
	void testChangeTextInRichTextRunNonRich() {
		HSLFSlide slideOne = ss.getSlides().get(0);
		List<List<HSLFTextParagraph>> textRuns = slideOne.getTextParagraphs();
		List<HSLFTextParagraph> trB = textRuns.get(1);
		assertEquals(1, trB.get(0).getTextRuns().size());

		HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
		assertEquals(HSLFTextParagraph.getRawText(trB.subList(0, 1)), rtrB.getRawText());
		assertNotNull(rtrB.getCharacterStyle());
		assertNotNull(rtrB.getTextParagraph().getParagraphStyle());

		// Change text via rich
		rtrB.setText("Test Test Test");
		assertEquals("Test Test Test", HSLFTextParagraph.getRawText(trB.subList(0, 1)));
		assertEquals("Test Test Test", rtrB.getRawText());

		// Will now have dummy props
        assertNotNull(rtrB.getCharacterStyle());
        assertNotNull(rtrB.getTextParagraph().getParagraphStyle());
	}

	/**
	 * Tests to ensure changing the text within rich text runs works
	 *  correctly
	 */
	@Test
	void testChangeTextInRichTextRun() {
		HSLFSlide slideOne = ssRich.getSlides().get(0);
		List<List<HSLFTextParagraph>> textParass = slideOne.getTextParagraphs();
		List<HSLFTextParagraph> trB = textParass.get(1);
		assertEquals(3, trB.size());

		// We start with 3 text runs, each with their own set of styles,
		// but all sharing the same paragraph styles
		HSLFTextRun rtrB = trB.get(0).getTextRuns().get(0);
		HSLFTextRun rtrC = trB.get(1).getTextRuns().get(0);
		HSLFTextRun rtrD = trB.get(2).getTextRuns().get(0);
		TextPropCollection tpBP = rtrB.getTextParagraph().getParagraphStyle();
		TextPropCollection tpBC = rtrB.getCharacterStyle();
		TextPropCollection tpCP = rtrC.getTextParagraph().getParagraphStyle();
		TextPropCollection tpCC = rtrC.getCharacterStyle();
		TextPropCollection tpDP = rtrD.getTextParagraph().getParagraphStyle();
		TextPropCollection tpDC = rtrD.getCharacterStyle();

		// Check text and stylings
		assertEquals(HSLFTextParagraph.getRawText(trB).substring(0, 30), rtrB.getRawText());
		assertNotNull(tpBP);
		assertNotNull(tpBC);
		assertNotNull(tpCP);
		assertNotNull(tpCC);
		assertNotNull(tpDP);
		assertNotNull(tpDC);
		assertEquals(tpBP, tpCP);
		assertEquals(tpBP, tpDP);
		assertEquals(tpCP, tpDP);
		assertNotEquals(tpBC, tpCC);
		assertNotEquals(tpBC, tpDC);
		assertNotEquals(tpCC, tpDC);

		// Check text in the rich runs
		assertEquals("This is the subtitle, in bold\r", rtrB.getRawText());
		assertEquals("This bit is blue and italic\r", rtrC.getRawText());
		assertEquals("This bit is red (normal)", rtrD.getRawText());

		String newBText = "New Subtitle, will still be bold\n";
		String newCText = "New blue and italic text\n";
		String newDText = "Funky new normal red text";
		rtrB.setText(newBText);
		rtrC.setText(newCText);
		rtrD.setText(newDText);
		HSLFTextParagraph.storeText(trB);

		assertEquals(newBText.replace('\n','\r'), rtrB.getRawText());
		assertEquals(newCText.replace('\n','\r'), rtrC.getRawText());
		assertEquals(newDText.replace('\n','\r'), rtrD.getRawText());

		assertEquals(newBText.replace('\n','\r') + newCText.replace('\n','\r') + newDText.replace('\n','\r'), HSLFTextParagraph.getRawText(trB));

		// The styles should have been updated for the new sizes
		assertEquals(newBText.length(), tpBC.getCharactersCovered());
		assertEquals(newCText.length(), tpCC.getCharactersCovered());
		assertEquals(newDText.length()+1, tpDC.getCharactersCovered()); // Last one is always one larger

        // Paragraph style should be sum of text length
		assertEquals(
			newBText.length() + newCText.length() + newDText.length() +1,
			tpBP.getCharactersCovered() + tpCP.getCharactersCovered() + tpDP.getCharactersCovered()
		);

		// Check stylings still as expected
		TextPropCollection ntpBC = rtrB.getCharacterStyle();
		TextPropCollection ntpCC = rtrC.getCharacterStyle();
		TextPropCollection ntpDC = rtrD.getCharacterStyle();
		assertEquals(tpBC.getTextPropList(), ntpBC.getTextPropList());
		assertEquals(tpCC.getTextPropList(), ntpCC.getTextPropList());
		assertEquals(tpDC.getTextPropList(), ntpDC.getTextPropList());
	}


	/**
	 * Test case for Bug 41015.
	 *
	 * In some cases RichTextRun.getText() threw StringIndexOutOfBoundsException because
	 * of the wrong list of potential paragraph properties defined in StyleTextPropAtom.
	 *
	 */
	@Test
	void testBug41015() throws IOException {
		List<HSLFTextRun> rt;

		HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("bug-41015.ppt");
		HSLFSlide sl = ppt.getSlides().get(0);
        List<List<HSLFTextParagraph>> textParass = sl.getTextParagraphs();
		assertEquals(2, textParass.size());

		List<HSLFTextParagraph> textParas = textParass.get(0);
		rt = textParass.get(0).get(0).getTextRuns();
		assertEquals(1, rt.size());
		assertEquals(0, textParass.get(0).get(0).getIndentLevel());
		assertEquals("sdfsdfsdf", rt.get(0).getRawText());

		textParas = textParass.get(1);
        String[] texts = {"Sdfsdfsdf\r", "Dfgdfg\r", "Dfgdfgdfg\r", "Sdfsdfs\r", "Sdfsdf\r"};
        int[] indents = {0, 0, 0, 1, 1};
		int i=0;
		for (HSLFTextParagraph p : textParas) {
		    assertEquals(texts[i], p.getTextRuns().get(0).getRawText());
		    assertEquals(indents[i], p.getIndentLevel());
		    i++;
		}
		ppt.close();
	}

	/**
	 * Test creation of TextRun objects.
	 */
	@Test
	void testAddTextRun() throws IOException {
		HSLFSlideShow ppt = new HSLFSlideShow();
		HSLFSlide slide = ppt.createSlide();

		assertEquals(0, slide.getTextParagraphs().size());

		HSLFTextBox shape1 = new HSLFTextBox();
		List<HSLFTextParagraph> run1 = shape1.getTextParagraphs();
		shape1.setText("Text 1");
		slide.addShape(shape1);

		//The array of Slide's text runs must be updated when new text shapes are added.
		List<List<HSLFTextParagraph>> runs = slide.getTextParagraphs();
		assertNotNull(runs);
		assertSame(run1, runs.get(0));

		HSLFTextBox shape2 = new HSLFTextBox();
		List<HSLFTextParagraph> run2 = shape2.getTextParagraphs();
		shape2.setText("Text 2");
		slide.addShape(shape2);

		runs = slide.getTextParagraphs();
		assertEquals(2, runs.size());

		assertSame(run1, runs.get(0));
		assertSame(run2, runs.get(1));

		// as getShapes()
		List<HSLFShape> sh = slide.getShapes();
		assertEquals(2, sh.size());
		assertTrue(sh.get(0) instanceof HSLFTextBox);
		HSLFTextBox box1 = (HSLFTextBox)sh.get(0);
		assertSame(run1, box1.getTextParagraphs());
		HSLFTextBox box2 = (HSLFTextBox)sh.get(1);
		assertSame(run2, box2.getTextParagraphs());

		// test Table - a complex group of shapes containing text objects
		HSLFSlide slide2 = ppt.createSlide();
		assertTrue(slide2.getTextParagraphs().isEmpty());
		HSLFTable table = new HSLFTable(2, 2);
		slide2.addShape(table);
		runs = slide2.getTextParagraphs();
		assertNotNull(runs);
		assertEquals(4, runs.size());
		ppt.close();
	}

	@Test
	void test48916() throws IOException {
        HSLFSlideShow ppt1 = HSLFTestDataSamples.getSlideShow("SampleShow.ppt");
        List<HSLFSlide> slides = ppt1.getSlides();
        for(HSLFSlide slide : slides){
            for(HSLFShape sh : slide.getShapes()){
                if (!(sh instanceof HSLFTextShape)) continue;
                HSLFTextShape tx = (HSLFTextShape)sh;
                List<HSLFTextParagraph> paras = tx.getTextParagraphs();
                //verify that records cached in  TextRun and EscherTextboxWrapper are the same
                 org.apache.poi.hslf.record.Record[] runChildren = paras.get(0).getRecords();
                 org.apache.poi.hslf.record.Record[] txboxChildren = tx.getEscherTextboxWrapper().getChildRecords();
                assertEquals(runChildren.length, txboxChildren.length);
                for(int i=0; i < txboxChildren.length; i++){
                    assertSame(txboxChildren[i], runChildren[i]);
                }
                // caused NPE prior to fix of Bugzilla #48916
                for (HSLFTextParagraph p : paras) {
                    for (HSLFTextRun rt : p.getTextRuns()) {
                        rt.setBold(true);
                        rt.setFontColor(Color.RED);
                    }
                }
                // tx.storeText();
            }
        }

        HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
        for(HSLFSlide slide : ppt2.getSlides()){
            for(HSLFShape sh : slide.getShapes()){
                if(sh instanceof HSLFTextShape){
                    HSLFTextShape tx = (HSLFTextShape)sh;
                    List<HSLFTextParagraph> run = tx.getTextParagraphs();
                    HSLFTextRun rt = run.get(0).getTextRuns().get(0);
                    assertTrue(rt.isBold());
                    assertEquals(Color.RED, getColor(rt.getFontColor()));
                }
            }
        }
        ppt2.close();
        ppt1.close();
    }

	@Test
	void test52244() throws IOException {
        HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("52244.ppt");
        HSLFSlide slide = ppt.getSlides().get(0);

        int[] sizes = {36, 24, 12, 32, 12, 12};

        int i=0;
        for (List<HSLFTextParagraph> textParas : slide.getTextParagraphs()) {
			HSLFTextRun first = textParas.get(0).getTextRuns().get(0);
            assertEquals("Arial", first.getFontFamily());
            assertNotNull(first.getFontSize());
            assertEquals(sizes[i++], first.getFontSize().intValue());
        }
        ppt.close();
    }

	@Test
	void testAppendEmpty() throws IOException {
        try (HSLFSlideShow ppt = new HSLFSlideShow()) {
			HSLFSlide s = ppt.createSlide();
			HSLFTextBox title = s.addTitle();
			title.setText("");
			title.appendText("\n", true);
			title.appendText("para", true);
			assertEquals("\npara", title.getText());
		}
	}
}
