[ Previous document | Content Table | Next document ]

8  Text Documents

 

8.1  Overview

In the OpenOffice.org API, a text document is a document model which is able to handle text contents. A document in our context is a product of work that can be stored and printed to make the result of the work a permanent resource. By model we mean data that forms the basis of a document and is organized in a manner that allows working with the data independently from their visual representation in a graphical user interface. 

It is important to understand that developers have to work with the model directly, when they want to change it through the OpenOffice.org API. The model has a controller object which enables developers to manipulate the visual presentation of the document in the user interface. But the controller is not used to change a document. The controller serves two purposes.

Keeping the difference between model and controller in mind, we will now discuss the parts of a text document model in the OpenOffice.org API. 

The text document model in the OpenOffice.org API has five major architectural areas, cf. Illustration 8.1 below. The five areas are:

The core of the text document model is the text. It consists of character strings organized in paragraphs and other text contents. The usage of text will be discussed in 8.3 Text Documents - Working with Text Documents.

The service manager of the document model creates all text contents for the model, except for the paragraphs. Note that the document service manager is different from the main service manager that is used when connecting to the office. Each document model has its own service manager, so that the services can be adapted to the document when required. Examples for text contents created by the text document service manager are text tables, text fields, drawing shapes, text frames or graphic objects. The service manager is asked for a text content, then you insert it into the text. 

Afterwards, the majority of these text contents in a text can be retrieved from the model using text content suppliers. The exception are drawing shapes. They can be found on the DrawPage, which is discussed below.

Above the text lies the DrawPage. It is used for drawing contents. Imagine it as a transparent layer with contents that can affect the text under the layer, for instance by forcing it to wrap around contents on the DrawPage. However, text can also wrap through DrawPage contents, so the similarity is limited.

Finally, there are services that allow for document wide styling and structuring of the text. Among them are style family suppliers for paragraphs, characters, pages and numbering patterns, and suppliers for line and outline numbering. 

Besides these five architectural areas, there are a number of aspects covering the document character of our model: It is printable, storable, modifiable, it can be refreshed, its contents are able to be searched and replaced and it supplies general information about itself. These aspects are shown at the lower right of the illustration. 

Finally, the controller provides access to the graphical user interface for the model and has knowledge about the current view status in the user interface, cf. the upper left of the diagram above. 

The usage of text is discussed in the section 8.3.1 Text Documents - Working with Text Documents - Word Processing below. This overview will be concluded by two examples:

8.1.1  Example: Fields in a Template

All following code samples are contained in TextDocuments.java. This file is located in the Samples folder that comes with the resources for the developer's manual.

The examples use the environment from chapter 2 First Steps, for instance, connecting using the getRemoteServiceManager() method.

We want to use a template file containing text fields and bookmarks and insert text into the fields and at the cursor position. The suitable template file TextTemplateWithUserFields.odt lies in the Samples folder, as well. Edit the path to this file below before running the sample.

The first step is to load the file as a template, so that OpenOffice.org creates a new, untitled document. As in the chapter 2 First Steps, we have to connect, get the Desktop object, query its XComponentLoader interface and call loadComponentFromUrl(). This time we tell OpenOffice.org how it should load the file. The key for loading parameters is the sequence of PropertyValue structs passed to loadComponentFromUrl(). The appropriate PropertyValue name is AsTemplate and we have to set AsTemplate  to true. (Text/TextDocuments.java)

/** Load a document as template */ 

protected XComponent newDocComponentFromTemplate(String loadUrl) throws java.lang.Exception { 

    // get the remote service manager

    mxRemoteServiceManager = this.getRemoteServiceManager(unoUrl);

    // retrieve the Desktop object, we need its XComponentLoader

    Object desktop = mxRemoteServiceManager.createInstanceWithContext(

        "com.sun.star.frame.Desktop", mxRemoteContext);

    XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface(

        XComponentLoader.class, desktop);

       

    // define load properties according to com.sun.star.document.MediaDescriptor

    // the boolean property AsTemplate tells the office to create a new document

    // from the given file

    PropertyValue[] loadProps = new PropertyValue[1];

    loadProps[0] = new PropertyValue();

    loadProps[0].Name = "AsTemplate";

    loadProps[0].Value = new Boolean(true);      

    // load

    return xComponentLoader.loadComponentFromURL(loadUrl, "_blank", 0, loadProps);          

Now that we are able to load a text document as template, we will open an existing template file that contains five text fields and a bookmark. We want to demonstrate how to insert text at predefined positions in a document. 

Text fields and bookmarks are supplied by the appropriate XTextFieldsSupplier and XBookmarksSupplier interfaces. Their fully qualified names are com.sun.star.text.XTextFieldsSupplier and com.sun.star.text.XBookmarksSupplier.

The XTextFieldsSupplier provides collections of text fields in our text. We use document variable fields for our purpose, which arecom.sun.star.text.textfield.User services. All User fields have a field master that holds the actual content of the variable. Therefore, the TextFields collection, as well as the FieldMasters are required for our example. We get the field masters for the five fields by name and set their Content property. Finally, we refresh the text fields so that they reflect the changes made to the field masters.

The XBookmarksSupplier returns all bookmarks in our document. The collection of bookmarks is a com.sun.star.container.XNameAccess, so that the bookmarks are retrieved by name. Every object in a text supports the interface XTextContent that has a method getAnchor(). The anchor is the text range an object takes up, so getAnchor() retrieves is an XTextRange. From the chapter 2 First Steps, a com.sun.star.text.XTextRange allows setting the string of a text range. Our bookmark is a text content and therefore must support XTextContent. Inserting text at a bookmark position is straightforward: get the anchor of the bookmark and set its string. (Text/TextDocuments.java)

/** Sample for use of templates 

    This sample uses the file TextTemplateWithUserFields.odt from the Samples folder.

    The file contains a number of User text fields (Variables - User) and a bookmark

    which we use to fill in various values

 */

protected void templateExample() throws java.lang.Exception { 

    // create a small hashtable that simulates a rowset with columns

    Hashtable recipient = new Hashtable();

    recipient.put("Company", "Manatee Books");

    recipient.put("Contact", "Rod Martin");

    recipient.put("ZIP", "34567");

    recipient.put("City", "Fort Lauderdale");

    recipient.put("State", "Florida");

       

    // load template with User fields and bookmark

    XComponent xTemplateComponent = newDocComponentFromTemplate(

    "file:///X:/devmanual/Samples/TextTemplateWithUserFields.odt");

       

    // get XTextFieldsSupplier and XBookmarksSupplier interfaces from document component

    XTextFieldsSupplier xTextFieldsSupplier = (XTextFieldsSupplier)UnoRuntime.queryInterface(

        XTextFieldsSupplier.class, xTemplateComponent);

    XBookmarksSupplier xBookmarksSupplier = (XBookmarksSupplier)UnoRuntime.queryInterface(

        XBookmarksSupplier.class, xTemplateComponent);

       

    // access the TextFields and the TextFieldMasters collections

    XNameAccess xNamedFieldMasters = xTextFieldsSupplier.getTextFieldMasters();

    XEnumerationAccess xEnumeratedFields = xTextFieldsSupplier.getTextFields();

       

    // iterate over hashtable and insert values into field masters

    java.util.Enumeration keys = recipient.keys();

    while (keys.hasMoreElements()) {

        // get column name

        String key = (String)keys.nextElement();

           

        // access corresponding field master

        Object fieldMaster = xNamedFieldMasters.getByName(

            "com.sun.star.text.FieldMaster.User." + key);

           

        // query the XPropertySet interface, we need to set the Content property

        XPropertySet xPropertySet = (XPropertySet)UnoRuntime.queryInterface(

            XPropertySet.class, fieldMaster);

           

        // insert the column value into field master

        xPropertySet.setPropertyValue("Content", recipient.get(key));

    }

 

    // afterwards we must refresh the textfields collection

    XRefreshable xRefreshable = (XRefreshable)UnoRuntime.queryInterface(

        XRefreshable.class, xEnumeratedFields);

    xRefreshable.refresh();

 

    // accessing the Bookmarks collection of the document

    XNameAccess xNamedBookmarks = xBookmarksSupplier.getBookmarks();

       

    // find the bookmark named "Subscription"

    Object bookmark = xNamedBookmarks.getByName("Subscription");

 

    // we need its XTextRange which is available from getAnchor(),

    // so query for XTextContent

    XTextContent xBookmarkContent = (XTextContent)UnoRuntime.queryInterface(

        XTextContent.class, bookmark);

 

    // get the anchor of the bookmark (its XTextRange)

    XTextRange xBookmarkRange = xBookmarkContent.getAnchor();

 

    // set string at the bookmark position

    xBookmarkRange.setString("subscription for the Manatee Journal");

8.1.2  Example: Visible Cursor Position

As discussed earlier, the OpenOffice.org API distinguishes between the model and controller. This difference is mirrored in two different kinds of cursors in the API: model cursors and visible cursors. The visible cursor is also called view cursor.

The second example assumes that the user has selected a text range in a paragraph and expects something to happen at that cursor position. Setting character and paragraph styles, and retrieving the current page number at the view cursor position is demonstrated in the example. The view cursor will be transformed into a model cursor. 

We want to work with the current document, therefore we cannot use loadComponentFromURL(). Rather, we ask the com.sun.star.frame.Desktop service for the current component. Once we have the current component—which is our document model—we go from the model to the controller and get the view cursor.

The view cursor has properties for the current character and paragraph style. The example uses built-in styles and sets the property CharStyleName to "Quotation" and ParaStyleName to "Quotations". Furthermore, the view cursor knows about the automatic page breaks. Because we are interested in the current page number, we get it from the view cursor and print it out.

The model cursor is much more powerful than the view cursor when it comes to possible movements and editing capabilities. We create a model cursor from the view cursor. Two steps are necessary: We ask the view cursor for its Text service, then we have the Text service create a model cursor based on the current cursor position. The model cursor knows where the paragraph ends, so we go there and insert a string. (Text/TextDocuments.java)

/** Sample for document changes, starting at the current view cursor position 

    The sample changes the paragraph style and the character style at the current

    view cursor selection

    Open the sample file ViewCursorExampleFile, select some text and run the example

    The current paragraph will be set to Quotations paragraph style

    The selected text will be set to Quotation character style

 */

private void viewCursorExample() throws java.lang.Exception { 

    // get the remote service manager

    mxRemoteServiceManager = this.getRemoteServiceManager(unoUrl);

 

    // get the Desktop service

    Object desktop = mxRemoteServiceManager.createInstanceWithContext(

        "com.sun.star.frame.Desktop", mxRemoteContext);

 

    // query its XDesktop interface, we need the current component

    XDesktop xDesktop = (XDesktop)UnoRuntime.queryInterface(

         XDesktop.class, desktop);

 

    // retrieve the current component and access the controller

    XComponent xCurrentComponent = xDesktop.getCurrentComponent();

 

    // get the XModel interface from the component

    XModel xModel = (XModel)UnoRuntime.queryInterface(XModel.class, xCurrentComponent);

 

    // the model knows its controller

    XController xController = xModel.getCurrentController();

 

    // the controller gives us the TextViewCursor

    // query the viewcursor supplier interface

    XTextViewCursorSupplier xViewCursorSupplier =

        (XTextViewCursorSupplier)UnoRuntime.queryInterface(

            XTextViewCursorSupplier.class, xController);

 

    // get the cursor

    XTextViewCursor xViewCursor = xViewCursorSupplier.getViewCursor();

       

    // query its XPropertySet interface, we want to set character and paragraph properties

    XPropertySet xCursorPropertySet = (XPropertySet)UnoRuntime.queryInterface(

        XPropertySet.class, xViewCursor);

 

    // set the appropriate properties for character and paragraph style

    xCursorPropertySet.setPropertyValue("CharStyleName", "Quotation");

    xCursorPropertySet.setPropertyValue("ParaStyleName", "Quotations");

 

    // print the current page number – we need the XPageCursor interface for this

    XPageCursor xPageCursor = (XPageCursor)UnoRuntime.queryInterface(

        XPageCursor.class, xViewCursor);

    System.out.println("The current page number is " + xPageCursor.getPage());

 

    // the model cursor is much more powerful, so

    // we create a model cursor at the current view cursor position with the following steps:

    // we get the Text service from the TextViewCursor, the cursor is an XTextRange and has

    // therefore a method getText()

    XText xDocumentText = xViewCursor.getText();

 

    // the text creates a model cursor from the viewcursor

    XTextCursor xModelCursor = xDocumentText.createTextCursorByRange(xViewCursor.getStart());

 

    // now we could query XWordCursor, XSentenceCursor and XParagraphCursor

    // or XDocumentInsertable, XSortable or XContentEnumerationAccess

    // and work with the properties of com.sun.star.text.TextCursor

       

    // in this case we just go to the end of the paragraph and add some text.

    XParagraphCursor xParagraphCursor = (XParagraphCursor)UnoRuntime.queryInterface(

    XParagraphCursor.class, xModelCursor);

 

    // goto the end of the paragraph

    xParagraphCursor.gotoEndOfParagraph(false);

    xParagraphCursor.setString(" ***** Fin de semana! ******");

8.2  Handling Text Document Files

8.2.1  Creating and Loading Text Documents

If a document in OpenOffice.org is required, begin by getting a com.sun.star.frame.Desktop service from the service manager. The desktop handles all document components in OpenOffice.org, among other things. It is discussed thoroughly in the chapter 7 Office Development. Office documents are often called components, because they support the com.sun.star.lang.XComponent interface. An XComponent is a UNO object that can be disposed explicitly and broadcast an event to other UNO objects when this happens.

The Desktop can load new and existing components from a URL. For this purpose it has a com.sun.star.frame.XComponentLoader interface that has one single method to load and instantiate components from a URL into a frame:

com.sun.star.lang::XComponent loadComponentFromURL([in] string aURL,

        [in] string aTargetFrameName,

        [in] long nSearchFlags,

        [in] sequence< com::sun::star::beans::PropertyValue > aArgs );

The interesting parameters in our context are the URL that describes which resource should be loaded and the sequence of load arguments. For the target frame pass "_blank" and set the search flags to 0. In most cases you will not want to reuse an existing frame.

The URL can be a file: URL, a http: URL, an ftp: URL or a private: URL. Look up the correct URL format in the load URL box in the function bar of OpenOffice.org. For new writer documents, a special URL scheme has to be used. The scheme is "private:", followed by "factory" as hostname. The resource is "swriter" for  OpenOffice.org writer documents. For a new writer document, use "private:factory/swriter".

The load arguments are described in com.sun.star.document.MediaDescriptor. The arguments AsTemplate and Hidden have properties that are boolean values. If AsTemplate is true, the loader creates a new untitled document from the given URL. If it is false, template files are loaded for editing. If Hidden is true, the document is loaded in the background. This is useful when generating a document in the background without letting the user observe, for example, it can be used to generate a document and print it without previewing. 7 Office Development describes other available options.

The section 8.1.1 Text Documents - Overview - Fields in a Template discusses a complete example about how loading works. The following snippet loads a document in hidden mode: (Text/TextDocuments.java)

// (the method getRemoteServiceManager is described in the chapter First Steps) 

mxRemoteServiceManager = this.getRemoteServiceManager(unoUrl); 

 

// retrieve the Desktop object, we need its XComponentLoader 

Object desktop = mxRemoteServiceManager.createInstanceWithContext( 

"com.sun.star.frame.Desktop", mxRemoteContext); 

 

// query the XComponentLoader interface from the Desktop service 

XComponentLoader xComponentLoader = (XComponentLoader)UnoRuntime.queryInterface( 

    XComponentLoader.class, desktop);

       

// define load properties according to com.sun.star.document.MediaDescriptor 

 

/* or simply create an empty array of com.sun.star.beans.PropertyValue structs: 

   PropertyValue[] loadProps = new PropertyValue[0]

*/ 

 

// the boolean property Hidden tells the office to open a file in hidden mode 

PropertyValue[] loadProps = new PropertyValue[1]; 

loadProps[0] = new PropertyValue(); 

loadProps[0].Name = "Hidden"; 

loadProps[0].Value = new Boolean(true);  

     

// load 

return xComponentLoader.loadComponentFromURL(loadUrl, "_blank", 0, loadProps);          

8.2.2  Saving Text Documents

Storing

Documents are storable through their interface com.sun.star.frame.XStorable. This interface is discussed in detail in 7 Office Development. An XStorable implements these operations:

boolean hasLocation()

string getLocation()

boolean isReadonly()

void store()

void storeAsURL( [in] string aURL, sequence< com::sun::star::beans::PropertyValue > aArgs)

void storeToURL( [in] string aURL, sequence< com::sun::star::beans::PropertyValue > aArgs)  

The method names are evident. The method storeAsUrl() is the exact representation of File – Save As, that is, it changes the current document location. In contrast, storeToUrl() stores a copy to a new location, but leaves the current document URL untouched.

Exporting

For exporting purposes, a filter name can be passed to storeAsURL() and storeToURL() that triggers an export to other file formats. The property needed for this purpose is the string argument FilterName that takes filter names defined in the configuration file:

<OfficePath>\share\config\registry\modules\org\openoffice\TypeDetection\Filter\*.xcu

In the *.xcu, look for <node oor:name=”...”/ oor:op=”replace”> elements, their oor:name attribute contains the needed strings for FilterName. The proper filter name for StarWriter 5.x is "StarWriter 5.0", and the export format "MS Word 97" is also popular. This is the element in <OfficePath>\share\config\registry\modules\org\openoffice\TypeDetection\Filter\fcfg_writer_filtewrs.xcu that describes the MS Word 97 filter:

<node oor:name="MS Word 97" oor:op="replace"> 

        <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN PREFERRED</value></prop>

        <prop oor:name="UIComponent"/>

        <prop oor:name="FilterService"/>

        <prop oor:name="UserData"><value>CWW8</value></prop>

        <prop oor:name="UIName">

                <value xml:lang="x-default">Microsoft Word 97/2000/XP</value>

        </prop>

        <prop oor:name="FileFormatVersion"><value>0</value></prop>

        <prop oor:name="Type"><value>writer_MS_Word_97</value></prop>

        <prop oor:name="TemplateName"/>

        <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>

</node> 

The following method stores a document using this filter: (Text/TextDocuments.java

/** Store a document, using the MS Word 97/2000/XP Filter */ 

    protected void storeDocComponent(XComponent xDoc, String storeUrl) throws java.lang.Exception {

       

        XStorable xStorable = (XStorable)UnoRuntime.queryInterface(XStorable.class, xDoc);

        PropertyValue[] storeProps = new PropertyValue[1];

        storeProps[0] = new PropertyValue();

        storeProps[0].Name = "FilterName";

        storeProps[0].Value = "MS Word 97";        

        xStorable.storeAsURL(storeUrl, storeProps);          

    }

If an empty array of PropertyValue structs is passed, the native .odt format of OpenOffice.org is used.

8.2.3  Printing Text Documents

Printer and Print Job Settings

Printing is a common office functionality. The chapter  7 Office Development provides in-depth information about it. The writer document implements the com.sun.star.view.XPrintable interface for printing. It consists of three methods:

sequence< com::sun::star::beans::PropertyValue > getPrinter ()

void setPrinter ( [in] sequence< com::sun::star::beans::PropertyValue > aPrinter)

void print ( [in] sequence< com::sun::star::beans::PropertyValue > xOptions)

The following code is used with a given document xDoc to print to the standard printer without any settings: (Text/TextDocuments.java)

        // query the XPrintable interface from your document

        XPrintable xPrintable = (XPrintable)UnoRuntime.queryInterface(XPrintable.class, xDoc);

       

        // create an empty printOptions array

        PropertyValue[] printOpts = new PropertyValue[0];

       

        // kick off printing       

        xPrintable.print(printOpts);

There are two groups of properties involved in general printing. The first one is used with setPrinter() and getPrinter() that controls the printer, and the second one is passed to print() and controls the print job.

com.sun.star.view.PrinterDescriptor comprises the properties for the printer:

Properties of com.sun.star.view.PrinterDescriptor

Name

string  — Specifies the name of the printer queue to be used.

PaperOrientation

com.sun.star.view.PaperOrientation. Specifies the orientation of the paper.

PaperFormat

com.sun.star.view.PaperFormat. Specifies a predefined paper size or if the paper size is a user-defined size.

PaperSize

com.sun.star.awt.Size. Specifies the size of the paper in 1/100 mm.

IsBusy

boolean Indicates if the printer is busy.

CanSetPaperOrientation

boolean Indicates if the printer allows changes to PaperOrientation.

CanSetPaperFormat

boolean  — Indicates if the printer allows changes to PaperFormat.

CanSetPaperSize

boolean  — Indicates if the printer allows changes to PaperSize.

com.sun.star.view.PrintOptions contains the following possibilities for a print job:

Properties of com.sun.star.view.PrintOptions

CopyCount

short   Specifies the number of copies to print.

FileName

string — Specifies the name of a file to print to, if set.

Collate

boolean   Advises the printer to collate the pages of the copies. If true, a whole document is printed prior to the next copy, otherwise the page copies are completed together.

Pages

string  Specifies the pages to print in the same format as in the print dialog of the GUI (e.g. "1, 3, 4-7, 9-")

The following method uses PrinterDescriptor and PrintOptions to print to a special printer,  and preselect the pages to print. (Text/TextDocuments.java)

protected void printDocComponent(XComponent xDoc) throws java.lang.Exception { 

    XPrintable xPrintable = (XPrintable)UnoRuntime.queryInterface(XPrintable.class, xDoc);

    PropertyValue[] printerDesc = new PropertyValue[1];

    printerDesc[0] = new PropertyValue();

    printerDesc[0].Name = "Name";

    printerDesc[0].Value = "5D PDF Creator";        

 

    xPrintable.setPrinter(printerDesc);        

       

    PropertyValue[] printOpts = new PropertyValue[1];

    printOpts[0] = new PropertyValue();

    printOpts[0].Name = "Pages";

    printOpts[0].Value = "3-5,7";        

       

    xPrintable.print(printOpts);

Printing Multiple Pages on one Page

The interface com.sun.star.text.XPagePrintable is used to print more than one document page to a single printed page.

sequence< com::sun::star::beans::PropertyValue > getPagePrintSettings()

void setPagePrintSettings( [in] sequence< com::sun::star::beans::PropertyValue > aSettings)

void printPages( [in] sequence< com::sun::star::beans::PropertyValue > xOptions)  

The first two methods getPagePrintSettings() and setPagePrintSettings() control the page printing. They use a sequence of com.sun.star.beans.PropertyValues whose possible values are defined in com.sun.star.text.PagePrintSettings:

Properties of com.sun.star.text.PagePrintSettings

PageRows

short  Number of rows in which document pages should appear on the output page.

PageColumns

short   Number of columns in which document pages should appear on the output page.

LeftMargin

long   Left margin on the output page.

RightMargin

long Right margin on the output page.

TopMargin

long Top margin on the output page.

BottomMargin

long Bottom margin on the output page.

HoriMargin

long Margin between the columns on the output page.

VertMargin

long Margin between the rows on the output page.

IsLandscape

boolean Determines if the output page is in landscape format.

The method printPages() prints the document according to the previous settings. The argument for the printPages() method may contain the PrintOptions as described in the section above (containing the properties CopyCount, FileName, Collate and Pages).

8.3  Working with Text Documents

8.3.1  Word Processing

The text model in Illustration 8.1 shows that working with text starts with the method getText() at the XTestDocument interface of the document model. It returns a com.sun.star.text.Text service that handles text in OpenOffice.org.

The Text service has two mandatory interfaces and no properties: 

UML diagram showing the of com.sun.star.text.Text serviceIllustration 8.2: Service com.sun.star.text.Text (mandatory interfaces only)

The XText is used to edit a text, and XEnumerationAccess is used to iterate over text. The following sections discuss these aspects of the Text service.

Editing Text

As previously discussed in the introductory chapter 2 First Steps, the interface com.sun.star.text.XText  incorporates three interfaces: XText, XSimpleText and XTextRange. When working with an XText, you work with the string it contains, or you insert and remove contents other than strings, such as tables, text fields, and graphics.

Strings

The XText is handled as a whole. There are two possibilities if the text is handled as one string. The complete string can be set at once, or strings can be added at the beginning or end of the existing text. These are the appropriate methods used for that purpose:

void setString( [in] string text)

String getString()

Consider the following example: (Text/TextDocuments.java

/** Setting the whole text of a document as one string */ 

protected void BodyTextExample() { 

    // Body Text and TextDocument example

    try {

        // demonstrate simple text insertion

        mxDocText.setString("This is the new body text of the document."

            + "\n\nThis is on the second line.\n\n");

    } catch (Exception e) {

        e.printStackTrace (System.out);

    }

Beginning and end of a text can be determined calling getStart() and getEnd():

com::sun::star::text::XTextRange getStart()

com::sun::star::text::XTextRange getEnd()

The following example adds text using the start and end range of a text: (Text/TextDocuments.java

/** Adding a string at the end or the beginning of text */ 

protected void TextRangeExample() { 

    try {

        // Get a text range referring to the beginning of the text document

        XTextRange xStart = mxDocText.getStart();

        // use setString to insert text at the beginning

        xStart.setString ("This is text inserted at the beginning.\n\n");

        // Get a text range referring to the end of the text document

        XTextRange xEnd = mxDocText.getEnd();

        // use setString to insert text at the end

            xEnd.setString ("This is text inserted at the end.\n\n");

    } catch (Exception e) {

        e.printStackTrace(System.out);

    }

The above code is not very flexible. To gain flexibility, create a text cursor that is a movable text range. Note that such a text cursor is not visible in the user interface. The XText creates a cursor that works on the model immediately. The following methods can be used to get as many cursors as required:

com::sun::star::text::XTextCursor createTextCursor()

com::sun::star::text::XTextCursor createTextCursorByRange(
                        com::sun::star::text::XTextRange aTextPosition)

The text cursor travels through the text as a "collapsed" text range with identical start and end as a point in text, or it can expand while it moves to contain a target string. This is controlled with the  methods of the XTextCursor interface:

// moving the cursor 

// if bExpand is true, the cursor expands while it travels 

boolean goLeft( [in] short nCount, [in] boolean bExpand)

boolean goRight( [in] short nCount, [in] boolean bExpand)

void gotoStart( [in] boolean bExpand)

void gotoEnd( [in] boolean bExpand)

void gotoRange( [in] com::sun::star::text::XTextRange xRange, [in] boolean bExpand)

 

// controlling the collapsed status of the cursor 

void collapseToStart()

void collapseToEnd()

boolean isCollapsed()

In writer, a text cursor has three interfaces that inherit from XTextCursor: com.sun.star.text.XWordCursor, com.sun.star.text.XSentenceCursor and com.sun.star.text.XParagraphCursor. These interfaces introduce the following additional movements and status checks:

boolean gotoNextWord( [in] boolean bExpand)

boolean gotoPreviousWord( [in] boolean bExpand)

boolean gotoEndOfWord( [in] boolean bExpand)

boolean gotoStartOfWord( [in] boolean bExpand)  

boolean isStartOfWord()

boolean isEndOfWord()

 

boolean gotoNextSentence( [in] boolean Expand)

boolean gotoPreviousSentence( [in] boolean Expand)

boolean gotoStartOfSentence( [in] boolean Expand)

boolean gotoEndOfSentence( [in] boolean Expand)

boolean isStartOfSentence()

boolean isEndOfSentence()

 

boolean gotoStartOfParagraph( [in] boolean bExpand)

boolean gotoEndOfParagraph( [in] boolean bExpand)

boolean gotoNextParagraph( [in] boolean bExpand)

boolean gotoPreviousParagraph( [in] boolean bExpand)  

boolean isStartOfParagraph()

boolean isEndOfParagraph()

Since XTextCursor inherits from XTextRange, a cursor is an XTextRange and incorporates the methods of an XTextRange:

com::sun::star::text::XText getText()

com::sun::star::text::XTextRange getStart()

com::sun::star::text::XTextRange getEnd()

string getString()

void setString( [in] string aString)

The cursor can be told where it is required and the string content can be set later. This does have a drawback. After setting the string, the inserted string is always selected. That means further text can not be added without moving the cursor again. Therefore the most flexible method to insert strings by means of a cursor is the method insertString() in XText. It takes an XTextRange as the target range that is replaced during insertion, a string to insert, and a boolean parameter that determines if the inserted text should be absorbed by the cursor after it has been inserted. The XTextRange could be any XTextRange. The XTextCursor is an XTextRange, so it is used here:

void insertString( [in] com::sun::star::text::XTextRange xRange,  

                   [in] string aString,  

                   [in] boolean bAbsorb)

To insert text sequentially the bAbsorb parameter must be set to false, so that the XTextRange collapses at the end of the inserted string after insertion. If bAbsorb is true, the text range selects the new inserted string. The string that was selected by the text range prior to insertion is deleted.

Consider the use of insertString() below: (Text/TextDocuments.java)

/** moving a text cursor, selecting text and overwriting it */ 

protected void TextCursorExample() { 

    try {

        // First, get the XSentenceCursor interface of our text cursor

        XSentenceCursor xSentenceCursor = (XSentenceCursor)UnoRuntime.queryInterface(

            XSentenceCursor.class, mxDocCursor);

 

        // Goto the next cursor, without selecting it

        xSentenceCursor.gotoNextSentence(false);

 

        // Get the XWordCursor interface of our text cursor

        XWordCursor xWordCursor = (XWordCursor) UnoRuntime.queryInterface(

            XWordCursor.class, mxDocCursor);

 

        // Skip the first four words of this sentence and select the fifth

        xWordCursor.gotoNextWord(false);

        xWordCursor.gotoNextWord(false);

        xWordCursor.gotoNextWord(false);

        xWordCursor.gotoNextWord(false);

        xWordCursor.gotoNextWord(true);

 

        // Use the XSimpleText interface to insert a word at the current cursor

        // location, over-writing

        // the current selection (the fifth word selected above)

        mxDocText.insertString(xWordCursor, "old ", true);

 

        // Access the property set of the cursor, and set the currently selected text

        // (which is the string we just inserted) to be bold

        XPropertySet xCursorProps = (XPropertySet) UnoRuntime.queryInterface(

            XPropertySet.class, mxDocCursor);

        xCursorProps.setPropertyValue("CharWeight", new Float(com.sun.star.awt.FontWeight.BOLD));

 

        // replace the '.' at the end of the sentence with a new string

        xSentenceCursor.gotoEndOfSentence(false);

        xWordCursor.gotoPreviousWord(true);

        mxDocText.insertString(xWordCursor,

            ", which has been changed with text cursors!", true);

    } catch (Exception e) {

            e.printStackTrace(System.out);

    }

Text Contents Other Than Strings

Up to this point, paragraphs made up of character strings has been discussed. Text can also contain other objects besides character strings in paragraphs. They all support the interface com.sun.star.text.XTextContent. In fact, everything in texts must support XTextContent.

A text content is an object that is attached to a com.sun.star.text.XTextRange. The text range it is attached to is called the anchor of the text content.

All text contents mentioned below, starting with tables, support the service com.sun.star.text.TextContent. It includes the interface com.sun.star.text.XTextContent that inherits from the interface com.sun.star.lang.XComponent. The TextContent services may have the following properties:

Properties of com.sun.star.text.TextContent

AnchorType

Describes the base the object is positioned to, according to  com.sun.star.text.TextContentAnchorType.

AnchorTypes

A sequence of com.sun.star.text.TextContentAnchorType that contains all allowed anchor types for the object.

TextWrap

Determines the way the surrounding text flows around the object, according to com.sun.star.text.WrapTextMode.

The method dispose() of the XComponent interface deletes the object from the document. Since a text content is an XComponent, com.sun.star.lang.XEventListener can be added or removed with the methods addEventListener() and removeEventListener(). These methods are called back when the object is disposed. Other events are not supported.

The method getAnchor() at the XTextContent interface returns a text range which reflects the text position where the object is located. This method may return a void object, for example, for text frames that are bound to a page. The method getAnchor() is used in situations where an XTextRange is required. For instance, placeholder fields (com.sun.star.text.textfield.JumpEdit)  can be filled out using their getAnchor() method. Also, yo can get a bookmark, retrieve its XTextRange from getAnchor() and use it to insert a string at the bookmark position.

The method attach() is an intended method to attach text contents to the document, but it is currently not implemented.

All text contents—including paragraphs—can be created by the service manager of the document. They are created using the factory methods createInstance() or createInstanceWithArguments() at the com.sun.star.lang.XMultiServiceFactory interface of the document.

All text contents—except for paragraphs—can be inserted into text using the com.sun.star.text.XText method insertTextContent(). They can be removed by calling removeTextContent(). Starting with the section 8.3.4 Text Documents - Working with Text Documents - Tables, there are code samples showing the usage of the document service manager with  insertTextContent().

void insertTextContent( [in] com::sun::star::text::XTextRange xRange,

                        [in] com::sun::star::text::XTextContent xContent, boolean bAbsorb);

void removeTextContent( [in] com::sun::star::text::XTextContent xContent)  

Paragraphs cannot be inserted by insertTextContent(). Only the interface XRelativeTextContentInsert can insert paragraphs. A paragraph created by the service manager can be used for creating a new paragraph before or after a table, or a text section positioned at the beginning or the end of page where no cursor can insert new paragraphs. Cf. the section 8.3.1 Text Documents - Working with Text Documents - Word Processing - Inserting a Paraqraph where no Cursor can go below.

Control Characters

We have used Java escape sequences for paragraph breaks, but this may not be feasible in every language. Moreover, OpenOffice.org supports a number of control characters that can be used. There are two possibilities: use the method  

void insertControlCharacter( [in] com::sun::star::text::XTextRange xRange,
                            [in] short nControlCharacter,

                             [in] boolean bAbsorb)

to insert single control characters as defined in the constants group com.sun.star.text.ControlCharacter, or use the corresponding unicode character from the following list as escape sequence in a string if your language supports it. In Java, Unicode characters in strings can be incorporated using the \uHHHH escape sequence, where H represents a hexadecimal digit

PARAGRAPH_BREAK

Insert a paragraph break (UNICODE  0x000D).

LINE_BREAK

Inserts a line break inside of the paragraph (UNICODE  0x000A).

HARD_HYPHEN

A character that appears like a dash, but prevents hyphenation at its position  (UNICODE 0x2011).

SOFT_HYPHEN

Marks a preferred position for hyphenation (UNICODE  0x00AD).

HARD_SPACE

A character that appears like a space, but prevents hyphenation at this point (UNICODE  0x00A0).

APPEND_PARAGRAPH

A new paragraph is appended (no UNICODE for this function). 

The section 8.3.2 Text Documents - Working with Text Documents - Formatting describes how page breaks are created by setting certain paragraph properties.

Iterating over Text

The second interface of com.sun.star.text.Text is XEnumerationAccess. AText service enumerates all paragraphs in a text and returns objects which support com.sun.star.text.Paragraph. This includes tables, because writer sees tables as specialized paragraphs that support the com.sun.star.text.TextTable service.

Paragraphs also have an com.sun.star.container.XEnumerationAccess of their own. They can enumerate every single text portion that they contain. A text portion is a text range containing a uniform piece of information that appears within the text flow. An ordinary paragraph, formatted in a uniform manner and containing nothing but a string, enumerates just a single text portion. In a paragraph that has specially formatted words or other contents, the text portion enumeration  returns one com.sun.star.text.TextPortion service for each differently formatted string, and for every other text content. Text portions include the service com.sun.star.text.TextRange and have the properties listed below:

Properties of com.sun.star.text.TextPortion

TextPortionType

string Contains the type of the text portion (see below).

ControlCharacter

short Returns the control character if the text portion contains a control character as defined in com.sun.star.text.ControlCharacter.

Bookmark

com.sun.star.text.XTextContent. Contains the bookmark if the portion has TextPortionType="Bookmark".

IsCollapsed

boolean Determines whether the portion is a point only.

IsStart

boolean Determines whether the portion is a start portion if two portions are needed to include an object, that is, DocmentIndexMark.

Possible Values for TextPortionType are:

TextPortionType (String) 

Description 

“Text” 

a portion with mere string content 

“TextField” 

A com.sun.star.text.TextField content.

“TextContent” 

A text content supplied through the interface XContentEnumerationAccess.

“Footnote” 

A footnote or an endnote. 

“ControlCharacter” 

A control character. 

“ReferenceMark” 

A reference mark. 

“DocumentIndexMark” 

A document index mark. 

“Bookmark” 

A bookmark. 

“Redline” 

A redline portion which is a result of the change tracking feature. 

“Ruby” 

A ruby attribute which is used in Asian text. 

The text portion enumeration of a paragraph does not supply contents which do belong to the paragraph, but do not fuse together with the text flow. These could be text frames, graphic objects, embedded objects or drawing shapes anchored at the paragraph, characters or as character. The TextPortionType "TextContent" indicate if there is a content anchored at a character or as a character. If you have a TextContent portion type, you know that there are shape objects anchored at a character or as a character.

This last group of data contained in a text, Paragraphs and TextPortions in writer support the interface com.sun.star.container.XContentEnumerationAccess. This interface tells which text contents besides the text flow contents there are and supplies them as an   com.sun.star.container.XEnumeration:

sequence< string > getAvailableServiceNames()

com::sun::star::container::XEnumeration createContentEnumeration( [in] string aServiceName)

The XContentEnumerationAccess of the paragraph lists the shape objects anchored at the paragraph while the XContentEnumerationAccess lists the shape objects anchored at a character or as a  character.

Note graphics marks a special text section

Precisely the same enumerations are available for the current text cursor selection. The text cursor enumerates paragraphs, text portions and text contents just like the service com.sun.star.text.Text itself.

The enumeration access to text through paragraphs and text portions is used if every single paragraph in a text needs to be touched. The application area for this enumeration are export filters,  that uses this enumeration to go over the whole document, writing out the paragraphs to the target file. The following code snippet centers all paragraphs in a text. (Text/TextDocuments.java)

/** This method demonstrates how to iterate over paragraphs */ 

protected void ParagraphExample () { 

    try {

        // The service 'com.sun.star.text.Text' supports the XEnumerationAccess interface to

        // provide an enumeration

        // of the paragraphs contained by the text the service refers to.

 

        // Here, we access this interface

        XEnumerationAccess xParaAccess = (XEnumerationAccess) UnoRuntime.queryInterface(

            XEnumerationAccess.class, mxDocText);

        // Call the XEnumerationAccess's only method to access the actual Enumeration

        XEnumeration xParaEnum = xParaAccess.createEnumeration();

 

        // While there are paragraphs, do things to them

        while (xParaEnum.hasMoreElements()) {

            // Get a reference to the next paragraphs XServiceInfo interface. TextTables

            // are also part of this

            // enumeration access, so we ask the element if it is a TextTable, if it

            // doesn't support the

            // com.sun.star.text.TextTable service, then it is safe to assume that it

            // really is a paragraph

            XServiceInfo xInfo = (XServiceInfo) UnoRuntime.queryInterface(

                XServiceInfo.class, xParaEnum.nextElement());

            if (!xInfo.supportsService("com.sun.star.text.TextTable")) {

                // Access the paragraph's property set...the properties in this

                // property set are listed

                // in: com.sun.star.style.ParagraphProperties

                XPropertySet xSet = (XPropertySet) UnoRuntime.queryInterface(

                    XPropertySet.class, xInfo);

                // Set the justification to be center justified

                xSet.setPropertyValue("ParaAdjust", com.sun.star.style.ParagraphAdjust.CENTER);

            }

        }

    } catch (Exception e) {

                e.printStackTrace (System.out);

    }

Inserting a Paragraph where no Cursor can go

The service com.sun.star.text.Text has an optional interface com.sun.star.text.XRelativeTextContentInsert which is available in Text services in writer. The intention of this interface is to insert paragraphs in positions where no cursor or text portion can be located to use the insertTextContent() method. These situation occurs when text sections or text tables are at the start or end of the document, or if they follow each other directly.

void insertTextContentBefore( [in] com::sun::star::text::XTextContent xNewContent,

                              [in] com::sun::star::text::XTextContent xSuccessor)

void insertTextContentAfter( [in] com::sun::star::text::XTextContent xNewContent,

                             [in] com::sun::star::text::XTextContent xPredecessor)

The only supported text contents are com.sun.star.text.Paragraph as new content, and com.sun.star.text.TextSection and com.sun.star.text.TextTable as successor or predecessor.      

Sorting Text

It is possible to sort text or the content of text tables.  

Sorting of text is done by the text cursor that supports com.sun.star.util.XSortable. It contains two methods:

sequence< com::sun::star::beans::PropertyValue > createSortDescriptor()

void sort( [in] sequence< com::sun::star::beans::PropertyValue > xDescriptor)

The method createSortDescriptor() returns a sequence of com.sun.star.beans.PropertyValue that provides the elements as described in the service com.sun.star.text.TextSortDescriptor

The method sort() sorts the text that is selected by the cursor, by the given parameters.

Sorting of tables happens directly at the table service, which supports XSortable. Sorting is a common feature of OpenOffice.org and it is described in detail in 7 Office Development.

Inserting Text Files

The text cursor in writer supports the interface com.sun.star.document.XDocumentInsertable which has a single method to insert a file at the current cursor position:

void insertDocumentFromURL( [in] string aURL,  

                            [in] sequence< com::sun::star::beans::PropertyValue > aOptions)

Pass a URL and an empty sequence of PropertyValue structs. However, load properties could be used as described in com.sun.star.document.MediaDescriptor.

Auto Text

The auto text function can be used to organize reusable text passages. They allow storing text, including the formatting and all other contents in a text block collection to apply them later. Three services deal with auto text in OpenOffice.org:  

/** Insert an autotext at the current cursor position of given cursor mxDocCursor*/ 

 

// Get an XNameAccess interface to all auto text groups from the document factory 

XNameAccess xContainer = (XNameAccess) UnoRuntime.queryInterface(  

    XNameAccess.class, mxFactory.createInstance("com.sun.star.text.AutoTextContainer"));

 

// Get the autotext group Standard 

xGroup = (XAutoTextGroup) UnoRuntime.queryInterface( 

    XAutoTextGroup.class, xContainer.getByName("Standard"));

 

// get the entry Best Wishes (BW) 

XAutoTextEntry xEntry = (XAutoTextEntry)UnoRuntime.queryInterface (  

    XAutoTextEntry.class, xGroup.getByName ("BW"));

 

// insert the modified autotext block at the cursor position 

xEntry.applyTo(mxDocCursor); 

 

 

 

/** Add a new autotext entry to the AutoTextContainer 

*/ 

// Select the last paragraph in the document 

xParaCursor.gotoPreviousParagraph(true); 

 

// Get the XAutoTextContainer interface of the AutoTextContainer service 

XAutoTextContainer xAutoTextCont = (XAutoTextContainer) UnoRuntime.queryInterface( 

    XAutoTextContainer.class, xContainer );

 

// If the APIExampleGroup already exists, remove it so we can add a new one 

if (xContainer.hasByName("APIExampleGroup")) 

    xAutoTextCont.removeByName("APIExampleGroup" );

 

// Create a new auto-text group called APIExampleGroup 

XAutoTextGroup xNewGroup = xAutoTextCont.insertNewByName ( "APIExampleGroup" ); 

 

// Create and insert a new auto text entry containing the current cursor selection 

XAutoTextEntry xNewEntry = xNewGroup.insertNewByName( 

    "NAE", "New AutoTextEntry", xParaCursor);

 

// Get the XSimpleText and XText interfaces of the new autotext block 

    XSimpleText xSimpleText = (XSimpleText) UnoRuntime.queryInterface(

        XSimpleText.class, xNewEntry);

XText xText = (XText) UnoRuntime.queryInterface(XText.class, xNewEntry); 

 

// Insert a string at the beginning of the autotext block 

xSimpleText.insertString(xText.getStart(),  

    "This string was inserted using the API!\n\n", false);

The current implementation forces the user to close the AutoTextEntry instance when they are changed, so that the changes can take effect.  However, the new AutoText is not written to disk until the destructor of the  AutoTextEntry instance inside the writer is called. When this example has finished executing, the file on disk correctly contains the complete text "This string was inserted using the API!\n\nSome text for a new autotext block", but there is no way in Java to call the destructor. It is not clear when the garbage collector deletes the object and writes the modifications to disk.

8.3.2  Formatting

A multitude of character, paragraph and other properties are available for text in OpenOffice.org. However, the objects implemented in the writer do not provide properties that support com.sun.star.beans.XPropertyChangeListener or com.sun.star.beans.XVetoableChangeListener yet.

Character and paragraph properties are available in the following services:

Services supporting Character
and Paragraph  Properties

Remark 

com.sun.star.text.TextCursor

If collapsed, the CharacterProperties refer to the position on the right hand side of the cursor.

com.sun.star.text.Paragraph

 

com.sun.star.text.TextPortion

 

com.sun.star.text.TextTableCursor

 

com.sun.star.text.Shape

 

com.sun.star.table.CellRange

In text tables. 

com.sun.star.text.TextDocument

The model offers a selected number of character properties which apply to the entire document. These are: CharFontName,CharFontStyleName, CharFontFamily, CharFontCharSet, CharFontPitch and their Asian counterparts CharFontStyleNameAsian, CharFontFamilyAsian, CharFontCharSetAsian, CharFontPitchAsian.

The character properties are described in the services com.sun.star.style.CharacterProperties, com.sun.star.style.CharacterPropertiesAsian and com.sun.star.style.CharacterPropertiesComplex.

com.sun.star.style.CharacterProperties describes common character properties for all language zones and character properties in Western text. The following table provides possible values.

Properties of com.sun.star.style.CharacterProperties

CharFontName

string This property specifies the name of the font in western text.

CharFontStyleName

string  This property contains the name of the font style.

CharFontFamily

short This property contains font family that is specified in com.sun.star.awt.FontFamily. Possible values are: DONTKNOW, DECORATIVE, MODERN, ROMAN, SCRIPT, SWISS, and SYSTEM.

CharFontCharSet

short  This property contains the text encoding of the font that is specified in com.sun.star.awt.CharSet. Possible values are: DONTKNOW, ANSI MAC, IBMPC_437, IBMPC_850, IBMPC_860, IBMPC_861, IBMPC_863, IBMPC_865, and SYSTEM SYMBOL.

CharFontPitch

short  This property contains the font pitch that is specified in com.sun.star.awt.FontPitch. The word font pitch refers to characters per inch, but the possible values are  DONTKNOW, FIXED and VARIABLE. VARIABLE points to the difference between proportional and unproportional fonts.

CharColor

long  This property contains the value of the text color in ARGB notation. ARGB has four bytes denoting alpha, red, green and blue. In hex notation, this can be used conveniently: 0xAARRGGBB. The AA (Alpha) can be 00 or left out.

CharEscapement

[optional] short  Property which contains the relative value of the character height in subscription or superscription.

CharHeight

float This value contains the height of the characters in point.

CharUnderline

short This property contains the value for the character underline that is specified in com.sun.star.awt.FontUnderline. A lot of underline types are available. Some possible values are SINGLE, DOUBLE, and DOTTED.

CharWeight

float This property contains the value of the font weight, cf. [com.sun.star.awt.FontWeight. A lot of weights are possible. The common ones are BOLD and NORMAL.

CharPosture

long This property contains the posture of the font as defined in com.sun.star.awt.FontSlant. The most common values are ITALIC and NONE.

CharAutoKerning

[optional] boolean Property to determine whether the kerning tables from the current font are used.

CharBackColor

[optional] long</