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