xref: /AOO41X/main/dtrans/source/win32/dtobj/FetcList.cxx (revision ff0525f24f03981d56b7579b645949f111420994)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dtrans.hxx"
26 
27 //------------------------------------------------------------------------
28 // includes
29 //------------------------------------------------------------------------
30 #include <osl/diagnose.h>
31 #include "FetcList.hxx"
32 #include "Fetc.hxx"
33 #include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp>
34 #include <com/sun/star/datatransfer/XMimeContentType.hpp>
35 
36 #ifndef _DATAFORMATTRANSLATOR_HXX_
37 #include "DataFmtTransl.hxx"
38 #endif
39 #include "..\misc\ImplHelper.hxx"
40 #include "..\misc\WinClip.hxx"
41 
42 #include <algorithm>
43 
44 #include "MimeAttrib.hxx"
45 
46 //------------------------------------------------------------------------
47 // namespace directives
48 //------------------------------------------------------------------------
49 
50 using namespace com::sun::star::uno;
51 using namespace com::sun::star::datatransfer;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::container;
54 using namespace rtl;
55 using namespace std;
56 
57 //------------------------------------------------------------------------
58 //
59 //------------------------------------------------------------------------
60 
61 LCID       CFormatRegistrar::m_TxtLocale   = 0;
62 sal_uInt32 CFormatRegistrar::m_TxtCodePage = GetACP( );
63 
64 //------------------------------------------------------------------------
65 //
66 //------------------------------------------------------------------------
67 
68 CFormatEtcContainer::CFormatEtcContainer( )
69 {
70     m_EnumIterator = m_FormatMap.begin( );
71 }
72 
73 //------------------------------------------------------------------------
74 //
75 //------------------------------------------------------------------------
76 
77 void CFormatEtcContainer::addFormatEtc( const CFormatEtc& fetc )
78 {
79     m_FormatMap.push_back( CFormatEtc( fetc ) );
80 }
81 
82 //------------------------------------------------------------------------
83 //
84 //------------------------------------------------------------------------
85 
86 void SAL_CALL CFormatEtcContainer::removeFormatEtc( const CFormatEtc& fetc )
87 {
88     FormatEtcMap_t::iterator iter =
89         find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
90 
91     if ( iter != m_FormatMap.end( ) )
92         m_FormatMap.erase( iter );
93 }
94 
95 //------------------------------------------------------------------------
96 //
97 //------------------------------------------------------------------------
98 
99 void SAL_CALL CFormatEtcContainer::removeAllFormatEtc( )
100 {
101     m_FormatMap.clear( );
102 }
103 
104 //------------------------------------------------------------------------
105 //
106 //------------------------------------------------------------------------
107 
108 sal_Bool CFormatEtcContainer::hasFormatEtc( const CFormatEtc& fetc ) const
109 {
110     FormatEtcMap_t::const_iterator iter =
111         find( m_FormatMap.begin(), m_FormatMap.end(), fetc );
112 
113     return ( iter != m_FormatMap.end( ) );
114 }
115 
116 //------------------------------------------------------------------------
117 //
118 //------------------------------------------------------------------------
119 
120 sal_Bool CFormatEtcContainer::hasElements( ) const
121 {
122     return ( m_FormatMap.size( ) > 0 );
123 }
124 
125 //------------------------------------------------------------------------
126 //
127 //------------------------------------------------------------------------
128 
129 void CFormatEtcContainer::beginEnumFormatEtc( )
130 {
131     m_EnumIterator = m_FormatMap.begin( );
132 }
133 
134 //------------------------------------------------------------------------
135 //
136 //------------------------------------------------------------------------
137 
138 sal_uInt32 SAL_CALL CFormatEtcContainer::nextFormatEtc( LPFORMATETC lpFetc,
139                                                         sal_uInt32 aNum )
140 {
141     OSL_ASSERT( lpFetc );
142     OSL_ASSERT( !IsBadWritePtr( lpFetc, sizeof( FORMATETC ) * aNum ) );
143 
144     sal_uInt32 nFetched = 0;
145 
146     if ( m_EnumIterator != m_FormatMap.end( ) )
147     {
148         for ( sal_uInt32 i = 0; i < aNum; i++, nFetched++, lpFetc++, ++m_EnumIterator )
149             CopyFormatEtc( lpFetc, *m_EnumIterator );
150     }
151 
152     return nFetched;
153 }
154 
155 
156 //------------------------------------------------------------------------
157 //
158 //------------------------------------------------------------------------
159 
160 sal_Bool SAL_CALL CFormatEtcContainer::skipFormatEtc( sal_uInt32 aNum )
161 {
162     FormatEtcMap_t::const_iterator iter_end = m_FormatMap.end( );
163     for ( sal_uInt32 i = 0;
164           (i < aNum) && (m_EnumIterator != iter_end);
165           i++, ++m_EnumIterator )
166         ;/* intentionally left empty */
167 
168     return ( m_EnumIterator != m_FormatMap.end( ) );
169 }
170 
171 
172 //#########################################################################
173 
174 
175 //------------------------------------------------------------------------
176 //
177 //------------------------------------------------------------------------
178 
179 CFormatRegistrar::CFormatRegistrar( const Reference< XMultiServiceFactory >& ServiceManager,
180                                     const CDataFormatTranslator& aDataFormatTranslator ) :
181     m_DataFormatTranslator( aDataFormatTranslator ),
182     m_bHasSynthesizedLocale( sal_False ),
183     m_SrvMgr( ServiceManager )
184 {
185 }
186 
187 // ----------------------------------------------------------------------------------------
188 // this function converts all DataFlavors of the given FlavorList into
189 // an appropriate FORMATETC structure, for some formats like unicodetext,
190 // text and text/html we will offer an accompany format e.g.:
191 //
192 // DataFlavor               | Registered Clipformat     |   Registered accompany clipformat
193 // -------------------------|---------------------------|-----------------------------------
194 // text/plain;charset=ansi  | CF_TEXT                   |   CF_UNICODETEXT
195 //                          |                           |   CF_LOCALE (if charset != GetACP()
196 //                          |                           |
197 // text/plain;charset=oem   | CF_OEMTEXT                |   CF_UNICODETEXT
198 //                          |                           |   CF_LOCALE (if charset != GetOEMCP()
199 //                          |                           |
200 // text/plain;charset=utf-16| CF_UNICODETEXT            |   CF_TEXT
201 //                          |                           |
202 // text/html                | HTML (Hypertext ...)      |   HTML Format
203 //                          |                           |
204 //
205 // if some tries to register different text formats with different charsets the last
206 // registered wins and the others are ignored
207 // ----------------------------------------------------------------------------------------
208 
209 void SAL_CALL CFormatRegistrar::RegisterFormats(
210     const Reference< XTransferable >& aXTransferable, CFormatEtcContainer& aFormatEtcContainer )
211 {
212     Sequence< DataFlavor > aFlavorList = aXTransferable->getTransferDataFlavors( );
213     sal_Int32  nFlavors                = aFlavorList.getLength( );
214     sal_Bool   bUnicodeRegistered      = sal_False;
215     DataFlavor aFlavor;
216 
217     for( sal_Int32 i = 0; i < nFlavors; i++ )
218     {
219         aFlavor = aFlavorList[i];
220         CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor );
221 
222         // maybe an internal format so we ignore it
223         if ( CF_INVALID == fetc.getClipformat( ) )
224             continue;
225 
226         if ( !needsToSynthesizeAccompanyFormats( fetc ) )
227             aFormatEtcContainer.addFormatEtc( fetc );
228         else
229         {
230             // if we haven't registered any text format up to now
231             if ( m_DataFormatTranslator.isTextFormat( fetc.getClipformat() ) && !bUnicodeRegistered )
232             {
233                 // if the transferable supports unicode text we ignore
234                 // any further text format the transferable offers
235                 // because we can create it from Unicode text in addition
236                 // we register CF_TEXT for non unicode clients
237                 if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat() ) )
238                 {
239                     aFormatEtcContainer.addFormatEtc( fetc ); // add CF_UNICODE
240                     aFormatEtcContainer.addFormatEtc(
241                         m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) ); // add CF_TEXT
242                     bUnicodeRegistered = sal_True;
243                 }
244                 else if ( !hasUnicodeFlavor( aXTransferable ) )
245                 {
246                     // we try to investigate the charset and make a valid
247                     // windows codepage from this charset the default
248                     // return value is the result of GetACP( )
249                     OUString charset = getCharsetFromDataFlavor( aFlavor );
250                     sal_uInt32 txtCP = getWinCPFromMimeCharset( charset );
251 
252                     // we try to get a Locale appropriate for this codepage
253                     if ( findLocaleForTextCodePage( ) )
254                     {
255                         m_TxtCodePage = txtCP;
256 
257                         aFormatEtcContainer.addFormatEtc(
258                             m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
259 
260                         if ( !IsOEMCP( m_TxtCodePage ) )
261                             aFormatEtcContainer.addFormatEtc(
262                                 m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT ) );
263                         else
264                             aFormatEtcContainer.addFormatEtc(
265                                 m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT ) );
266 
267                         aFormatEtcContainer.addFormatEtc(
268                             m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE ) );
269 
270                         // we save the flavor so it's easier when
271                         // queried for it in XTDataObject::GetData(...)
272                         m_RegisteredTextFlavor  = aFlavor;
273                         m_bHasSynthesizedLocale = sal_True;
274                     }
275                 }
276             }
277             else if ( m_DataFormatTranslator.isTextHtmlFormat( fetc.getClipformat( ) ) ) // Html (Hyper Text...)
278             {
279                 // we add text/html ( HTML (HyperText Markup Language) )
280                 aFormatEtcContainer.addFormatEtc( fetc );
281 
282                 // and HTML Format
283                 OUString htmlFormat( OUString::createFromAscii( "HTML Format" ) );
284                 aFormatEtcContainer.addFormatEtc(
285                     m_DataFormatTranslator.getFormatEtcForClipformatName( htmlFormat ) );
286             }
287         }
288     }
289 }
290 
291 //------------------------------------------------------------------------
292 //
293 //------------------------------------------------------------------------
294 
295 sal_Bool SAL_CALL CFormatRegistrar::hasSynthesizedLocale( ) const
296 {
297     return m_bHasSynthesizedLocale;
298 }
299 
300 //------------------------------------------------------------------------
301 //
302 //------------------------------------------------------------------------
303 
304 LCID SAL_CALL CFormatRegistrar::getSynthesizedLocale( ) const
305 {
306     return m_TxtLocale;
307 }
308 
309 //------------------------------------------------------------------------
310 //
311 //------------------------------------------------------------------------
312 
313 sal_uInt32 SAL_CALL CFormatRegistrar::getRegisteredTextCodePage( ) const
314 {
315     return m_TxtCodePage;
316 }
317 
318 //------------------------------------------------------------------------
319 //
320 //------------------------------------------------------------------------
321 
322 DataFlavor SAL_CALL CFormatRegistrar::getRegisteredTextFlavor( ) const
323 {
324     return m_RegisteredTextFlavor;
325 }
326 
327 //------------------------------------------------------------------------
328 //
329 //------------------------------------------------------------------------
330 
331 sal_Bool SAL_CALL CFormatRegistrar::isSynthesizeableFormat( const CFormatEtc& aFormatEtc ) const
332 {
333     return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
334              m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
335              m_DataFormatTranslator.isHTMLFormat( aFormatEtc.getClipformat() ) );
336 }
337 
338 //------------------------------------------------------------------------
339 //
340 //------------------------------------------------------------------------
341 
342 inline
343 sal_Bool SAL_CALL CFormatRegistrar::needsToSynthesizeAccompanyFormats( const CFormatEtc& aFormatEtc ) const
344 {
345     return ( m_DataFormatTranslator.isOemOrAnsiTextFormat( aFormatEtc.getClipformat() ) ||
346              m_DataFormatTranslator.isUnicodeTextFormat( aFormatEtc.getClipformat() ) ||
347              m_DataFormatTranslator.isTextHtmlFormat( aFormatEtc.getClipformat( ) ) );
348 }
349 
350 //------------------------------------------------------------------------
351 //
352 //------------------------------------------------------------------------
353 
354 OUString SAL_CALL CFormatRegistrar::getCharsetFromDataFlavor( const DataFlavor& aFlavor )
355 {
356     OUString charset;
357 
358     try
359     {
360         Reference< XMimeContentTypeFactory > xMimeFac(
361             m_SrvMgr->createInstance( OUString::createFromAscii( \
362                 "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY );
363 
364         if( xMimeFac.is( ) )
365         {
366             Reference< XMimeContentType > xMimeType( xMimeFac->createMimeContentType( aFlavor.MimeType ) );
367             if ( xMimeType->hasParameter( TEXTPLAIN_PARAM_CHARSET ) )
368                 charset = xMimeType->getParameterValue( TEXTPLAIN_PARAM_CHARSET );
369             else
370                 charset = getMimeCharsetFromWinCP( GetACP( ), PRE_WINDOWS_CODEPAGE );
371         }
372     }
373     catch(NoSuchElementException&)
374     {
375         OSL_ENSURE( sal_False, "Unexpected" );
376     }
377     catch(...)
378     {
379         OSL_ENSURE( sal_False, "Invalid data flavor" );
380     }
381 
382     return charset;
383 }
384 
385 //------------------------------------------------------------------------
386 //
387 //------------------------------------------------------------------------
388 
389 sal_Bool SAL_CALL CFormatRegistrar::hasUnicodeFlavor( const Reference< XTransferable >& aXTransferable ) const
390 {
391     CFormatEtc fetc( CF_UNICODETEXT );
392 
393     DataFlavor aFlavor =
394         m_DataFormatTranslator.getDataFlavorFromFormatEtc( fetc );
395 
396     return aXTransferable->isDataFlavorSupported( aFlavor );
397 }
398 
399 //------------------------------------------------------------------------
400 //
401 //------------------------------------------------------------------------
402 
403 inline
404 sal_Bool CFormatRegistrar::isEqualCurrentSystemCodePage( sal_uInt32 aCodePage ) const
405 {
406     return ( (aCodePage == GetOEMCP()) || (aCodePage == GetACP()) );
407 }
408 
409 //------------------------------------------------------------------------
410 //
411 //------------------------------------------------------------------------
412 
413 sal_Bool SAL_CALL CFormatRegistrar::findLocaleForTextCodePage( )
414 {
415     m_TxtLocale = 0;
416     EnumSystemLocalesA( CFormatRegistrar::EnumLocalesProc, LCID_INSTALLED );
417     return ( IsValidLocale( m_TxtLocale, LCID_INSTALLED ) ) ? sal_True : sal_False;
418 }
419 
420 //------------------------------------------------------------------------
421 //
422 //------------------------------------------------------------------------
423 
424 sal_Bool SAL_CALL CFormatRegistrar::isLocaleCodePage( LCID lcid, LCTYPE lctype, sal_uInt32 codepage )
425 {
426     char  buff[6];
427     sal_uInt32 localeCodePage;
428 
429     OSL_ASSERT( IsValidLocale( lcid, LCID_INSTALLED ) );
430 
431     // get the ansi codepage of the current locale
432     GetLocaleInfoA( lcid, lctype, buff, sizeof( buff ) );
433     localeCodePage = atol( buff );
434 
435     return ( localeCodePage == codepage );
436 }
437 
438 //------------------------------------------------------------------------
439 //
440 //------------------------------------------------------------------------
441 
442 inline
443 sal_Bool SAL_CALL CFormatRegistrar::isLocaleOemCodePage( LCID lcid, sal_uInt32 codepage )
444 {
445     return isLocaleCodePage( lcid, LOCALE_IDEFAULTCODEPAGE, codepage );
446 }
447 
448 //------------------------------------------------------------------------
449 //
450 //------------------------------------------------------------------------
451 
452 inline
453 sal_Bool SAL_CALL CFormatRegistrar::isLocaleAnsiCodePage( LCID lcid, sal_uInt32 codepage )
454 {
455     return isLocaleCodePage( lcid, LOCALE_IDEFAULTANSICODEPAGE, codepage );
456 }
457 
458 //------------------------------------------------------------------------
459 //
460 //------------------------------------------------------------------------
461 
462 BOOL CALLBACK CFormatRegistrar::EnumLocalesProc( LPSTR lpLocaleStr )
463 {
464     // the lpLocaleStr parametere is hexadecimal
465     LCID lcid = strtol( lpLocaleStr, NULL, 16 );
466 
467     if ( isLocaleAnsiCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) ||
468          isLocaleOemCodePage( lcid, CFormatRegistrar::m_TxtCodePage ) )
469     {
470         CFormatRegistrar::m_TxtLocale = lcid;
471         return sal_False; // stop enumerating
472     }
473 
474     return sal_True;
475 }
476 
477