LibreOffice Module sw (master)  1
htmlforw.cxx
Go to the documentation of this file.
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 <com/sun/star/form/FormSubmitEncoding.hpp>
21 #include <com/sun/star/form/FormSubmitMethod.hpp>
22 #include <com/sun/star/form/FormButtonType.hpp>
23 #include <com/sun/star/frame/XModel.hpp>
24 #include <com/sun/star/script/XEventAttacherManager.hpp>
25 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
26 #include <com/sun/star/form/XFormsSupplier.hpp>
27 #include <com/sun/star/form/XForm.hpp>
28 #include <com/sun/star/form/FormComponentType.hpp>
29 #include <com/sun/star/awt/XTextLayoutConstrains.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <hintids.hxx>
32 #include <o3tl/any.hxx>
33 #include <rtl/math.hxx>
34 #include <vcl/svapp.hxx>
35 #include <svl/macitem.hxx>
36 #include <svtools/htmlout.hxx>
37 #include <svtools/htmlkywd.hxx>
38 #include <svl/urihelper.hxx>
39 #include <vcl/unohelp.hxx>
40 #include <svx/svdouno.hxx>
41 #include <editeng/brushitem.hxx>
42 #include <editeng/colritem.hxx>
43 #include <editeng/fhgtitem.hxx>
44 #include <editeng/fontitem.hxx>
45 #include <editeng/wghtitem.hxx>
46 #include <editeng/postitem.hxx>
47 #include <editeng/udlnitem.hxx>
49 #include <osl/diagnose.h>
50 #include <docsh.hxx>
51 #include <fmtanchr.hxx>
52 #include <viewsh.hxx>
53 #include <pam.hxx>
54 #include <doc.hxx>
57 #include "wrthtml.hxx"
58 #include "htmlfly.hxx"
59 #include "htmlform.hxx"
60 #include <frmfmt.hxx>
61 #include <frameformats.hxx>
62 #include <memory>
63 
64 using namespace ::com::sun::star;
65 
79 
80 static void lcl_html_outEvents( SvStream& rStrm,
81  const uno::Reference< form::XFormComponent >& rFormComp,
82  bool bCfgStarBasic,
83  rtl_TextEncoding eDestEnc,
84  OUString *pNonConvertableChars )
85 {
86  uno::Reference< uno::XInterface > xParentIfc = rFormComp->getParent();
87  OSL_ENSURE( xParentIfc.is(), "lcl_html_outEvents: no parent interface" );
88  if( !xParentIfc.is() )
89  return;
90  uno::Reference< container::XIndexAccess > xIndexAcc( xParentIfc, uno::UNO_QUERY );
91  uno::Reference< script::XEventAttacherManager > xEventManager( xParentIfc,
92  uno::UNO_QUERY );
93  if( !xIndexAcc.is() || !xEventManager.is() )
94  return;
95 
96  // and search for the position of the ControlModel within
97  sal_Int32 nCount = xIndexAcc->getCount(), nPos;
98  for( nPos = 0 ; nPos < nCount; nPos++ )
99  {
100  uno::Any aTmp = xIndexAcc->getByIndex(nPos);
101  if( auto x1 = o3tl::tryAccess<uno::Reference<form::XFormComponent>>(aTmp) )
102 
103  {
104  if( rFormComp == *x1 )
105  break;
106  }
107  else if( auto x2 = o3tl::tryAccess<uno::Reference<form::XForm>>(aTmp) )
108  {
109  if( rFormComp == *x2 )
110  break;
111  }
112  else
113  {
114  OSL_ENSURE( false, "lcl_html_outEvents: wrong reflection" );
115  }
116  }
117 
118  if( nPos == nCount )
119  return;
120 
121  const uno::Sequence< script::ScriptEventDescriptor > aDescs =
122  xEventManager->getScriptEvents( nPos );
123  if( !aDescs.hasElements() )
124  return;
125 
126  for( const script::ScriptEventDescriptor& rDesc : aDescs )
127  {
128  ScriptType eScriptType = EXTENDED_STYPE;
129  OUString aScriptType( rDesc.ScriptType );
130  if( aScriptType.equalsIgnoreAsciiCase(SVX_MACRO_LANGUAGE_JAVASCRIPT) )
131  eScriptType = JAVASCRIPT;
132  else if( aScriptType.equalsIgnoreAsciiCase(SVX_MACRO_LANGUAGE_STARBASIC ) )
133  eScriptType = STARBASIC;
134  if( JAVASCRIPT != eScriptType && !bCfgStarBasic )
135  continue;
136 
137  OUString sListener( rDesc.ListenerType );
138  if (!sListener.isEmpty())
139  {
140  const sal_Int32 nIdx { sListener.lastIndexOf('.')+1 };
141  if (nIdx>0)
142  {
143  if (nIdx<sListener.getLength())
144  {
145  sListener = sListener.copy(nIdx);
146  }
147  else
148  {
149  sListener.clear();
150  }
151  }
152  }
153  OUString sMethod( rDesc.EventMethod );
154 
155  const char *pOpt = nullptr;
156  for( int j=0; aEventListenerTable[j]; j++ )
157  {
158  if( sListener.equalsAscii( aEventListenerTable[j] ) &&
159  sMethod.equalsAscii( aEventMethodTable[j] ) )
160  {
161  pOpt = (STARBASIC==eScriptType ? aEventSDOptionTable
162  : aEventOptionTable)[j];
163  break;
164  }
165  }
166 
167  OString sOut = " ";
168  if( pOpt && (EXTENDED_STYPE != eScriptType ||
169  rDesc.AddListenerParam.isEmpty()) )
170  sOut += pOpt;
171  else
172  {
174  OUStringToOString(sListener, RTL_TEXTENCODING_ASCII_US) + "-" +
175  OUStringToOString(sMethod, RTL_TEXTENCODING_ASCII_US);
176  }
177  sOut += "=\"";
178  rStrm.WriteOString( sOut );
179  HTMLOutFuncs::Out_String( rStrm, rDesc.ScriptCode, eDestEnc, pNonConvertableChars );
180  rStrm.WriteChar( '\"' );
181  if( EXTENDED_STYPE == eScriptType &&
182  !rDesc.AddListenerParam.isEmpty() )
183  {
185  OUStringToOString(sListener, RTL_TEXTENCODING_ASCII_US) + "-" +
186  OUStringToOString(sMethod, RTL_TEXTENCODING_ASCII_US) + "=\"";
187  rStrm.WriteOString( sOut );
188  HTMLOutFuncs::Out_String( rStrm, rDesc.AddListenerParam,
189  eDestEnc, pNonConvertableChars );
190  rStrm.WriteChar( '\"' );
191  }
192  }
193 }
194 
195 static bool lcl_html_isHTMLControl( sal_Int16 nClassId )
196 {
197  bool bRet = false;
198 
199  switch( nClassId )
200  {
201  case form::FormComponentType::TEXTFIELD:
202  case form::FormComponentType::COMMANDBUTTON:
203  case form::FormComponentType::RADIOBUTTON:
204  case form::FormComponentType::CHECKBOX:
205  case form::FormComponentType::LISTBOX:
206  case form::FormComponentType::IMAGEBUTTON:
207  case form::FormComponentType::FILECONTROL:
208  bRet = true;
209  break;
210  }
211 
212  return bRet;
213 }
214 
216 {
217  SwNodeOffset nStartIdx = m_pCurrentPam->GetPoint()->nNode.GetIndex();
218  size_t i = 0;
219 
220  // Skip all controls in front of the current paragraph
221  while ( i < m_aHTMLControls.size() && m_aHTMLControls[i]->nNdIdx < nStartIdx )
222  ++i;
223 
224  return i < m_aHTMLControls.size() && m_aHTMLControls[i]->nNdIdx == nStartIdx;
225 }
226 
227 void SwHTMLWriter::OutForm( bool bTag_On, const SwStartNode *pStartNd )
228 {
229  if( m_bPreserveForm ) // we are in a table or an area with form spanned over it
230  return;
231 
232  if( !bTag_On )
233  {
234  // end the form when all controls are output
235  if( mxFormComps.is() &&
236  mxFormComps->getCount() == m_nFormCntrlCnt )
237  {
238  OutForm( false, mxFormComps );
239  mxFormComps.clear();
240  }
241  return;
242  }
243 
244  uno::Reference< container::XIndexContainer > xNewFormComps;
245  SwNodeOffset nStartIdx = pStartNd ? pStartNd->GetIndex()
246  : m_pCurrentPam->GetPoint()->nNode.GetIndex();
247 
248  // skip controls before the interesting area
249  size_t i = 0;
250  while ( i < m_aHTMLControls.size() && m_aHTMLControls[i]->nNdIdx < nStartIdx )
251  ++i;
252 
253  if( !pStartNd )
254  {
255  // Check for a single node: there it's only interesting, if there is
256  // a control for the node and to which form it belongs.
257  if( i < m_aHTMLControls.size() &&
258  m_aHTMLControls[i]->nNdIdx == nStartIdx )
259  xNewFormComps = m_aHTMLControls[i]->xFormComps;
260  }
261  else
262  {
263  // we iterate over a table/an area: we're interested in:
264  // - if there are controls with different start nodes
265  // - if there is a form, with controls which aren't all in the table/area
266 
267  uno::Reference< container::XIndexContainer > xCurrentFormComps;// current form in table
268  const SwStartNode *pCurrentStNd = nullptr; // and the start node of a Control
269  sal_Int32 nCurrentCtrls = 0; // and the found controls in it
270  SwNodeOffset nEndIdx = pStartNd->EndOfSectionIndex();
271  for( ; i < m_aHTMLControls.size() &&
272  m_aHTMLControls[i]->nNdIdx <= nEndIdx; i++ )
273  {
274  const SwStartNode *pCntrlStNd =
275  m_pDoc->GetNodes()[m_aHTMLControls[i]->nNdIdx]->StartOfSectionNode();
276 
277  if( xCurrentFormComps.is() )
278  {
279  // already inside a form ...
280  if( xCurrentFormComps==m_aHTMLControls[i]->xFormComps )
281  {
282  // ... and the control is also inside ...
283  if( pCurrentStNd!=pCntrlStNd )
284  {
285  // ... but it's inside another cell:
286  // Then open a form above the table
287  xNewFormComps = xCurrentFormComps;
288  break;
289  }
290  nCurrentCtrls = nCurrentCtrls + m_aHTMLControls[i]->nCount;
291  }
292  else
293  {
294  // ... but the Control is in another cell:
295  // There we act as if we open a new from and continue searching.
296  xCurrentFormComps = m_aHTMLControls[i]->xFormComps;
297  pCurrentStNd = pCntrlStNd;
298  nCurrentCtrls = m_aHTMLControls[i]->nCount;
299  }
300  }
301  else
302  {
303  // We aren't in a form:
304  // There we act as if we open a form.
305  xCurrentFormComps = m_aHTMLControls[i]->xFormComps;
306  pCurrentStNd = pCntrlStNd;
307  nCurrentCtrls = m_aHTMLControls[i]->nCount;
308  }
309  }
310  if( !xNewFormComps.is() && xCurrentFormComps.is() &&
311  nCurrentCtrls != xCurrentFormComps->getCount() )
312  {
313  // A form should be opened in the table/area which isn't completely
314  // inside the table. Then we must also now open the form.
315  xNewFormComps = xCurrentFormComps;
316  }
317  }
318 
319  if( !(xNewFormComps.is() &&
320  (!mxFormComps.is() || xNewFormComps != mxFormComps)) )
321  return;
322 
323  // A form should be opened ...
324  if( mxFormComps.is() )
325  {
326  // ... but a form is still open: That is in every case an error,
327  // but we'll close the old form nevertheless.
328  OutForm( false, mxFormComps );
329 
331  }
332 
333  mxFormComps = xNewFormComps;
334 
335  OutForm( true, mxFormComps );
336  uno::Reference< beans::XPropertySet > xTmp;
338 }
339 
341 {
342  // Without DrawModel there can't be controls. Then you also can't access the
343  // document via UNO, because otherwise a DrawModel would be created.
345  return;
346 
347  SwDocShell *pDocSh = m_pDoc->GetDocShell();
348  if( !pDocSh )
349  return;
350 
351  uno::Reference< drawing::XDrawPageSupplier > xDPSupp( pDocSh->GetBaseModel(),
352  uno::UNO_QUERY );
353  OSL_ENSURE( xDPSupp.is(), "XTextDocument not received from XModel" );
354  uno::Reference< drawing::XDrawPage > xDrawPage = xDPSupp->getDrawPage();
355 
356  OSL_ENSURE( xDrawPage.is(), "XDrawPage not received" );
357  if( !xDrawPage.is() )
358  return;
359 
360  uno::Reference< form::XFormsSupplier > xFormsSupplier( xDrawPage, uno::UNO_QUERY );
361  OSL_ENSURE( xFormsSupplier.is(),
362  "XFormsSupplier not received from XDrawPage" );
363 
364  uno::Reference< container::XNameContainer > xTmp = xFormsSupplier->getForms();
365  OSL_ENSURE( xTmp.is(), "XForms not received" );
366  uno::Reference< container::XIndexContainer > xForms( xTmp, uno::UNO_QUERY );
367  OSL_ENSURE( xForms.is(), "XForms without container::XIndexContainer?" );
368 
369  sal_Int32 nCount = xForms->getCount();
370  for( sal_Int32 i=0; i<nCount; i++)
371  {
372  uno::Any aTmp = xForms->getByIndex( i );
373  if( auto x = o3tl::tryAccess<uno::Reference<form::XForm>>(aTmp) )
374  OutHiddenForm( *x );
375  else
376  {
377  OSL_ENSURE( false, "OutHiddenForms: wrong reflection" );
378  }
379  }
380 }
381 
382 void SwHTMLWriter::OutHiddenForm( const uno::Reference< form::XForm > & rForm )
383 {
384  uno::Reference< container::XIndexContainer > xFormComps( rForm, uno::UNO_QUERY );
385  if( !xFormComps.is() )
386  return;
387 
388  sal_Int32 nCount = xFormComps->getCount();
389  bool bHiddenOnly = nCount > 0, bHidden = false;
390  for( sal_Int32 i=0; i<nCount; i++ )
391  {
392  uno::Any aTmp = xFormComps->getByIndex( i );
393  auto xFormComp = o3tl::tryAccess<uno::Reference<form::XFormComponent>>(
394  aTmp);
395  OSL_ENSURE( xFormComp, "OutHiddenForm: wrong reflection" );
396  if( !xFormComp )
397  continue;
398 
399  uno::Reference< form::XForm > xForm( *xFormComp, uno::UNO_QUERY );
400  if( xForm.is() )
401  OutHiddenForm( xForm );
402 
403  if( bHiddenOnly )
404  {
405  uno::Reference< beans::XPropertySet > xPropSet( *xFormComp, uno::UNO_QUERY );
406  OUString sPropName("ClassId");
407  if( xPropSet->getPropertySetInfo()->hasPropertyByName( sPropName ) )
408  {
409  uno::Any aAny2 = xPropSet->getPropertyValue( sPropName );
410  if( auto n = o3tl::tryAccess<sal_Int16>(aAny2) )
411  {
412  if( form::FormComponentType::HIDDENCONTROL == *n )
413  bHidden = true;
414  else if( lcl_html_isHTMLControl( *n ) )
415  bHiddenOnly = false;
416  }
417  }
418  }
419  }
420 
421  if( bHidden && bHiddenOnly )
422  {
423  OutForm( true, xFormComps );
424  uno::Reference< beans::XPropertySet > xTmp;
425  OutHiddenControls( xFormComps, xTmp );
426  OutForm( false, xFormComps );
427  }
428 }
429 
430 void SwHTMLWriter::OutForm( bool bOn,
431  const uno::Reference< container::XIndexContainer > & rFormComps )
432 {
433  m_nFormCntrlCnt = 0;
434 
435  if( !bOn )
436  {
437  DecIndentLevel(); // indent content of form
438  if( m_bLFPossible )
439  OutNewLine();
440  HTMLOutFuncs::Out_AsciiTag( Strm(), OStringConcatenation(GetNamespace() + OOO_STRING_SVTOOLS_HTML_form), false );
441  m_bLFPossible = true;
442 
443  return;
444  }
445 
446  // the new form is opened
447  if( m_bLFPossible )
448  OutNewLine();
449  OString sOut = "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_form;
450 
451  uno::Reference< beans::XPropertySet > xFormPropSet( rFormComps, uno::UNO_QUERY );
452 
453  uno::Any aTmp = xFormPropSet->getPropertyValue( "Name" );
454  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
455  {
456  if( !s->isEmpty() )
457  {
458  sOut += " " OOO_STRING_SVTOOLS_HTML_O_name "=\"";
459  Strm().WriteOString( sOut );
462  sOut = "\"";
463  }
464  }
465 
466  aTmp = xFormPropSet->getPropertyValue( "TargetURL" );
467  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
468  {
469  if ( !s->isEmpty() )
470  {
471  sOut += " " OOO_STRING_SVTOOLS_HTML_O_action "=\"";
472  Strm().WriteOString( sOut );
473  OUString aURL
476  sOut = "\"";
477  }
478  }
479 
480  aTmp = xFormPropSet->getPropertyValue( "SubmitMethod" );
481  if( auto eMethod = o3tl::tryAccess<form::FormSubmitMethod>(aTmp) )
482  {
483  if( form::FormSubmitMethod_POST==*eMethod )
484  {
485  sOut += " " OOO_STRING_SVTOOLS_HTML_O_method "=\""
487  }
488  }
489  aTmp = xFormPropSet->getPropertyValue( "SubmitEncoding" );
490  if( auto eEncType = o3tl::tryAccess<form::FormSubmitEncoding>(aTmp) )
491  {
492  const char *pStr = nullptr;
493  switch( *eEncType )
494  {
495  case form::FormSubmitEncoding_MULTIPART:
497  break;
498  case form::FormSubmitEncoding_TEXT:
500  break;
501  default:
502  ;
503  }
504 
505  if( pStr )
506  {
507  sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_enctype "=\"") +
508  pStr + "\"";
509  }
510  }
511 
512  aTmp = xFormPropSet->getPropertyValue( "TargetFrame" );
513  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
514  {
515  if (!s->isEmpty() )
516  {
517  sOut += " " OOO_STRING_SVTOOLS_HTML_O_target "=\"";
518  Strm().WriteOString( sOut );
521  sOut = "\"";
522  }
523  }
524 
525  Strm().WriteOString( sOut );
526  uno::Reference< form::XFormComponent > xFormComp( rFormComps, uno::UNO_QUERY );
528  Strm().WriteChar( '>' );
529 
530  IncIndentLevel(); // indent content of form
531  m_bLFPossible = true;
532 }
533 
535  const uno::Reference< container::XIndexContainer > & rFormComps,
536  const uno::Reference< beans::XPropertySet > & rPropSet )
537 {
538  sal_Int32 nCount = rFormComps->getCount();
539  sal_Int32 nPos = 0;
540  if( rPropSet.is() )
541  {
542  bool bDone = false;
543 
544  uno::Reference< form::XFormComponent > xFC( rPropSet, uno::UNO_QUERY );
545  for( nPos=0; !bDone && nPos < nCount; nPos++ )
546  {
547  uno::Any aTmp = rFormComps->getByIndex( nPos );
548  auto x = o3tl::tryAccess<uno::Reference<form::XFormComponent>>(aTmp);
549  OSL_ENSURE( x,
550  "OutHiddenControls: wrong reflection" );
551  bDone = x && *x == xFC;
552  }
553  }
554 
555  for( ; nPos < nCount; nPos++ )
556  {
557  uno::Any aTmp = rFormComps->getByIndex( nPos );
558  auto xFC = o3tl::tryAccess<uno::Reference<form::XFormComponent>>(aTmp);
559  OSL_ENSURE( xFC,
560  "OutHiddenControls: wrong reflection" );
561  if( !xFC )
562  continue;
563  uno::Reference< beans::XPropertySet > xPropSet( *xFC, uno::UNO_QUERY );
564 
565  OUString sPropName = "ClassId";
566  if( !xPropSet->getPropertySetInfo()->hasPropertyByName( sPropName ) )
567  continue;
568 
569  aTmp = xPropSet->getPropertyValue( sPropName );
570  auto n = o3tl::tryAccess<sal_Int16>(aTmp);
571  if( !n )
572  continue;
573 
574  if( form::FormComponentType::HIDDENCONTROL == *n )
575  {
576  if( m_bLFPossible )
577  OutNewLine( true );
578  OString sOut = "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_input " "
581 
582  aTmp = xPropSet->getPropertyValue( "Name" );
583  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
584  {
585  if( !s->isEmpty() )
586  {
587  sOut += " " OOO_STRING_SVTOOLS_HTML_O_name "=\"";
588  Strm().WriteOString( sOut );
591  sOut = "\"";
592  }
593  }
594  aTmp = xPropSet->getPropertyValue( "HiddenValue" );
595  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
596  {
597  if( !s->isEmpty() )
598  {
599  sOut += " " OOO_STRING_SVTOOLS_HTML_O_value "=\"";
600  Strm().WriteOString( sOut );
603  sOut = "\"";
604  }
605  }
606  sOut += ">";
607  Strm().WriteOString( sOut );
608 
609  m_nFormCntrlCnt++;
610  }
611  else if( lcl_html_isHTMLControl( *n ) )
612  {
613  break;
614  }
615  }
616 }
617 
618 // here are the output routines, thus the form::Forms are bundled:
619 
621 {
622  // it must be a Draw-Format
623  OSL_ENSURE( RES_DRAWFRMFMT == rFormat.Which(),
624  "GetHTMLControl only allow for Draw-Formats" );
625 
626  // Look if a SdrObject exists for it
627  const SdrObject *pObj = rFormat.FindSdrObject();
628  if( !pObj || SdrInventor::FmForm != pObj->GetObjInventor() )
629  return nullptr;
630 
631  const SdrUnoObj& rFormObj = dynamic_cast<const SdrUnoObj&>(*pObj);
632  const uno::Reference< awt::XControlModel >& xControlModel =
633  rFormObj.GetUnoControlModel();
634 
635  OSL_ENSURE( xControlModel.is(), "UNO-Control without model" );
636  if( !xControlModel.is() )
637  return nullptr;
638 
639  uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY );
640 
641  OUString sPropName("ClassId");
642  if( !xPropSet->getPropertySetInfo()->hasPropertyByName( sPropName ) )
643  return nullptr;
644 
645  uno::Any aTmp = xPropSet->getPropertyValue( sPropName );
646  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
647  {
648  if( lcl_html_isHTMLControl( *n ) )
649  {
650  return pObj;
651  }
652  }
653 
654  return nullptr;
655 }
656 
657 static void GetControlSize(const SdrUnoObj& rFormObj, Size& rSz, SwDoc *pDoc)
658 {
660  if( !pVSh )
661  return;
662 
663  uno::Reference< awt::XControl > xControl;
664  SdrView* pDrawView = pVSh->GetDrawView();
665  OSL_ENSURE( pDrawView && pVSh->GetWin(), "no DrawView or window!" );
666  if ( pDrawView && pVSh->GetWin() )
667  xControl = rFormObj.GetUnoControl( *pDrawView, *pVSh->GetWin()->GetOutDev() );
668  uno::Reference< awt::XTextLayoutConstrains > xLC( xControl, uno::UNO_QUERY );
669  OSL_ENSURE( xLC.is(), "no XTextLayoutConstrains" );
670  if( !xLC.is() )
671  return;
672 
673  sal_Int16 nCols=0, nLines=0;
674  xLC->getColumnsAndLines( nCols, nLines );
675  rSz.setWidth( nCols );
676  rSz.setHeight( nLines );
677 }
678 
680  const SwDrawFrameFormat& rFormat,
681  const SdrUnoObj& rFormObj,
682  bool bInCntnr )
683 {
684  const uno::Reference< awt::XControlModel >& xControlModel =
685  rFormObj.GetUnoControlModel();
686 
687  OSL_ENSURE( xControlModel.is(), "UNO-Control without model" );
688  if( !xControlModel.is() )
689  return rWrt;
690 
691  uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY );
692  uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
693  xPropSet->getPropertySetInfo();
694 
695  SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
696  rHTMLWrt.m_nFormCntrlCnt++;
697 
698  enum Tag { TAG_INPUT, TAG_SELECT, TAG_TEXTAREA, TAG_NONE };
699  static char const * const TagNames[] = {
702  Tag eTag = TAG_INPUT;
703  enum Type {
704  TYPE_TEXT, TYPE_PASSWORD, TYPE_CHECKBOX, TYPE_RADIO, TYPE_FILE,
705  TYPE_SUBMIT, TYPE_IMAGE, TYPE_RESET, TYPE_BUTTON, TYPE_NONE };
706  static char const * const TypeNames[] = {
712  Type eType = TYPE_NONE;
713  OUString sValue;
714  OString sOptions;
715  bool bEmptyValue = false;
716  uno::Any aTmp = xPropSet->getPropertyValue( "ClassId" );
717  sal_Int16 nClassId = *o3tl::doAccess<sal_Int16>(aTmp);
718  HtmlFrmOpts nFrameOpts = HTML_FRMOPTS_CONTROL;
719  switch( nClassId )
720  {
721  case form::FormComponentType::CHECKBOX:
722  case form::FormComponentType::RADIOBUTTON:
723  eType = (form::FormComponentType::CHECKBOX == nClassId
724  ? TYPE_CHECKBOX : TYPE_RADIO);
725  aTmp = xPropSet->getPropertyValue( "DefaultState" );
726  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
727  {
728  if ( TRISTATE_FALSE != *n )
729  {
730  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_checked "=\""
732  "\"";
733  }
734  }
735 
736  aTmp = xPropSet->getPropertyValue( "RefValue" );
737  if( auto rVal = o3tl::tryAccess<OUString>(aTmp) )
738 
739  {
740  if( rVal->isEmpty() )
741  bEmptyValue = true;
742  else if( *rVal != OOO_STRING_SVTOOLS_HTML_on )
743  sValue = *rVal;
744  }
745  break;
746 
747  case form::FormComponentType::COMMANDBUTTON:
748  {
749  form::FormButtonType eButtonType = form::FormButtonType_PUSH;
750  aTmp = xPropSet->getPropertyValue( "ButtonType" );
751  if( auto t = o3tl::tryAccess<form::FormButtonType>(aTmp) )
752  eButtonType = *t;
753 
754  switch( eButtonType )
755  {
756  case form::FormButtonType_RESET:
757  eType = TYPE_RESET;
758  break;
759  case form::FormButtonType_SUBMIT:
760  eType = TYPE_SUBMIT;
761  break;
762  case form::FormButtonType_PUSH:
763  default:
764  eType = TYPE_BUTTON;
765  }
766 
767  aTmp = xPropSet->getPropertyValue( "Label" );
768  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
769  {
770  if( !s->isEmpty() )
771  {
772  sValue = *s;
773  }
774  }
775  }
776  break;
777 
778  case form::FormComponentType::LISTBOX:
779  if( rHTMLWrt.m_bLFPossible )
780  rHTMLWrt.OutNewLine( true );
781  eTag = TAG_SELECT;
782  aTmp = xPropSet->getPropertyValue( "Dropdown" );
783  if( auto b1 = o3tl::tryAccess<bool>(aTmp) )
784  {
785  if( !*b1 )
786  {
787  Size aSz( 0, 0 );
788  GetControlSize( rFormObj, aSz, rWrt.m_pDoc );
789 
790  // How many are visible ??
791  if( aSz.Height() )
792  {
793  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_size "=\"" +
794  OString::number(static_cast<sal_Int32>(aSz.Height())) + "\"";
795  }
796 
797  auto aTmp2 = xPropSet->getPropertyValue( "MultiSelection" );
798  if( auto b2 = o3tl::tryAccess<bool>(aTmp2) )
799  {
800  if ( *b2 )
801  {
802  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_multiple;
803  }
804  }
805  }
806  }
807  break;
808 
809  case form::FormComponentType::TEXTFIELD:
810  {
811  Size aSz( 0, 0 );
812  GetControlSize( rFormObj, aSz, rWrt.m_pDoc );
813 
814  bool bMultiLine = false;
815  OUString sMultiLine("MultiLine");
816  if( xPropSetInfo->hasPropertyByName( sMultiLine ) )
817  {
818  aTmp = xPropSet->getPropertyValue( sMultiLine );
819  auto b = o3tl::tryAccess<bool>(aTmp);
820  bMultiLine = b && *b;
821  }
822 
823  if( bMultiLine )
824  {
825  if( rHTMLWrt.m_bLFPossible )
826  rHTMLWrt.OutNewLine( true );
827  eTag = TAG_TEXTAREA;
828 
829  if( aSz.Height() )
830  {
831  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_rows "=\"" +
832  OString::number(static_cast<sal_Int32>(aSz.Height())) + "\"";
833  }
834  if( aSz.Width() )
835  {
836  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_cols "=\"" +
837  OString::number(static_cast<sal_Int32>(aSz.Width())) + "\"";
838  }
839 
840  aTmp = xPropSet->getPropertyValue( "HScroll" );
841  if( aTmp.getValueType() == cppu::UnoType<void>::get() ||
842  (aTmp.getValueType() == cppu::UnoType<bool>::get() &&
843  !*o3tl::forceAccess<bool>(aTmp)) )
844  {
845  const char *pWrapStr = nullptr;
846  auto aTmp2 = xPropSet->getPropertyValue( "HardLineBreaks" );
847  auto b = o3tl::tryAccess<bool>(aTmp2);
848  pWrapStr = (b && *b) ? OOO_STRING_SVTOOLS_HTML_WW_hard
850  sOptions += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_wrap "=\"") +
851  pWrapStr + "\"";
852  }
853  }
854  else
855  {
856  eType = TYPE_TEXT;
857  OUString sEchoChar("EchoChar");
858  if( xPropSetInfo->hasPropertyByName( sEchoChar ) )
859  {
860  aTmp = xPropSet->getPropertyValue( sEchoChar );
861  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
862  {
863  if( *n != 0 )
864  eType = TYPE_PASSWORD;
865  }
866  }
867 
868  if( aSz.Width() )
869  {
870  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_size "=\"" +
871  OString::number(static_cast<sal_Int32>(aSz.Width())) + "\"";
872  }
873 
874  aTmp = xPropSet->getPropertyValue( "MaxTextLen" );
875  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
876  {
877  if( *n != 0 )
878  {
879  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_maxlength "=\"" +
880  OString::number(static_cast<sal_Int32>(*n)) + "\"";
881  }
882  }
883 
884  if( xPropSetInfo->hasPropertyByName( "DefaultText" ) )
885  {
886  aTmp = xPropSet->getPropertyValue( "DefaultText" );
887  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
888  {
889  if( !s->isEmpty() )
890  {
891  sValue = *s;
892  }
893  }
894  }
895  }
896  }
897  break;
898 
899  case form::FormComponentType::FILECONTROL:
900  {
901  Size aSz( 0, 0 );
902  GetControlSize( rFormObj, aSz, rWrt.m_pDoc );
903  eType = TYPE_FILE;
904 
905  if( aSz.Width() )
906  {
907  sOptions += " " OOO_STRING_SVTOOLS_HTML_O_size "=\"" +
908  OString::number(static_cast<sal_Int32>(aSz.Width())) + "\"";
909  }
910 
911  // VALUE vim form: don't export because of security reasons
912  }
913  break;
914 
915  case form::FormComponentType::IMAGEBUTTON:
916  eType = TYPE_IMAGE;
917  nFrameOpts = HTML_FRMOPTS_IMG_CONTROL;
918  break;
919 
920  default: // doesn't know HTML
921  eTag = TAG_NONE; // therefore skip it
922  break;
923  }
924 
925  if( eTag == TAG_NONE )
926  return rWrt;
927 
928  OString sOut = OString::Concat("<") + TagNames[eTag];
929  if( eType != TYPE_NONE )
930  {
931  sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") +
932  TypeNames[eType] + "\"";
933  }
934 
935  aTmp = xPropSet->getPropertyValue("Name");
936  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
937  {
938  if( !s->isEmpty() )
939  {
940  sOut += " " OOO_STRING_SVTOOLS_HTML_O_name "=\"";
941  rWrt.Strm().WriteOString( sOut );
942  HTMLOutFuncs::Out_String( rWrt.Strm(), *s,
943  rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
944  sOut = "\"";
945  }
946  }
947 
948  aTmp = xPropSet->getPropertyValue("Enabled");
949  if( auto b = o3tl::tryAccess<bool>(aTmp) )
950  {
951  if( !*b )
952  {
954  }
955  }
956 
957  if( !sValue.isEmpty() || bEmptyValue )
958  {
959  sOut += " " OOO_STRING_SVTOOLS_HTML_O_value "=\"";
960  rWrt.Strm().WriteOString( sOut );
961  HTMLOutFuncs::Out_String( rWrt.Strm(), sValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
962  sOut = "\"";
963  }
964 
965  sOut += " " + sOptions;
966 
967  if( TYPE_IMAGE == eType )
968  {
969  aTmp = xPropSet->getPropertyValue( "ImageURL" );
970  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
971  {
972  if( !s->isEmpty() )
973  {
974  sOut += " " OOO_STRING_SVTOOLS_HTML_O_src "=\"";
975  rWrt.Strm().WriteOString( sOut );
976 
979  rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
980  sOut = "\"";
981  }
982  }
983 
984  Size aTwipSz( rFormObj.GetLogicRect().GetSize() );
985  Size aPixelSz( 0, 0 );
986  if( (aTwipSz.Width() || aTwipSz.Height()) &&
988  {
989  aPixelSz =
991  MapMode(MapUnit::MapTwip) );
992  if( !aPixelSz.Width() && aTwipSz.Width() )
993  aPixelSz.setWidth( 1 );
994  if( !aPixelSz.Height() && aTwipSz.Height() )
995  aPixelSz.setHeight( 1 );
996  }
997 
998  if( aPixelSz.Width() )
999  {
1000  sOut += " " OOO_STRING_SVTOOLS_HTML_O_width "=\"" +
1001  OString::number(static_cast<sal_Int32>(aPixelSz.Width())) + "\"";
1002  }
1003 
1004  if( aPixelSz.Height() )
1005  {
1006  sOut += " " OOO_STRING_SVTOOLS_HTML_O_height "=\"" +
1007  OString::number(static_cast<sal_Int32>(aPixelSz.Height())) + "\"";
1008  }
1009  }
1010 
1011  aTmp = xPropSet->getPropertyValue( "TabIndex" );
1012  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
1013  {
1014  sal_Int16 nTabIndex = *n;
1015  if( nTabIndex > 0 )
1016  {
1017  if( nTabIndex >= 32767 )
1018  nTabIndex = 32767;
1019 
1020  sOut += " " OOO_STRING_SVTOOLS_HTML_O_tabindex "=\"" +
1021  OString::number(static_cast<sal_Int32>(nTabIndex)) + "\"";
1022  }
1023  }
1024 
1025  if( !sOut.isEmpty() )
1026  rWrt.Strm().WriteOString( sOut );
1027 
1028  OSL_ENSURE( !bInCntnr, "Container is not supported for Controls" );
1029  if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) && !bInCntnr )
1030  {
1031  // If Character-Objects can't be positioned absolutely,
1032  // then delete the corresponding flag.
1033  nFrameOpts |= (TYPE_IMAGE == eType
1036  }
1037  OString aEndTags;
1038  if( nFrameOpts != HtmlFrmOpts::NONE )
1039  aEndTags = rHTMLWrt.OutFrameFormatOptions(rFormat, OUString(), nFrameOpts);
1040 
1041  if( rHTMLWrt.m_bCfgOutStyles )
1042  {
1043  bool bEdit = TAG_TEXTAREA == eTag || TYPE_FILE == eType ||
1044  TYPE_TEXT == eType;
1045 
1047  if( xPropSetInfo->hasPropertyByName( "BackgroundColor" ) )
1048  {
1049  aTmp = xPropSet->getPropertyValue( "BackgroundColor" );
1050  if( auto n = o3tl::tryAccess<sal_Int32>(aTmp) )
1051  {
1052  Color aCol(ColorTransparency, *n);
1053  aItemSet.Put( SvxBrushItem( aCol, RES_CHRATR_BACKGROUND ) );
1054  }
1055  }
1056  if( xPropSetInfo->hasPropertyByName( "TextColor" ) )
1057  {
1058  aTmp = xPropSet->getPropertyValue( "TextColor" );
1059  if( auto n = o3tl::tryAccess<sal_Int32>(aTmp) )
1060  {
1061  Color aColor( ColorTransparency, *n );
1062  aItemSet.Put( SvxColorItem( aColor, RES_CHRATR_COLOR ) );
1063  }
1064  }
1065  if( xPropSetInfo->hasPropertyByName( "FontHeight" ) )
1066  {
1067  aTmp = xPropSet->getPropertyValue( "FontHeight" );
1068  if( auto nHeight = o3tl::tryAccess<float>(aTmp) )
1069 
1070  {
1071  if( *nHeight > 0 && (!bEdit || !rtl::math::approxEqual(*nHeight, 10.0)) )
1072  aItemSet.Put( SvxFontHeightItem( sal_Int16(*nHeight * 20.), 100, RES_CHRATR_FONTSIZE ) );
1073  }
1074  }
1075  if( xPropSetInfo->hasPropertyByName( "FontName" ) )
1076  {
1077  aTmp = xPropSet->getPropertyValue( "FontName" );
1078  if( auto aFName = o3tl::tryAccess<OUString>(aTmp) )
1079  {
1080  if( !aFName->isEmpty() )
1081  {
1083  DefaultFontType::FIXED, LANGUAGE_ENGLISH_US,
1084  GetDefaultFontFlags::OnlyOne ) );
1085  if( !bEdit || *aFName != aFixedFont.GetFamilyName() )
1086  {
1087  FontFamily eFamily = FAMILY_DONTKNOW;
1088  if( xPropSetInfo->hasPropertyByName( "FontFamily" ) )
1089  {
1090  auto aTmp2 = xPropSet->getPropertyValue( "FontFamily" );
1091  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp2) )
1092  eFamily = static_cast<FontFamily>(*n);
1093  }
1094  SvxFontItem aItem(eFamily, *aFName, OUString(), PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, RES_CHRATR_FONT);
1095  aItemSet.Put( aItem );
1096  }
1097  }
1098  }
1099  }
1100  if( xPropSetInfo->hasPropertyByName( "FontWeight" ) )
1101  {
1102  aTmp = xPropSet->getPropertyValue( "FontWeight" );
1103  if( auto x = o3tl::tryAccess<float>(aTmp) )
1104  {
1105  FontWeight eWeight =
1107  if( eWeight != WEIGHT_DONTKNOW && eWeight != WEIGHT_NORMAL )
1108  aItemSet.Put( SvxWeightItem( eWeight, RES_CHRATR_WEIGHT ) );
1109  }
1110  }
1111  if( xPropSetInfo->hasPropertyByName( "FontSlant" ) )
1112  {
1113  aTmp = xPropSet->getPropertyValue( "FontSlant" );
1114  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
1115  {
1116  FontItalic eItalic = static_cast<FontItalic>(*n);
1117  if( eItalic != ITALIC_DONTKNOW && eItalic != ITALIC_NONE )
1118  aItemSet.Put( SvxPostureItem( eItalic, RES_CHRATR_POSTURE ) );
1119  }
1120  }
1121  if( xPropSetInfo->hasPropertyByName( "FontLineStyle" ) )
1122  {
1123  aTmp = xPropSet->getPropertyValue( "FontLineStyle" );
1124  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
1125  {
1126  FontLineStyle eUnderline = static_cast<FontLineStyle>(*n);
1127  if( eUnderline != LINESTYLE_DONTKNOW &&
1128  eUnderline != LINESTYLE_NONE )
1129  aItemSet.Put( SvxUnderlineItem( eUnderline, RES_CHRATR_UNDERLINE ) );
1130  }
1131  }
1132  if( xPropSetInfo->hasPropertyByName( "FontStrikeout" ) )
1133  {
1134  aTmp = xPropSet->getPropertyValue( "FontStrikeout" );
1135  if( auto n = o3tl::tryAccess<sal_Int16>(aTmp) )
1136  {
1137  FontStrikeout eStrikeout = static_cast<FontStrikeout>(*n);
1138  if( eStrikeout != STRIKEOUT_DONTKNOW &&
1139  eStrikeout != STRIKEOUT_NONE )
1140  aItemSet.Put( SvxCrossedOutItem( eStrikeout, RES_CHRATR_CROSSEDOUT ) );
1141  }
1142  }
1143 
1144  rHTMLWrt.OutCSS1_FrameFormatOptions( rFormat, nFrameOpts, &rFormObj,
1145  &aItemSet );
1146  }
1147 
1148  uno::Reference< form::XFormComponent > xFormComp( xControlModel, uno::UNO_QUERY );
1149  lcl_html_outEvents( rWrt.Strm(), xFormComp, rHTMLWrt.m_bCfgStarBasic,
1150  rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1151 
1152  rWrt.Strm().WriteChar( '>' );
1153 
1154  if( TAG_SELECT == eTag )
1155  {
1156  aTmp = xPropSet->getPropertyValue( "StringItemList" );
1157  if( auto aList = o3tl::tryAccess<uno::Sequence<OUString>>(aTmp) )
1158  {
1159  rHTMLWrt.IncIndentLevel(); // the content of Select can be indented
1160  sal_Int32 nCnt = aList->getLength();
1161  const OUString *pStrings = aList->getConstArray();
1162 
1163  const OUString *pValues = nullptr;
1164  sal_Int32 nValCnt = 0;
1165  auto aTmp2 = xPropSet->getPropertyValue( "ListSource" );
1166  uno::Sequence<OUString> aValList;
1167  if( auto s = o3tl::tryAccess<uno::Sequence<OUString>>(aTmp2) )
1168  {
1169  aValList = *s;
1170  nValCnt = aValList.getLength();
1171  pValues = aValList.getConstArray();
1172  }
1173 
1174  uno::Any aSelTmp = xPropSet->getPropertyValue( "DefaultSelection" );
1175  const sal_Int16 *pSels = nullptr;
1176  sal_Int32 nSel = 0;
1177  sal_Int32 nSelCnt = 0;
1178  uno::Sequence<sal_Int16> aSelList;
1179  if( auto s = o3tl::tryAccess<uno::Sequence<sal_Int16>>(aSelTmp) )
1180  {
1181  aSelList = *s;
1182  nSelCnt = aSelList.getLength();
1183  pSels = aSelList.getConstArray();
1184  }
1185 
1186  for( sal_Int32 i = 0; i < nCnt; i++ )
1187  {
1188  OUString sVal;
1189  bool bSelected = false, bEmptyVal = false;
1190  if( i < nValCnt )
1191  {
1192  const OUString& rVal = pValues[i];
1193  if( rVal == "$$$empty$$$" )
1194  bEmptyVal = true;
1195  else
1196  sVal = rVal;
1197  }
1198 
1199  bSelected = (nSel < nSelCnt) && pSels[nSel] == i;
1200  if( bSelected )
1201  nSel++;
1202 
1203  rHTMLWrt.OutNewLine(); // every Option gets its own line
1204  sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_option;
1205  if( !sVal.isEmpty() || bEmptyVal )
1206  {
1207  sOut += " " OOO_STRING_SVTOOLS_HTML_O_value "=\"";
1208  rWrt.Strm().WriteOString( sOut );
1209  HTMLOutFuncs::Out_String( rWrt.Strm(), sVal,
1210  rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1211  sOut = "\"";
1212  }
1213  if( bSelected )
1215 
1216  sOut += ">";
1217  rWrt.Strm().WriteOString( sOut );
1218 
1219  HTMLOutFuncs::Out_String( rWrt.Strm(), pStrings[i],
1220  rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1221  }
1222  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_option), false );
1223 
1224  rHTMLWrt.DecIndentLevel();
1225  rHTMLWrt.OutNewLine();// the </SELECT> gets its own line
1226  }
1227  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_select), false );
1228  }
1229  else if( TAG_TEXTAREA == eTag )
1230  {
1231  // In TextAreas no additional spaces or LF may be exported!
1232  OUString sVal;
1233  aTmp = xPropSet->getPropertyValue( "DefaultText" );
1234  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
1235  {
1236  if( !s->isEmpty() )
1237  {
1238  sVal = *s;
1239  }
1240  }
1241  if( !sVal.isEmpty() )
1242  {
1243  sVal = convertLineEnd(sVal, LINEEND_LF);
1244  sal_Int32 nPos = 0;
1245  while ( nPos != -1 )
1246  {
1247  if( nPos )
1249  OUString aLine = sVal.getToken( 0, 0x0A, nPos );
1250  HTMLOutFuncs::Out_String( rWrt.Strm(), aLine,
1251  rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
1252  }
1253  }
1254  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OStringConcatenation(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_textarea), false );
1255  }
1256  else if( TYPE_CHECKBOX == eType || TYPE_RADIO == eType )
1257  {
1258  aTmp = xPropSet->getPropertyValue("Label");
1259  if( auto s = o3tl::tryAccess<OUString>(aTmp) )
1260  {
1261  if( !s->isEmpty() )
1262  {
1263  HTMLOutFuncs::Out_String( rWrt.Strm(), *s,
1264  rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( ' ' );
1265  }
1266  }
1267  }
1268 
1269  if( !aEndTags.isEmpty() )
1270  rWrt.Strm().WriteOString( aEndTags );
1271 
1272  // Controls aren't bound to a paragraph, therefore don't output LF anymore!
1273  rHTMLWrt.m_bLFPossible = false;
1274 
1275  if( rHTMLWrt.mxFormComps.is() )
1276  rHTMLWrt.OutHiddenControls( rHTMLWrt.mxFormComps, xPropSet );
1277  return rWrt;
1278 }
1279 
1283 static void AddControl( HTMLControls& rControls,
1284  const SdrUnoObj& rFormObj,
1285  SwNodeOffset nNodeIdx )
1286 {
1287  const uno::Reference< awt::XControlModel >& xControlModel =
1288  rFormObj.GetUnoControlModel();
1289  if( !xControlModel.is() )
1290  return;
1291 
1292  uno::Reference< form::XFormComponent > xFormComp( xControlModel, uno::UNO_QUERY );
1293  uno::Reference< uno::XInterface > xIfc = xFormComp->getParent();
1294  uno::Reference< form::XForm > xForm(xIfc, uno::UNO_QUERY);
1295 
1296  OSL_ENSURE( xForm.is(), "Where is the form?" );
1297  if( xForm.is() )
1298  {
1299  uno::Reference< container::XIndexContainer > xFormComps( xForm, uno::UNO_QUERY );
1300  std::unique_ptr<HTMLControl> pHCntrl(new HTMLControl( xFormComps, nNodeIdx ));
1301  auto itPair = rControls.insert( std::move(pHCntrl) );
1302  if (!itPair.second )
1303  {
1304  if( (*itPair.first)->xFormComps==xFormComps )
1305  (*itPair.first)->nCount++;
1306  }
1307  }
1308 }
1309 
1311 {
1312  // Idea: first off collect the paragraph- and character-bound controls.
1313  // In the process for every control the paragraph position and VCForm are
1314  // saved in an array.
1315  // With that array it's possible to find out where form::Forms must be
1316  // opened and closed.
1317 
1318  if( m_pHTMLPosFlyFrames )
1319  {
1320  // collect the paragraph-bound controls
1321  for( size_t i=0; i<m_pHTMLPosFlyFrames->size(); i++ )
1322  {
1323  const SwHTMLPosFlyFrame* pPosFlyFrame = (*m_pHTMLPosFlyFrames)[ i ].get();
1324  if( HtmlOut::Control != pPosFlyFrame->GetOutFn() )
1325  continue;
1326 
1327  const SdrObject *pSdrObj = pPosFlyFrame->GetSdrObject();
1328  OSL_ENSURE( pSdrObj, "Where is the SdrObject?" );
1329  if( !pSdrObj )
1330  continue;
1331 
1332  AddControl( m_aHTMLControls, dynamic_cast<const SdrUnoObj&>(*pSdrObj),
1333  pPosFlyFrame->GetNdIndex().GetIndex() );
1334  }
1335  }
1336 
1337  // and now the ones in a character-bound frame
1338  const SwFrameFormats* pSpzFrameFormats = m_pDoc->GetSpzFrameFormats();
1339  for( size_t i=0; i<pSpzFrameFormats->size(); i++ )
1340  {
1341  const SwFrameFormat *pFrameFormat = (*pSpzFrameFormats)[i];
1342  if( RES_DRAWFRMFMT != pFrameFormat->Which() )
1343  continue;
1344 
1345  const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor();
1346  const SwPosition *pPos = rAnchor.GetContentAnchor();
1347  if ((RndStdIds::FLY_AS_CHAR != rAnchor.GetAnchorId()) || !pPos)
1348  continue;
1349 
1350  const SdrObject *pSdrObj =
1351  SwHTMLWriter::GetHTMLControl( *static_cast<const SwDrawFrameFormat*>(pFrameFormat) );
1352  if( !pSdrObj )
1353  continue;
1354 
1355  AddControl( m_aHTMLControls, dynamic_cast<const SdrUnoObj&>(*pSdrObj), pPos->nNode.GetIndex() );
1356  }
1357 }
1358 
1360  const uno::Reference< container::XIndexContainer > & rFormComps,
1361  SwNodeOffset nIdx ) :
1362  xFormComps( rFormComps ), nNdIdx( nIdx ), nCount( 1 )
1363 {}
1364 
1366 {}
1367 
1368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define SVX_MACRO_LANGUAGE_JAVASCRIPT
#define OOO_STRING_SVTOOLS_HTML_O_src
Starts a section of nodes in the document model.
Definition: node.hxx:313
Type
EXTENDED_STYPE
std::unique_ptr< SwHTMLPosFlyFrames > m_pHTMLPosFlyFrames
Definition: wrthtml.hxx:260
constexpr TypedWhichId< SvxCrossedOutItem > RES_CHRATR_CROSSEDOUT(5)
const HtmlFrmOpts HTML_FRMOPTS_CONTROL
Definition: htmlforw.cxx:66
static vcl::Font GetDefaultFont(DefaultFontType nType, LanguageType eLang, GetDefaultFontFlags nFlags, const OutputDevice *pOutDev=nullptr)
URL aURL
const OUString & GetBaseURL() const
Definition: shellio.hxx:444
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:679
const char * aEventSDOptionTable[]
Definition: htmlform.cxx:164
static void AddControl(HTMLControls &rControls, const SdrUnoObj &rFormObj, SwNodeOffset nNodeIdx)
Find out if a format belongs to a control and if yes return its form.
Definition: htmlforw.cxx:1283
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
Marks a position in the document model.
Definition: pam.hxx:36
bool m_bPreserveForm
Definition: wrthtml.hxx:385
HTMLControls m_aHTMLControls
Definition: wrthtml.hxx:288
const OUString & GetFamilyName() const
SdrView * GetDrawView()
Definition: vnew.cxx:373
#define OOO_STRING_SVTOOLS_HTML_IT_image
#define OOO_STRING_SVTOOLS_HTML_IT_text
static SVT_DLLPUBLIC SvStream & Out_String(SvStream &, const OUString &, rtl_TextEncoding eDestEnc, OUString *pNonConvertableChars=nullptr)
void setWidth(tools::Long nWidth)
#define LANGUAGE_ENGLISH_US
#define OOO_STRING_SVTOOLS_HTML_O_disabled
#define OOO_STRING_SVTOOLS_HTML_IT_checkbox
SwDocShell * GetDocShell()
Definition: doc.hxx:1352
#define OOO_STRING_SVTOOLS_HTML_O_sdaddparam
SwNodeIndex nNode
Definition: pam.hxx:38
static const SdrObject * GetHTMLControl(const SwDrawFrameFormat &rFormat)
Definition: htmlforw.cxx:620
#define OOO_STRING_SVTOOLS_HTML_IT_button
#define OOO_STRING_SVTOOLS_HTML_textarea
#define OOO_STRING_SVTOOLS_HTML_O_multiple
detail::Optional< sal_Int32 >::type tryAccess< sal_Int32 >(css::uno::Any const &any)
FAMILY_DONTKNOW
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_FONTSIZE(8)
#define OOO_STRING_SVTOOLS_HTML_IT_file
sal_Int64 n
Definition: doc.hxx:188
void DecIndentLevel()
Definition: wrthtml.hxx:508
detail::Optional< float >::type tryAccess< float >(css::uno::Any const &any)
OUString m_aNonConvertableCharacters
Definition: wrthtml.hxx:295
constexpr TypedWhichId< SvxUnderlineItem > RES_CHRATR_UNDERLINE(14)
void OutHiddenControls(const css::uno::Reference< css::container::XIndexContainer > &rFormComps, const css::uno::Reference< css::beans::XPropertySet > &rPropSet)
Definition: htmlforw.cxx:534
const sal_uInt16 TYPE_TEXT
bool HasControls() const
Definition: htmlforw.cxx:215
#define OOO_STRING_SVTOOLS_HTML_form
static SVT_DLLPUBLIC SvStream & Out_AsciiTag(SvStream &, std::string_view rStr, bool bOn=true)
#define OOO_STRING_SVTOOLS_HTML_IT_hidden
float x
SVL_DLLPUBLIC OUString simpleNormalizedMakeRelative(OUString const &baseUriReference, OUString const &uriReference)
SvStream & WriteCharPtr(const char *pBuf)
void OutHiddenForms()
Definition: htmlforw.cxx:340
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
const SwNodeIndex & GetNdIndex() const
Definition: htmlfly.hxx:118
const SwFrameFormats * GetSpzFrameFormats() const
Definition: doc.hxx:744
const HtmlFrmOpts HTML_FRMOPTS_IMG_CONTROL_CSS1
Definition: htmlforw.cxx:76
#define TYPE_CHECKBOX
IDocumentDrawModelAccess const & getIDocumentDrawModelAccess() const
Definition: doc.cxx:155
static OutputDevice * GetDefaultDevice()
constexpr tools::Long Width() const
void OutNewLine(bool bCheck=false)
Definition: wrthtml.cxx:1441
bool m_bLFPossible
Definition: wrthtml.hxx:381
#define OOO_STRING_SVTOOLS_HTML_O_size
#define OOO_STRING_SVTOOLS_HTML_O_height
constexpr TypedWhichId< SwDrawFrameFormat > RES_DRAWFRMFMT(159)
#define OOO_STRING_SVTOOLS_HTML_IT_reset
LINESTYLE_NONE
static bool lcl_html_isHTMLControl(sal_Int16 nClassId)
Definition: htmlforw.cxx:195
int nCount
Tag
std::enable_if< !(detail::IsDerivedReference< T >::value||detail::IsUnoSequenceType< T >::value||std::is_base_of< css::uno::XInterface, T >::value), typename detail::Optional< T >::type >::type tryAccess(css::uno::Any const &any)
#define OOO_STRING_SVTOOLS_HTML_METHOD_post
#define OOO_STRING_SVTOOLS_HTML_IT_radio
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:154
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
#define OOO_STRING_SVTOOLS_HTML_O_sdevent
size_type size() const
#define OOO_STRING_SVTOOLS_HTML_O_maxlength
sal_uInt16 m_nFormCntrlCnt
Definition: wrthtml.hxx:314
#define OOO_STRING_SVTOOLS_HTML_WW_soft
bool IsHTMLMode(sal_uInt32 nMode) const
Definition: wrthtml.hxx:577
Specific frame formats (frames, DrawObjects).
constexpr TypedWhichId< SvxWeightItem > RES_CHRATR_WEIGHT(15)
DocumentType eType
static void GetControlSize(const SdrUnoObj &rFormObj, Size &rSz, SwDoc *pDoc)
Definition: htmlforw.cxx:657
WEIGHT_DONTKNOW
#define OOO_STRING_SVTOOLS_HTML_O_tabindex
Style of a layout element.
Definition: frmfmt.hxx:59
LINEEND_LF
bool m_bCfgStarBasic
Definition: wrthtml.hxx:344
rtl_TextEncoding m_eDestEnc
Definition: wrthtml.hxx:336
css::uno::Reference< css::container::XIndexContainer > mxFormComps
Definition: wrthtml.hxx:298
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
int i
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
#define OOO_STRING_SVTOOLS_HTML_O_rows
SwNodeOffset GetIndex() const
Definition: node.hxx:292
TRISTATE_FALSE
FlyAnchors.
Definition: fmtanchr.hxx:34
HtmlOut GetOutFn() const
Definition: htmlfly.hxx:121
virtual const SwDrawModel * GetDrawModel() const =0
Draw Model and id accessors.
WEIGHT_NORMAL
#define OOO_STRING_SVTOOLS_HTML_O_selected
#define OOO_STRING_SVTOOLS_HTML_O_method
#define OOO_STRING_SVTOOLS_HTML_O_name
css::uno::Reference< css::frame::XModel3 > GetBaseModel() const
PITCH_DONTKNOW
void GetControls()
Definition: htmlforw.cxx:1310
css::uno::Type const & get()
ColorTransparency
#define OOO_STRING_SVTOOLS_HTML_option
static void lcl_html_outEvents(SvStream &rStrm, const uno::Reference< form::XFormComponent > &rFormComp, bool bCfgStarBasic, rtl_TextEncoding eDestEnc, OUString *pNonConvertableChars)
Definition: htmlforw.cxx:80
ITALIC_NONE
HTMLControl(const css::uno::Reference< css::container::XIndexContainer > &rForm, SwNodeOffset nIdx)
Definition: htmlforw.cxx:1359
const char * aEventListenerTable[]
Definition: htmlform.cxx:140
#define OOO_STRING_SVTOOLS_HTML_IT_password
JAVASCRIPT
LINESTYLE_DONTKNOW
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
#define OOO_STRING_SVTOOLS_HTML_ET_multipart
const HtmlFrmOpts HTML_FRMOPTS_CONTROL_CSS1
Definition: htmlforw.cxx:68
XPropertyListType t
SAL_WARN_UNUSED_RESULT Point LogicToPixel(const Point &rLogicPt) const
HtmlFrmOpts
Definition: wrthtml.hxx:76
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
constexpr TypedWhichId< SvxColorItem > RES_CHRATR_COLOR(3)
FontFamily
const PropertyValue * pValues
constexpr TypedWhichId< SvxBrushItem > RES_CHRATR_BACKGROUND(21)
constexpr Size GetSize() const
FontWeight
OUString const aScriptType
Writer & OutHTML_DrawFrameFormatAsControl(Writer &rWrt, const SwDrawFrameFormat &rFormat, const SdrUnoObj &rFormObj, bool bInCntnr)
Definition: htmlforw.cxx:679
detail::Optional< sal_Int16 >::type tryAccess< sal_Int16 >(css::uno::Any const &any)
#define OOO_STRING_SVTOOLS_HTML_select
SvStream & WriteOString(std::string_view rStr)
constexpr tools::Long Height() const
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
vcl::Window * GetWin() const
Definition: viewsh.hxx:338
const sal_uInt16 TYPE_IMAGE
void OutForm(bool bTagOn=true, const SwStartNode *pStNd=nullptr)
Definition: htmlforw.cxx:227
const SdrObject * GetSdrObject() const
Definition: htmlfly.hxx:117
#define OOO_STRING_SVTOOLS_HTML_O_cols
#define OOO_STRING_SVTOOLS_HTML_O_target
void IncIndentLevel()
Definition: wrthtml.hxx:504
VCL_DLLPUBLIC float ConvertFontWeight(FontWeight eWeight)
#define OOO_STRING_SVTOOLS_HTML_WW_hard
::OutputDevice const * GetOutDev() const
SwNodes & GetNodes()
Definition: doc.hxx:409
ITALIC_DONTKNOW
#define OOO_STRING_SVTOOLS_HTML_O_wrap
OString GetNamespace() const
Determines the prefix string needed to respect the requested namespace alias.
Definition: wrthtml.cxx:1490
SvStream & WriteChar(char nChar)
css::uno::Reference< css::awt::XControl > GetUnoControl(const SdrView &_rView, const OutputDevice &_rOut) const
#define OOO_STRING_SVTOOLS_HTML_ET_text
#define OOO_STRING_SVTOOLS_HTML_IT_submit
std::shared_ptr< SwUnoCursor > m_pCurrentPam
Definition: shellio.hxx:410
#define OOO_STRING_SVTOOLS_HTML_O_value
#define OOO_STRING_SVTOOLS_HTML_input
const css::uno::Reference< css::awt::XControlModel > & GetUnoControlModel() const
void OutHiddenForm(const css::uno::Reference< css::form::XForm > &rForm)
Definition: htmlforw.cxx:382
STRIKEOUT_DONTKNOW
void setHeight(tools::Long nHeight)
const char * aEventOptionTable[]
Definition: htmlform.cxx:176
SvStream & Strm()
Definition: writer.cxx:215
const char * aEventMethodTable[]
Definition: htmlform.cxx:152
#define OOO_STRING_SVTOOLS_HTML_O_type
#define OOO_STRING_SVTOOLS_HTML_O_checked
size_t size() const
detail::Optional< bool >::type tryAccess< bool >(css::uno::Any const &any)
#define SVX_MACRO_LANGUAGE_STARBASIC
ScriptType
bool m_bCfgOutStyles
Definition: wrthtml.hxx:341
STRIKEOUT_NONE
std::pair< const_iterator, bool > insert(Value &&x)
#define OOO_STRING_SVTOOLS_HTML_on
const HtmlFrmOpts HTML_FRMOPTS_IMG_CONTROL
Definition: htmlforw.cxx:73
FontLineStyle
#define OOO_STRING_SVTOOLS_HTML_O_action
STARBASIC
#define HTMLMODE_ABS_POS_DRAW
Definition: wrthtml.hxx:124
SdrObject * FindSdrObject()
Definition: frmfmt.hxx:140
constexpr TypedWhichId< SvxPostureItem > RES_CHRATR_POSTURE(11)
FontStrikeout
#define OOO_STRING_SVTOOLS_HTML_O_width
#define SAL_NEWLINE_STRING
SwDoc * m_pDoc
Definition: shellio.hxx:408
sal_uInt16 nPos
OString OutFrameFormatOptions(const SwFrameFormat &rFrameFormat, const OUString &rAltText, HtmlFrmOpts nFrameOpts)
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1319
FontItalic
virtual const tools::Rectangle & GetLogicRect() const override
void OutCSS1_FrameFormatOptions(const SwFrameFormat &rFrameFormat, HtmlFrmOpts nFrameOpts, const SdrObject *pSdrObj=nullptr, const SfxItemSet *pItemSet=nullptr)
Definition: css1atr.cxx:1846