/******************************************************************************/
/**************************TEMPLATE HANDLING TOOL******************************/
/*****************************by Michael Kauril********************************/



-- Import of all needed Java classes
.bsf~bsf.import("java.awt.GridLayout","GridLayout")
.bsf~bsf.import("java.awt.GridBagLayout","GridBagLayout")
.bsf~bsf.import("java.awt.Toolkit","Toolkit")
.bsf~bsf.import("java.awt.ScrollPane","ScrollPane")
.bsf~bsf.import("java.awt.FlowLayout","FlowLayout")
.bsf~bsf.import("java.awt.GraphicsEnvironment", "GraphicsEnvironment")
.bsf~bsf.import("javax.swing.JFrame","JFrame")
.bsf~bsf.import("javax.swing.JLabel","JLabel")
.bsf~bsf.import("javax.swing.JRadioButton","JRadio")
.bsf~bsf.import("javax.swing.ImageIcon","Icon")
.bsf~bsf.import("javax.swing.JWindow","JWindow")
.bsf~bsf.import("javax.swing.JPanel","JPanel")
.bsf~bsf.import("javax.swing.JButton","JButton")
.bsf~bsf.import("javax.swing.JOptionPane", "JOptionPane")
.bsf~bsf.import("javax.swing.border.BevelBorder", "BevelBorder")
.bsf~bsf.import("javax.swing.border.EtchedBorder", "EtchedBorder")



Call create_gui



::Requires BSF.CLS        -- Make oo-like BSF4Rexx support available
::Requires UNO.CLS        -- Get UNO support
::Requires RXREGEXP.CLS   -- Get the support of regular expressions
::Routine makeUrl         -- operating system independent
Return  ConvertToURL(stream(arg(1), "c", "query exists"))
Exit




/******************************************************************************/
---------------------------------ROUTINES---------------------------------------
/******************************************************************************/


/***************************ROUTINE create_gui*********************************/

::Routine create_gui
-- Create a java swing menu with radiobuttons
-- Create java swing objects
label   = .JLabel~new("BITTE TREFFEN SIE EINE AUSWAHL:");
label2  = .JLabel~new("---------------------------------------------------------------------------")

label3  = .JLabel~new("Klicken Sie 'AKTUELL' zum Erstellen eines neuen Dokumentes");
label4  = .JLabel~new("Klicken Sie 'HISTORISCH' zum Laden eines alten Dokumentes");
window  = .JWindow~new();
labelp  = .JPanel~new();
buttonp1  = .JPanel~new();
jbutton1 = .JButton~new("AKTUELL");
jbutton2 = .JButton~new("HISTORISCH");
jbutton3 = .JButton~new("ABBRECHEN");

buttonp2 = .JPanel~new();
bevelborder = .BevelBorder~new(0)

-- Set the Layout and add objects to jpanels
labelp~setLayout(.FlowLayout~new())
labelp~~add(label)~~add(label2)~~add(label3)~~add(label4)
buttonp1~setLayout(.FlowLayout~new())
buttonp1~~add(jbutton1)~~add(jbutton2)
buttonp2~setLayout(.FlowLayout~new())
buttonp2~~add(jbutton3)


-- Set the position of the jwindow to the center of the screen
toolkit=.Toolkit~getDefaultToolkit()
screenSize = Toolkit~getScreenSize()

wx = screenSize~width()/3.2
wy = screenSize~height()/4
Parse var wx wx '.'
Parse var wy wy '.'

If wx<400 then wx=400
If wy<256 then wy=256

w_x = wx/2
w_y = wy/2
Parse var w_x w_x'.'
Parse var w_y w_y'.'
scx = screenSize~width()/2-w_x
scy = screenSize~height()/2-w_y

-- Set the layout of the jwindow and add the jpanels
window~getContentPane()~setLayout(.GridLayout~new(3,1));
window~getContentPane()~setBorder(bevelborder);
window~getContentPane()~~add(labelp)~~add(buttonp1)~~add(buttonp2);

-- Set the location, size and visibility of the jwindow
window~~setLocation(scx,scy)~~setSize(wx,wy)~~setVisible(.true)-
~~setAlwaysOnTop(.true)

-- Add eventlisteners to the jbuttons
jbutton1~bsf.addEventListener("action", "", "Call setnew")
jbutton2~bsf.addEventListener("action", "", "Call setold")
jbutton3~bsf.addEventListener("action", "", "Exit")


/* A never ending loop which execute the messages from the 
   eventhandler as a rexx program*/
Do forever
        event = bsf("pollEventText")
        interpret event
End

Exit


/* Procedure which gets the latest template and opens it
   It is called from the eventhandler by pressing the jbutton "newb" */

setnew:
        window~dispose()  -- Close the open jwindow
        CALL SysFileTree "C:\_templates\*.*", "file", "O" -- Creation of a
        -- stem(="array") of the system file tree of the specified folder

        Do i=1 TO file.0
                PARSE VAR file.i prefix.i =15 filename.i =23 subfix.i -- Extraction 
                -- of the date information out of the full path of the file 
        End

        i=2
        e=1
        f=0

        -- Comparison of the Dates to find out the latest one
        Do Until i > file.0
                If filename.e>filename.i Then e=e-1;
                If filename.e>filename.i Then f=e;
                Else f=i;
                e=e+1
                i=i+1
        End

        .local~filename =  filename.f""subfix.f
        Call main_new
Exit

/* Procedure which opens a new jwindow with a scrollpanel to chose an already created document
   It is called from the eventhandler by pressing the jbutton "oldb" */
setold:
        window~dispose()  -- Close the open jwindow
        CALL SysFileTree "C:\_old\*.*", "file", "O"     -- Creation of a 
        -- stem(="array") of the system file tree of the specified folder

        Do i=1 To file.0
                PARSE VAR file.i prefix.i =9 filename.i       -- Extraction of the date 
                -- information out of the full path of the file 
        End

        -- Create java Swing objects
        label  = .JLabel~new("ÜBERSICHT HISTORISCHER DOKUMENTE");
        label2 = .JLabel~new("------------------------------------------------");
        label3 = .JLabel~new("Bitte wählen Sie ein historisches Dokument aus!");
        window  = .JWindow~new();
        scrollp = .ScrollPane~new()
        jpanel  = .JPanel~new()
        jpanel2 = .JPanel~new()
        mainp   = .JPanel~new()
        jbutton1 = .JButton~new("OK");
        jbutton2 = .JButton~new("ABBRECHEN");
        buttonp = .JPanel~new();
        bevelborder = .BevelBorder~new(0)
        -- Set the Layout and add objects to the jpanels

        Do i=1 To file.0
                jpanel~setLayout(.GridLayout~new(i,2));
                jbutton.i = .JRadio~new(filename.i);
                jpanel~~add(jbutton.i)
                jbutton.i~bsf.addEventListener("action", "", t"=".true)
                jbutton.i~bsf.addEventListener("action", "", f"="i)
        End

        jpanel2~setLayout(.FlowLayout~new());
        jpanel2~~add(label)~~add(label2)~~add(label3)
        scrollp~~add(jpanel)  -- Add the jpanel to the scrollpanel
        buttonp~setLayout(.FlowLayout~new())
        buttonp~~add(jbutton1)~~add(jbutton2)
        mainp~setLayout(.GridLayout~new())
        mainp~add(jpanel2)~add(buttonp)


        -- Set the Gridlayout for the jwindow and add the jpanel and the scrollpanel  
        window~getContentPane()~setLayout(.GridLayout~new(2,1));
        window~getContentPane()~setBorder(bevelborder);
        window~getContentPane()~~add(scrollp)~~add(mainp);

        -- Get the centered position of the jwindow depending on the screenresolution
        toolkit=.Toolkit~getDefaultToolkit()
        screenSize=Toolkit~getScreenSize()


        wx = screenSize~width()/3.4
        wy = screenSize~height()/3.4
        Parse var wx wx '.'
        Parse var wy wy '.'

        If wx<376 Then wx=376
        If wy<301 Then wy=301
        w_x = wx/2
        w_y = wy/2
        Parse var w_x w_x'.'
        Parse var w_y w_y'.'
        scx = screenSize~width()/2-w_x
        scy = screenSize~height()/2-w_y

        -- Set the location and size of the jwindow
        window~~setLocation(scx,scy)~~setSize(wx,wy)~~setVisible(.true)~~setAlwaysOnTop(.true)
        jbutton1~bsf.addEventListener("action", "", "Call open")
        jbutton2~bsf.addEventListener("action", "", "Call create_gui")
        jbutton2~bsf.addEventListener("action", "", "window~dispose()")

        /* A never ending loop which execute the messages from the eventhandler 
           as a rexx program*/
        Do Forever
                event = bsf("pollEventText")
                interpret event
                Call set
        End

Exit

set:

Do e=1 To file.0
          if jbutton.e <> jbutton.f Then jbutton.e~setSelected(.false);
End
return
Exit


open:
        window~dispose()               -- Close the open jwindow
        .local~filename =  filename.f
        if t=.true Then Call main_old
           Else Call setold            -- Start routine main_old
Exit

shutdown:
--window~dispose()                     -- Close the open jwindow
Exit



/******************************ROUTINE main_new********************************/

::Routine main_new  -- Main routine that opens a new template, save the content, 
                    -- export it to pdf and print it

        -- Open the newest template file
        oDesktop         = UNO.createDesktop() -- Get the UNO Desktop service object
        xComponentLoader = oDesktop~XDesktop~XComponentLoader -- Get the XComponent-
                                                              -- Loader interface 

        -- Open the document with the property value hidden
        url              = makeUrl("C:\_templates\".local~filename)
        -- Get the template from the specified folder
        props            = bsf.createArray(.UNO~propertyValue,1)
        props[1]         = .UNO~PropertyValue~new
        props[1]~Name    = "Hidden"
        props[1]~Value   = box("boolean", .true)
        xWriterComponent = xComponentLoader~loadComponentFromURL(url, "_blank", 0, props)
        -- Load the document with specified properties

        xWriterDocument  = xWriterComponent~XTextDocument -- Get the main interface of the textdocument
        xText            = xWriterDocument~getText()      -- Get the text of the document
        xModel           = xWriterDocument~XModel        -- Get the model from the textdocument 
        xController      = xModel~getCurrentController    -- Get the controller for the model

        -- With the help of the controller and XTextViewCursorSupplier we get the TextViewCursor
        xViewCursorSupplier=xController~XTextViewCursorSupplier
        xViewCursor = XViewCursorSupplier~getViewCursor

        -- The XSearchable Interface gives the textdocument the possibility to search the content
        xSearchabel = xWriterDocument~XSearchable
        xSearchDescriptor = xSearchabel~createSearchDescriptor()
        xSearchDescriptor~setSearchString("insert") -- Set the search string for the searchdescriptor
        i=1
        xFound = xSearchabel~findFirst(xSearchDescriptor) -- Find the first matching content
        xFound.i = xFound

        /* Loop which is searching for the searchstring until all matching strings
           are found. It saves the found strings to a stem (=array) variable */
        Do While xfound <> .nil
                .local~i=i
                i=i+1
                xFound = xSearchabel~findNext(xFound, xSearchDescriptor)
                xFound.i = xFound
        End

        i=i-1

        -- Loop which gets the content that is positioned after the searchstring
        Do While i > 0
                xmodel      = xFound.i~XTextRange~getText() /* Get the textrange 
                                                               of each searchstring */
                xposition   = xFound.i~XTextRange~getStart()
                xTextCursor = xmodel~createTextCursorByRange(xposition)
                xViewCursor~gotoRange(xTextCursor,.false)
                xWordCursor = xTextCursor~XWordCursor()

                xWordCursor~gotoendofWord(.true)
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                width.i=xWordCursor~getString() -- Get the width of the textbox 
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                height.i=xWordCursor~getString() -- Get the height of the textbox
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                text.i=xWordCursor~getString()   -- Get the text of the textbox 
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                f_height.i=xWordCursor~getString() -- Get the font height of the textbox
                xWordCursor~gotonextWord(.false)
                xSentenceCursor = xWordCursor~XSentenceCursor()
                xSentenceCursor~gotoendofSentence(.true)
                font.i=xSentenceCursor~getString() -- Get the font of the textbox
                if text.i = "Geschäftsnummer" then .local~number=i

                f.i=xViewCursor~getPosition()  -- Get the coordinates of the searchstring
                i=i-1
        End

        xWriterComponent~dispose()





        -- Open a new document to insert forms and content

        xContext         = UNO.connect()
        -- Get a connection to the server and retrieve the XContext object
        xMCF             = xContext~getServiceManager
        -- Get the XMultiComponentFactory
        oDesktop         = UNO.createDesktop()
        -- Create an UNO Desktop service object
        xComponentLoader = oDesktop~XDesktop~XComponentLoader
        -- Get the componentLoader interface from the desktop object


        -- create a new Writer document
        url              = "private:factory/swriter"
        xWriterComponent = xComponentLoader~loadComponentFromURL(-
        url, "_blank", 0, .UNO~noProps)

        xWriterDocument  = xWriterComponent~XTextDocument
        xText            = xWriterDocument~getText()
        xServiceManager = xWriterDocument~XMultiServiceFactory
        -- Get the service manager of the textdocument

        /* Save objects that are often used in the program as '.local' variables. 
           With this they can be accessed like global variables in the program.  */
        .local~Context         = xContext
        .local~MCF             = xMCF
        .local~ServiceManager  = xServiceManager
        .local~WriterComponent = xWriterComponent
        .local~Text            = xText


        i = .i
        /* Loop that creates textboxes at the position of the searchstrings
           with the specified properties out of the content of the template.*/
        Do While i>0
                textbox.i = create_form("TextField", width.i, height.i, f.i)
                -- Create a textbox with the routine 'create_form'
                textbox.i~setPropertyValue("Text", text.i)
                -- Assign text to the textbox
                textbox.i~setPropertyValue("MultiLine", box("boolean", .true))
                -- Set the textbox multiline
                FontDescriptor        = .bsf~new("com.sun.star.awt.FontDescriptor")
                -- Create a fontdescriptor
                FontDescriptor~Height = f_height.i
                FontDescriptor~Name   = font.i
                textbox.i~setPropertyValue("FontDescriptor", FontDescriptor)
                -- Assign the fontdescriptor to control the font
                i=i-1
        End


        xTextCursor       = xText~createTextCursor() -- Create a TextCursor within the document
        .local~TextCursor = xTextCursor
        xTextCursor~XDocumentInsertable~insertDocumentFromURL(-
        "file:///C:/_templates/".local~filename,.UNO~noProps)
        xModel            = xWriterDocument~XModel  -- Get model from the textcomponent
        xController       = xModel~getCurrentController()
        -- Get the controller of the textdocument

        -- Get the XViewCursor with the help of the controller and the XTextViewCursorSupplier
        xViewCursorSupplier = xController~XTextViewCursorSupplier
        xViewCursor         = XViewCursorSupplier~getViewCursor()
        .local~ViewCursor   = xViewCursor

        i=.i
        -- Loop which replaces all keywords of the template used for inserting textboxes
        Do While i > 0
                xReplaceable       = xWriterDocument~XReplaceable
                xReplaceDescriptor = xReplaceable~createReplaceDescriptor()
                -- Create the replacedescriptor with the XReplaceable interface 
                xReplaceDescriptor~~setSearchString("insert "width.i" "height.i" "text.i" "f_height.i" "font.i)-
                ~~setReplaceString("")
                -- Set search and replace string
                xReplaceable~replaceAll(xReplaceDescriptor)
                -- Replace all strings matching the searchstring
                i=i-1
        End

        Call switch_design_mode  -- Switch the design mode from design to live mode
        Call textsection         -- Insert a protected textsection
        Call state_window        -- Open the state info window of the macro

        If .c<>true Then Call main_finish

        Exit





        /* Procedure that finalise the macro after the content is inserted
           and the user has pushed the "FORTSETZEN" button.*/
        main_finish:
        i=.i
        -- Loop that gets all textcontent out of the textboxes 
        Do While i > 0
                tb.i = textbox.i~getPropertyValue("Text")
                i=i-1
        End

        Call switch_design_mode

        i=.i
        -- Loop which changes properties of the textboxes
        Do While i > 0
                textbox.i~setPropertyValue("Border", box("short",0))
                -- Set the border invisible
                textbox.i~setPropertyValue("ReadOnly", box("boolean",.true))
                -- Set the content ReadOnly
                i=i-1
        end

        /********************Saving the document as PDF************************/

        -- Set the storing properties
        xStorable = .WriterComponent~XStorable
        storeprops = bsf.createArray(.UNO~propertyValue, 3)
        storeprops[1] = .UNO~PropertyValue~new
        storeprops[1]~Name  = "FilterName"
        storeprops[1]~Value = "writer_pdf_Export"
        storeprops[2] = .UNO~PropertyValue~new
        storeprops[2]~Name  = "CompressMode"
        storeprops[2]~Value = 2

        xWriterDocument = .WriterComponent~XTextDocument  -- Loading of textdocument
        xText = xWriterDocument~getText()     -- Get the content of the document

        date=date("S")
        e=.number
        file=date"_"tb.e

        .local~file=file

        xStorable~storeToUrl("file:///C:/"file".pdf", storeprops)
        -- Store the document to the specified url


        /********************Printing of the document**************************/

        xPrintable = xWriterComponent~XPrintable
        xPrintable~print(.UNO~noProps)

        CALL SysSleep 1


        xWriterComponent~dispose()   -- Closing of the Document





        /****************Saving the content of the document********************/

        /* This part of the program saves the content of the file to a new
           XML document */

        oDesktop         = UNO.createDesktop() -- Create an UNO Desktop service object
        xComponentLoader = oDesktop~XDesktop~XComponentLoader
        -- Get the componentloader interface from the desktop object

        -- Open a new Writer document in hidden mode
        url              = "private:factory/swriter"
        props            = bsf.createArray(.UNO~propertyValue,1)
        props[1]         = .UNO~PropertyValue~new
        props[1]~Name    = "Hidden"
        props[1]~Value   = box("boolean", .true)
        xWriterComponent = xComponentLoader~loadComponentFromURL(-
        url, "_blank", 0, props) -- Load the document with specified properties

        xWriterDocument  = xWriterComponent~XTextDocument /* Get the main interface 
                                                             of the textdocument */
        xText            = xWriterDocument~getText()      /* Get the text of the 
                                                             document */
        xTextCursor = xText~createTextCursor()            /* Create a TextCursor 
                                                             within the document */

        /* At the beginning of the document it is important to insert the 
           starting tags for the xml file*/
        xText~getEnd()~setstring("<?xml version="'"1.0"'" encoding="'"ISO-8859-1"'"?>")
        xText~insertControlCharacter(xTextCursor,bsf.getConstant(-
        "com.sun.star.text.ControlCharacter","PARAGRAPH_BREAK"),.false)
        xText~getEnd()~setstring("<content>")
        xText~insertControlCharacter(xTextCursor,bsf.getConstant(-
        "com.sun.star.text.ControlCharacter","PARAGRAPH_BREAK"),.false)
        xText~getEnd()~setstring("<template>".filename"</template>")
        xText~insertControlCharacter(xTextCursor,bsf.getConstant(-
        "com.sun.star.text.ControlCharacter","PARAGRAPH_BREAK"),.false)
        xText~getEnd()~setstring("<textfields>")


        i=.i
        e=1
        /* Loop that insert the text of the textboxes and a paragraph 
           breaks per textbox into the new document, additionally it inserts
           xml tags at the beginning and end of a paragraph*/
        Do While e <= i
                xText~insertControlCharacter(xTextCursor,bsf.getConstant(-
                "com.sun.star.text.ControlCharacter","PARAGRAPH_BREAK"),.false)
                xText~getEnd()~setstring("<"text.e">"tb.e"</"text.e">")
                e=e+1
        End

        xText~insertControlCharacter(xTextCursor,bsf.getConstant(-
        "com.sun.star.text.ControlCharacter","PARAGRAPH_BREAK"),.false)
        xText~getEnd()~setstring("</textfields>")
        xText~insertControlCharacter(xTextCursor,bsf.getConstant(-
        "com.sun.star.text.ControlCharacter","PARAGRAPH_BREAK"),.false)
        xText~getEnd()~setstring("</content>")


        /* Set the properties of the document to "Text" to be able to
           save the document as a XML file */
        props            = bsf.createArray(.UNO~propertyValue,1)
        props[1]         = .UNO~PropertyValue~new
        props[1]~Name    = "FilterName"
        props[1]~Value   = "Text"

        -- Store the created document to a specified location with the set properties
        xStorable = xWriterComponent~XStorable
        xStorable~storeToUrl("file:///C:/_old/".file".xml", props)
        xWriterDocument~dispose()

        -- MessageDialog who informs the user that the macro was completed successfully
        window = .JWindow~new()
        jpanel1 = .JPanel~new()
        jpanel2 = .JPanel~new()
        jlabel = .JLabel~new("Das Dokument mit der Bezeichnung '".file -
        "' wurde erfolgreich erstellt")
        jbutton     = .JButton~new("OK");
        bevelborder = .BevelBorder~new(0)

        jpanel1~~add(jlabel)
        jpanel2~~add(jbutton)

        window~getContentPane()~setLayout(.GridLayout~new(2,1));
        window~getContentPane()~setBorder(bevelborder);
        window~getContentPane()~~add(jpanel1)~~add(jpanel2)
        window~~pack()~~setLocationRelativeTo(window)~~setVisible(.true)-
        ~~setAlwaysOnTop(.true)

        jbutton~bsf.addEventListener('action', '', 'call next')
        Do Forever
                event = bsf("pollEventText")
                interpret event
        End



        next:
        window~dispose()
        Exit

        Exit



/****************************ROUTINE main_old**********************************/

::Routine main_old  /* Routine responsible for loading old documents
                       This routine merges the template file and the xml
                       file with the content of the document.*/

        oDesktop         = UNO.createDesktop() -- Create an UNO Desktop service object
        xComponentLoader = oDesktop~XDesktop~XComponentLoader
        -- Get the componentloader interface from the desktop object

        -- Open the content file of an old document in hidden mode
        url              = makeUrl("C:\_old\".filename)
        -- Get the document from the specified folder
        props            = bsf.createArray(.UNO~propertyValue,1)
        props[1]         = .UNO~PropertyValue~new
        props[1]~Name    = "Hidden"
        props[1]~Value   = box("boolean", .true)
        xWriterComponent = xComponentLoader~loadComponentFromURL(url, "_blank", 0, props)

        xWriterDocument  = xWriterComponent~XTextDocument
        -- Get the main interface of the textdocument
        xText            = xWriterDocument~getText()
        -- Get the text of the document

        xTextCursor      = xText~createTextCursor()  -- Create a TextCursor
        xWordCursor      = xTextCursor~XWordCursor   -- Create a WordCursor
        xParagraphCursor = xTextCursor~XParagraphCursor -- Create a ParagraphCursor

        -- The ParagraphCursor moves through the document to the needed content
        xParagraphCursor~gotoendofParagraph(.true)
        xParagraphCursor~gotonextParagraph(.false)
        xParagraphCursor~gotoendofParagraph(.true)
        xParagraphCursor~gotonextParagraph(.false)
        xParagraphCursor~gotoendofParagraph(.true)
        file = xParagraphCursor~getString()

        -- The variable is parsed to get the content between the xml tags
        parse var file prefix '>' filename '</'
        xParagraphCursor~gotoendofParagraph(.true)
        xParagraphCursor~gotonextParagraph(.false)
        .local~file = filename


        /* Loop that saves each content of the paragraphes
           of the document to a variable */
        a = .false
        i = 1
        Do While a = .false
                xParagraphCursor~gotonextParagraph(.false)
                xParagraphCursor~gotoendofParagraph(.true)
                textg.i = xTextCursor~getString()
                if textg.i = "</textfields>" then a = .true
                i = i+1
        End

        e = 1

        /* Loop that parse each variable to get the content 
           between the tags of the xml content file */
        Do Until e = i
                parse var textg.e prefix '>' text.e '<'
                e=e+1
        End

        xWriterComponent~dispose()  -- Close the document



        -- Open the template file which is specified in the content file

        oDesktop         = UNO.createDesktop() -- Create an UNO Desktop service object
        xComponentLoader = oDesktop~XDesktop~XComponentLoader
        -- Get the componentloader interface from the desktop object

        -- Open a template file
        url = makeUrl("C:\_templates\".file) -- Get the textdocument from the specified folder
        props = bsf.createArray(.UNO~propertyValue,1)
        props[1] = .UNO~PropertyValue~new
        props[1]~Name  = "Hidden"
        props[1]~Value = box("boolean", .true)
        xWriterComponent = xComponentLoader~loadComponentFromURL(url, "_blank", 0, props)

        xWriterDocument  = xWriterComponent~XTextDocument /* Get the main interface 
                                                             of the textdocument */
        xText            = xWriterDocument~getText() -- Get the text of the document

        xModel           = xWriterDocument~XModel -- Get the model from the textdocument 
        xController      = xModel~getCurrentController -- Get the controller for the model

        /* With the help of the controller and XTextViewCursorSupplier 
           we get the TextViewCursor */
        xViewCursorSupplier = xController~XTextViewCursorSupplier
        xViewCursor         = XViewCursorSupplier~getViewCursor

        /* The XSearchable Interface gives the textdocument the 
           possibility to search the content */
        xSearchabel         = xWriterDocument~xSearchable
        xSearchDescriptor   = xSearchabel~createSearchDescriptor
        xSearchDescriptor~setSearchString("insert")
        i=1
        xFound   = xSearchabel~findFirst(xSearchDescriptor)
        xFound.i = xFound

        /* Loop which is searching for the searchstring within 
           the document and saving the matchings to variables */
        Do While xfound <> .nil
                .local~i=i
                i=i+1
                xFound = xSearchabel~findNext(xFound, xSearchDescriptor)
                xFound.i = xFound
        End

        i=i-1
        -- Loop which gets the content that is positioned after the searchstring
        Do While i > 0
                xmodel      = xFound.i~XTextRange~getText() /* Get the textrange 
                                                               of each searchstring */
                xposition   = xFound.i~XTextRange~getStart()
                xTextCursor = xmodel~createTextCursorByRange(xposition)
                xViewCursor~gotoRange(xTextCursor,.false)
                xWordCursor = xTextCursor~XWordCursor()

                xWordCursor~gotoendofWord(.true)
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                width.i=xWordCursor~getString()  -- Get the width of the textbox
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                height.i=xWordCursor~getString() -- Get the height of the textbox
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                text2.i=xWordCursor~getString()  -- Get the text of the textbox 
                xWordCursor~gotonextWord(.false)
                xWordCursor~gotoendofWord(.true)
                f_height.i=xWordCursor~getString() -- Get the font height of the textbox
                xWordCursor~gotonextWord(.false)
                xSentenceCursor = xWordCursor~XSentenceCursor()
                xSentenceCursor~gotoendofSentence(.true)
                font.i=xSentenceCursor~getString() -- Get the font of the textbox

                f.i=xViewCursor~getPosition() -- Get the coordinates of the searchstring
                i=i-1
        End


        xWriterComponent~dispose()  -- Close the document



        -- Open a new document to insert forms and content

        xContext         = UNO.connect()
        -- Get a connection to the server and retrieve the XContext object
        xMCF             = xContext~getServiceManager -- Get the XMultiComponentFactory
        oDesktop         = UNO.createDesktop() -- Create an UNO Desktop service object
        xComponentLoader = oDesktop~XDesktop~XComponentLoader
        -- Get the componentLoader interface from the desktop object

        -- create a new Writer document
        url              = "private:factory/swriter"
        xWriterComponent = xComponentLoader~loadComponentFromURL(-
        url, "_blank", 0, .UNO~noProps)

        xWriterDocument  = xWriterComponent~XTextDocument
        xText            = xWriterDocument~getText()
        xServiceManager = xWriterDocument~XMultiServiceFactory
        -- Get the service manager of the textdocument

        /* Save objects that are often used in the program as '.local' variables. 
           With this they can be accessed like global variables in the program.  */
        .local~Context         = xContext
        .local~MCF             = xMCF
        .local~ServiceManager  = xServiceManager
        .local~WriterComponent = xWriterComponent
        .local~Text            = xText


        i = .i
        /* Loop that creates textboxes at the position of the searchstrings
           with the specified properties out of the content of the template.*/
        Do While i>0
                textbox.i = create_form("TextField", width.i, height.i, f.i)
                -- Create a textbox with the routine 'create_form'
                textbox.i~setPropertyValue("Text", text.i) -- Assign text to the textbox
                textbox.i~setPropertyValue("MultiLine", box("boolean", .true))
                -- Set the textbox multiline
                FontDescriptor        = .bsf~new("com.sun.star.awt.FontDescriptor")
                -- Create a fontdescriptor
                FontDescriptor~Height = f_height.i
                FontDescriptor~Name   = font.i
                textbox.i~setPropertyValue("FontDescriptor", FontDescriptor)
                -- Assign the fontdescriptor to control the font
                i=i-1
        End


        xTextCursor       = xText~createTextCursor()
        -- Create a TextCursor within the document
        .local~TextCursor = xTextCursor
        xTextCursor~XDocumentInsertable~insertDocumentFromURL(-
        "file:///C:/_templates/".file,.UNO~noProps)
        xModel            = xWriterDocument~XModel -- Get model from the textcomponent
        xController       = xModel~getCurrentController()
        -- Get the controller of the textdocument

        -- Get the XViewCursor with the help of the controller and the XTextViewCursorSupplier
        xViewCursorSupplier = xController~XTextViewCursorSupplier
        xViewCursor         = XViewCursorSupplier~getViewCursor()
        .local~ViewCursor   = xViewCursor

        i=.i
        -- Loop which replaces all keywords of the template used for inserting textboxes
        Do While i > 0
                xReplaceable       = xWriterDocument~XReplaceable
                xReplaceDescriptor = xReplaceable~createReplaceDescriptor()
                -- Create the replacedescriptor with the XReplaceable interface 
                xReplaceDescriptor~~setSearchString("insert "width.i" "height.i" "text2.i" "f_height.i" "font.i)-
                ~~setReplaceString("")
                -- Set search and replace string
                xReplaceable~replaceAll(xReplaceDescriptor)
                -- Replace all strings matching the searchstring
                i=i-1
        End


        Call textsection         -- Insert a protected textsection

        i=.i
        -- Loop which changes properties of the textboxes
        Do While i > 0
                textbox.i~setPropertyValue("Border", box("short",0))
                -- Set the border invisible
                textbox.i~setPropertyValue("ReadOnly", box("boolean",.true))
                -- Set the content ReadOnly
                i=i-1
        End

        Call switch_design_mode  -- Switch the design mode from design to live mode
Exit


/****************************ROUTINE state_window******************************/

::Routine state_window  -- Routine that opens a jwindow which is pausing the macro


        -- create java swing objects
        label    = .JLabel~new("")
        label2   = .JLabel~new("MAKRO ANGEHALTEN",0)
        label3   = .JLabel~new("-------------------------------",0)
        label4   = .JLabel~new("Bitte Inhalt eingeben!",0)
        label5   = .JLabel~new("Um Makro fortzusetzen,",0)
        label6   = .JLabel~new("bitte auf FORTSETZEN klicken!",0)
        window   = .JWindow~new();
        next     = .JButton~new("FORTSETZEN");
        cancel = .JButton~new("ABBRECHEN");
        icon     = .Icon~new("ma.png");
        jbuttonp = .JPanel~new();
        panel1   = .JPanel~new();
        panel2   = .JPanel~new();
        etchedborder = .EtchedBorder~new(0)

        -- set the layout for the jpanels and add objects
        jbuttonp~setLayout(.GridLayout~new(2,1))
        jbuttonp~~add(next)~~add(cancel);
        panel1~setLayout(.GridLayout~new(5,1))
        panel1~~add(label2)~~add(label3)~~add(label4)~~add(label5)~~add(label6)
        panel2~~add(label);


        -- Set the jwindow to use the GridBagLayout and add objects
        window~getContentPane()~setLayout(.GridBagLayout~new());
        window~getContentPane()~setBorder(etchedborder);
        window~getContentPane()~~add(panel1)~~add(jbuttonp)~~add(panel2);

        -- Set the size of the jwindow
        toolkit=.Toolkit~getDefaultToolkit()
        screenSize = Toolkit~getScreenSize()

        boxw = screenSize~width()/3
        boxh = screenSize~height()/7
        Parse var boxw boxw '.'
        Parse var boxh boxh '.'

        If boxw<426 Then boxw=426
        If boxh<146 Then boxh=146


        -- Get the Size of the screen without the task bar
        ge = .GraphicsEnvironment~getLocalGraphicsEnvironment()
        maximumWindowBounds = ge~getMaximumWindowBounds();
        resx= maximumWindowBounds~width()
        resy= maximumWindowBounds~height()

        -- Get the position of the jwindow in the right corner of  the screen
        boxpx = resx - boxw
        boxp = resy - boxh

        -- Set the location, size and visibility of the jwindow
        window~~pack()~~setLocation(boxpx,boxp)~~setSize(boxw,boxh)-
        ~~setVisible(.true)~~setAlwaysOnTop(.true)

        label~setIcon(icon);

        -- Add eventhandling to the jbutton
        next~bsf.addEventListener('action', '', 'Call next')
        cancel~bsf.addEventListener('action', '', ".local~c= true")
        cancel~bsf.addEventListener('action', '', 'Call cancel')


        /* A never ending loop which execute the messages from the 
           eventhandler as a rexx program */
        Do Forever
                event = bsf("pollEventText")
                interpret event
        End

        Exit

        next:
        window~dispose()
        Exit

        cancel:
        window~dispose()
        .WriterComponent~dispose()
        Call create_gui
        Exit


/*************************ROUTINE switch_design_mode***************************/


::Routine switch_design_mode  -- Routine to switch the design mode from design to live mode
        url                    = bsf.loadClass("com.sun.star.util.URL") -- Load the class URL
        aToggleURL             = bsf.createArray(url, 1) -- Create an array to store the URL object
        aToggleURL[1]          = .bsf~new("com.sun.star.util.URL")
        aToggleURL[1]~Complete = ".uno:SwitchControlDesignMode"

        xmodel = .WriterComponent~XModel -- Get the current model of the document
        xController = xmodel~getCurrentController  -- Get the XController interface
        xDispatchProvider = xController~getFrame~XDispatchProvider -- Get the dispatch provider

        -- Use an URLTransformer to parse the url
        frameDesktop = .MCF~createInstanceWithContext("com.sun.star.util.URLTransformer",.Context)
        xURLTransformer = frameDesktop~XURLTransformer -- Initialisation of the XURLTransformer interface
        xURLTransformer~parseStrict(aToggleURL)        -- Parse the url
        xDispatcher = xDispatchProvider~queryDispatch( aToggleURL[1],"", 0 )
        -- Get all dispatcher from the specified url
        xDispatcher~dispatch( aToggleURL[1], .UNO~noProps )
        -- Execute a dispatcher from the given url


/***************************ROUTINE textsection********************************/


::Routine textsection  -- Routine to insert a protected textsection accross the whole document
        .ViewCursor~gotoStart(.false)
        .TextCursor~gotoEnd(.true)      -- Mark the whole document as a TextRange
        xTextSection = .ServiceManager~createInstance("com.sun.star.text.TextSection")
        -- Create an instance of the textsection
        xTextSection~XNamed~setName("xTextSection")  -- Set a name for the textsection
        xTextSectionprops = xTextSection~XPropertySet()
        xTextSectionprops~setPropertyValue("IsProtected",box("boolean",.true))
        -- Set the property value IsProtected  
        TextSection = xTextSection~XTextContent()
        .Text~insertTextContent(.TextCursor,TextSection,.true) -- Insert the textsection


/***************************ROUTINE create_form********************************/


::Routine create_form -- Routine to create and initialize a shape for the document
        xMSF = .WriterComponent~XMultiServiceFactory
        xControlShape = xMSF~createInstance("com.sun.star.drawing.ControlShape")~XControlShape
        -- Create a control shape

        FormComponent = "com.sun.star.form.component."ARG(1)  -- Create a form component
        xControlModel = .MCF~createInstanceWithContext(FormComponent,.Context)~XControlModel
        -- Create a control model

        -- Set the position and size of the form 
        xControlShape~setSize(.bsf~new("com.sun.star.awt.Size", ARG(2)*100, ARG(3)*100))
        -- The size is specified in 100th/mm
        xControlShape~setPosition(ARG(4)) -- Set the position specified in 100th/mm
        xPropertySet = xControlShape~XPropertySet  -- Get the propertyset of the shape
        xPropertySet~setPropertyValue("AnchorType", bsf.getConstant(-
        "com.sun.star.text.TextContentAnchorType", "AT_PARAGRAPH"))
        -- Adjust the anchor to the paragraph

        xControlShape~setControl(xControlModel) -- Set the ControlModel of the shape 

        -- Add the shape to the shapes of the document
        xDrawPageSupplier = .WriterComponent~XDrawPageSupplier
        xDrawPage         = xDrawPageSupplier~getDrawPage()
        xShapes           = xDrawPage~XShapes
        xShapes~add(xControlShape)

        return xControlModel~XPropertySet /* Returns the XPropertySet interface 
                                             to give the possibility of adjustments */