1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <drawingml/textfield.hxx>
21 
22 #include <list>
23 
24 #include <rtl/ustring.hxx>
25 #include <rtl/string.hxx>
26 #include <sal/log.hxx>
27 #include <com/sun/star/beans/XPropertySet.hpp>
28 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
29 #include <com/sun/star/text/XTextField.hpp>
30 
31 #include <oox/helper/helper.hxx>
32 #include <oox/helper/propertyset.hxx>
33 #include <oox/core/xmlfilterbase.hxx>
34 #include <drawingml/textparagraphproperties.hxx>
35 #include <drawingml/textcharacterproperties.hxx>
36 #include <tools/diagnose_ex.h>
37 
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::text;
41 using namespace ::com::sun::star::beans;
42 using namespace ::com::sun::star::frame;
43 using namespace ::com::sun::star::lang;
44 
45 namespace oox { namespace drawingml {
46 
TextField()47 TextField::TextField()
48 {
49 }
50 
51 namespace {
52 
53 /** instantiate the textfields. Because of semantics difference between
54  * OpenXML and OpenOffice, some OpenXML field might cause two fields to be created.
55  * @param aFields the created fields. The list is empty if no field has been created.
56  * @param xModel the model
57  * @param sType the OpenXML field type.
58  */
lclCreateTextFields(std::vector<Reference<XTextField>> & aFields,const Reference<XModel> & xModel,const OUString & sType)59 void lclCreateTextFields( std::vector< Reference< XTextField > > & aFields,
60                                                             const Reference< XModel > & xModel, const OUString & sType )
61 {
62     Reference< XInterface > xIface;
63     Reference< XMultiServiceFactory > xFactory( xModel, UNO_QUERY_THROW );
64     if( sType.startsWith("datetime"))
65     {
66         OString s = OUStringToOString( sType, RTL_TEXTENCODING_UTF8);
67         OString p( s.pData->buffer + 8 );
68         try
69         {
70             if(p.startsWith("'"))
71             {
72                 xIface = xFactory->createInstance( "com.sun.star.text.TextField.Custom" );
73                 aFields.emplace_back( xIface, UNO_QUERY );
74                 return;
75             }
76             bool bIsDate = true;
77             int idx = p.toInt32();
78             sal_uInt16 nNumFmt;
79             xIface = xFactory->createInstance( "com.sun.star.text.TextField.DateTime" );
80             aFields.emplace_back( xIface, UNO_QUERY );
81             Reference< XPropertySet > xProps( xIface, UNO_QUERY_THROW );
82 
83             // here we should format the field properly. waiting after #i81091.
84             switch( idx )
85             {
86             case 1: // Date dd/mm/yyyy
87                 // this is the default format...
88                 nNumFmt = 5;
89                 xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
90                 break;
91             case 2: // Date Day, Month dd, yyyy
92                 break;
93             case 3: // Date dd Month yyyy
94                 nNumFmt = 3;
95                 xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
96                 break;
97             case 4: // Date Month dd, yyyy
98                 break;
99             case 5: // Date dd-Mon-yy
100                 break;
101             case 6: // Date Month yy
102                 break;
103             case 7: // Date Mon-yy
104                 break;
105             case 8: // DateTime dd/mm/yyyy H:MM PM
106                 lclCreateTextFields( aFields, xModel, "datetime12" );
107                 break;
108             case 9: // DateTime dd/mm/yy H:MM:SS PM
109                 lclCreateTextFields( aFields, xModel, "datetime13" );
110                 break;
111             case 10: // Time H:MM
112                 bIsDate = false;
113                 nNumFmt = 3;
114                 xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
115                 break;
116             case 11: // Time H:MM:SS
117                 bIsDate = false;
118                 // this is the default format
119                 nNumFmt = 2;
120                 xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
121                 break;
122             case 12: // Time H:MM PM
123                 bIsDate = false;
124                 nNumFmt = 6;
125                 xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
126                 break;
127             case 13: // Time H:MM:SS PM
128                 bIsDate = false;
129                 nNumFmt = 7;
130                 xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
131                 break;
132             default:
133                 nNumFmt = 2;
134                 xProps->setPropertyValue("NumberFormat", makeAny(nNumFmt));
135             }
136             xProps->setPropertyValue( "IsDate", makeAny( bIsDate ) );
137             xProps->setPropertyValue( "IsFixed", makeAny( false ) );
138         }
139         catch(const Exception &)
140         {
141             TOOLS_WARN_EXCEPTION("oox", "");
142         }
143     }
144     else if ( sType == "slidenum" )
145     {
146         xIface = xFactory->createInstance( "com.sun.star.text.TextField.PageNumber" );
147         aFields.emplace_back( xIface, UNO_QUERY );
148     }
149     else if ( sType == "slidecount" )
150     {
151         xIface = xFactory->createInstance( "com.sun.star.text.TextField.PageCount" );
152         aFields.emplace_back( xIface, UNO_QUERY );
153     }
154     else if ( sType == "slidename" )
155     {
156         xIface = xFactory->createInstance( "com.sun.star.text.TextField.PageName" );
157         aFields.emplace_back( xIface, uno::UNO_QUERY );
158     }
159     else if ( sType.startsWith("file") )
160     {
161         OString s = OUStringToOString( sType, RTL_TEXTENCODING_UTF8);
162         OString p( s.pData->buffer + 4 );
163         int idx = p.toInt32();
164         xIface = xFactory->createInstance( "com.sun.star.text.TextField.FileName" );
165         aFields.emplace_back( xIface, UNO_QUERY );
166         Reference< XPropertySet > xProps( xIface, UNO_QUERY_THROW );
167 
168         switch( idx )
169         {
170             case 1: // Path
171                 xProps->setPropertyValue("FileFormat", makeAny<sal_Int16>(1));
172                 break;
173             case 2: // File name without extension
174                 xProps->setPropertyValue("FileFormat", makeAny<sal_Int16>(2));
175                 break;
176             case 3: // File name with extension
177                 xProps->setPropertyValue("FileFormat", makeAny<sal_Int16>(3));
178                 break;
179             default: // Path/File name
180                 xProps->setPropertyValue("FileFormat", makeAny<sal_Int16>(0));
181         }
182     }
183     else if( sType == "author" )
184     {
185         xIface = xFactory->createInstance( "com.sun.star.text.TextField.Author" );
186         aFields.emplace_back( xIface, UNO_QUERY );
187     }
188 }
189 
190 } // namespace
191 
insertAt(const::oox::core::XmlFilterBase & rFilterBase,const Reference<XText> & xText,const Reference<XTextCursor> & xAt,const TextCharacterProperties & rTextCharacterStyle,float) const192 sal_Int32 TextField::insertAt(
193         const ::oox::core::XmlFilterBase& rFilterBase,
194         const Reference < XText > & xText,
195         const Reference < XTextCursor > &xAt,
196         const TextCharacterProperties& rTextCharacterStyle,
197         float /*nDefaultCharHeight*/) const
198 {
199     sal_Int32 nCharHeight = 0;
200     try
201     {
202         PropertyMap aioBulletList;
203         Reference< XPropertySet > xProps( xAt, UNO_QUERY);
204         PropertySet aPropSet( xProps );
205 
206         maTextParagraphProperties.pushToPropSet( &rFilterBase, xProps, aioBulletList, nullptr, true, 18 );
207 
208         TextCharacterProperties aTextCharacterProps( rTextCharacterStyle );
209         aTextCharacterProps.assignUsed( maTextParagraphProperties.getTextCharacterProperties() );
210         aTextCharacterProps.assignUsed( getTextCharacterProperties() );
211         if ( aTextCharacterProps.moHeight.has() )
212             nCharHeight = aTextCharacterProps.moHeight.get();
213         aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase );
214 
215         std::vector< Reference< XTextField > > fields;
216         lclCreateTextFields( fields, rFilterBase.getModel(), msType );
217         if( !fields.empty() )
218         {
219             bool bFirst = true;
220             for (auto const& field : fields)
221             {
222                 if( field.is() )
223                 {
224                     Reference< XTextContent > xContent( field, UNO_QUERY);
225                     if( bFirst)
226                     {
227                         bFirst = false;
228                     }
229                     else
230                     {
231                         xText->insertString( xAt, " ", false );
232                     }
233                     xText->insertTextContent( xAt, xContent, false );
234                 }
235             }
236         }
237         else
238         {
239             xText->insertString( xAt, getText(), false );
240         }
241     }
242     catch( const Exception&  )
243     {
244         TOOLS_WARN_EXCEPTION("oox", "OOX:  TextField::insertAt()");
245     }
246 
247     return nCharHeight;
248 }
249 
250 } }
251 
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
253