<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE script:module PUBLIC "-//OpenOffice.org//DTD OfficeDocument 1.0//EN" "module.dtd">
<script:module xmlns:script="http://openoffice.org/2000/script" script:name="sw_SwXStyle" script:language="StarBasic">


'*************************************************************************
'
'  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.
'
'*************************************************************************






' REQUIRED VARIABLES for interface/service tests:

' Requiered for  com.sun.star.container.XNamed
 Global cNameToSet As String ' "fixed" if name is fixed
' Requiered for  com.sun.star.style.XStyle
Global oStandartStyle As Variant


Sub CreateObj()

'*************************************************************************
' COMPONENT: 
' sw.SwXStyle
'*************************************************************************
On Error Goto ErrHndl

    Dim bOK As Boolean
    bOK = true

    oDoc = utils.createDocument("swriter", cObjectName)

    oCursor = oDoc.Text.createTextCursor()

    oStyleFamilies = oDoc.StyleFamilies
    aElementNames() = oStyleFamilies.Elementnames

    oDoc.Text.insertString(oCursor, "Elements of StyleFamlilies are:", false)
    oDoc.Text.insertControlCharacter(oCursor, 0, false)

    for i = lBound(aElementNames()) to uBound(aElementNames())
        oCursor.gotoEnd(false)
        oDoc.Text.insertString(oCursor, aElementNames(i), false)
        oDoc.Text.insertControlCharacter(oCursor, 0, false)
    next i


    oObj = oStyleFamilies.getByIndex(0)

    oDoc.Text.insertControlCharacter(oCursor, 0, false)
    oCursor.gotoEnd(false)

    oDoc.Text.insertString(oCursor,"Elements of StyleFamlilie " &amp; aElementNames(0) &amp; "  are:", false)
    oDoc.Text.insertControlCharacter(oCursor, 0, false)

    aElementNames() = oObj.Elementnames
    for i = lBound(aElementNames()) to uBound(aElementNames())
        oCursor.gotoEnd(false)
        oDoc.Text.insertString(oCursor, aElementNames(i), false)
        oDoc.Text.insertControlCharacter(oCursor, 0, false)
    next i

    oNew = oDoc.createInstance("com.sun.star.style.CharacterStyle")
    oStyleFamily = oStyleFamilies.getByIndex(0)'
    oStyleFamily.insertByName("Dummy", oNew)

    oObj = oStyleFamily.getByName("Dummy")

    'Use the style...
    oCursor.setPropertyValue("CharStyleName", "Dummy")

    oStandartStyle = oStyleFamily.getByName(aElementNames(1))


Exit Sub
ErrHndl:
    Test.Exception()
End Sub
</script:module>
