fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svtools / source / misc / imap2.cxx
blobbec3886d0db1a37abc36ea8f1b4c367fc93605cc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <comphelper/string.hxx>
22 #include <string.h>
23 #include <rtl/strbuf.hxx>
24 #include <vcl/svapp.hxx>
25 #include <tools/urlobj.hxx>
26 #include <vcl/wrkwin.hxx>
27 #include <sot/formats.hxx>
29 #include "svl/urihelper.hxx"
30 #include <svtools/imap.hxx>
31 #include <svtools/imapobj.hxx>
32 #include <svtools/imaprect.hxx>
33 #include <svtools/imapcirc.hxx>
34 #include <svtools/imappoly.hxx>
36 #include <math.h>
38 #define NOTEOL(c) ((c)!='\0')
40 TYPEINIT0_AUTOFACTORY( ImageMap );
42 void IMapObject::AppendCERNCoords(OStringBuffer& rBuf, const Point& rPoint100) const
44 const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MAP_100TH_MM ) ) );
46 rBuf.append('(');
47 rBuf.append(static_cast<sal_Int32>(aPixPt.X()));
48 rBuf.append(',');
49 rBuf.append(static_cast<sal_Int32>(aPixPt.Y()));
50 rBuf.append(RTL_CONSTASCII_STRINGPARAM(") "));
53 void IMapObject::AppendNCSACoords(OStringBuffer& rBuf, const Point& rPoint100) const
55 const Point aPixPt( Application::GetDefaultDevice()->LogicToPixel( rPoint100, MapMode( MAP_100TH_MM ) ) );
57 rBuf.append(static_cast<sal_Int32>(aPixPt.X()));
58 rBuf.append(',');
59 rBuf.append(static_cast<sal_Int32>(aPixPt.Y()));
60 rBuf.append(' ');
63 void IMapObject::AppendCERNURL(OStringBuffer& rBuf, const String& rBaseURL) const
65 rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative(rBaseURL, aURL), osl_getThreadTextEncoding()));
68 void IMapObject::AppendNCSAURL(OStringBuffer& rBuf, const String& rBaseURL) const
70 rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative(rBaseURL, aURL), osl_getThreadTextEncoding()));
71 rBuf.append(' ');
74 void IMapRectangleObject::WriteCERN( SvStream& rOStm, const String& rBaseURL ) const
76 OStringBuffer aStrBuf(RTL_CONSTASCII_STRINGPARAM("rectangle "));
78 AppendCERNCoords(aStrBuf, aRect.TopLeft());
79 AppendCERNCoords(aStrBuf, aRect.BottomRight());
80 AppendCERNURL(aStrBuf, rBaseURL);
82 rOStm.WriteLine(aStrBuf.makeStringAndClear());
85 void IMapRectangleObject::WriteNCSA( SvStream& rOStm, const String& rBaseURL ) const
87 OStringBuffer aStrBuf(RTL_CONSTASCII_STRINGPARAM("rect "));
89 AppendNCSAURL(aStrBuf, rBaseURL);
90 AppendNCSACoords(aStrBuf, aRect.TopLeft());
91 AppendNCSACoords(aStrBuf, aRect.BottomRight());
93 rOStm.WriteLine(aStrBuf.makeStringAndClear());
96 void IMapCircleObject::WriteCERN( SvStream& rOStm, const String& rBaseURL ) const
98 OStringBuffer aStrBuf(RTL_CONSTASCII_STRINGPARAM("circle "));
100 AppendCERNCoords(aStrBuf, aCenter);
101 aStrBuf.append(nRadius);
102 aStrBuf.append(' ');
103 AppendCERNURL(aStrBuf, rBaseURL);
105 rOStm.WriteLine(aStrBuf.makeStringAndClear());
108 void IMapCircleObject::WriteNCSA( SvStream& rOStm, const String& rBaseURL ) const
110 OStringBuffer aStrBuf(RTL_CONSTASCII_STRINGPARAM("circle "));
112 AppendNCSAURL(aStrBuf, rBaseURL);
113 AppendNCSACoords(aStrBuf, aCenter);
114 AppendNCSACoords(aStrBuf, aCenter + Point(nRadius, 0));
116 rOStm.WriteLine(aStrBuf.makeStringAndClear());
119 void IMapPolygonObject::WriteCERN( SvStream& rOStm, const String& rBaseURL ) const
121 OStringBuffer aStrBuf(RTL_CONSTASCII_STRINGPARAM("polygon "));
122 const sal_uInt16 nCount = aPoly.GetSize();
124 for (sal_uInt16 i = 0; i < nCount; ++i)
125 AppendCERNCoords(aStrBuf, aPoly[i]);
127 AppendCERNURL(aStrBuf, rBaseURL);
129 rOStm.WriteLine(aStrBuf.makeStringAndClear());
132 void IMapPolygonObject::WriteNCSA( SvStream& rOStm, const String& rBaseURL ) const
134 OStringBuffer aStrBuf(RTL_CONSTASCII_STRINGPARAM("poly "));
135 const sal_uInt16 nCount = std::min( aPoly.GetSize(), (sal_uInt16) 100 );
137 AppendNCSAURL(aStrBuf, rBaseURL);
139 for (sal_uInt16 i = 0; i < nCount; ++i)
140 AppendNCSACoords(aStrBuf, aPoly[i]);
142 rOStm.WriteLine(aStrBuf.makeStringAndClear());
145 void ImageMap::Write( SvStream& rOStm, sal_uLong nFormat, const String& rBaseURL ) const
147 switch( nFormat )
149 case( IMAP_FORMAT_BIN ) : Write( rOStm, rBaseURL );
150 case( IMAP_FORMAT_CERN ) : ImpWriteCERN( rOStm, rBaseURL ); break;
151 case( IMAP_FORMAT_NCSA ) : ImpWriteNCSA( rOStm, rBaseURL ); break;
153 default:
154 break;
158 void ImageMap::ImpWriteCERN( SvStream& rOStm, const String& rBaseURL ) const
160 IMapObject* pObj;
161 size_t nCount = maList.size();
163 for ( size_t i = 0; i < nCount; i++ )
165 pObj = maList[ i ];
167 switch( pObj->GetType() )
169 case( IMAP_OBJ_RECTANGLE ):
170 ( (IMapRectangleObject*) pObj )->WriteCERN( rOStm, rBaseURL );
171 break;
173 case( IMAP_OBJ_CIRCLE ):
174 ( (IMapCircleObject*) pObj )->WriteCERN( rOStm, rBaseURL );
175 break;
177 case( IMAP_OBJ_POLYGON ):
178 ( (IMapPolygonObject*) pObj )->WriteCERN( rOStm, rBaseURL );
179 break;
181 default:
182 break;
187 void ImageMap::ImpWriteNCSA( SvStream& rOStm, const String& rBaseURL ) const
189 IMapObject* pObj;
190 size_t nCount = maList.size();
192 for ( size_t i = 0; i < nCount; i++ )
194 pObj = maList[ i ];
196 switch( pObj->GetType() )
198 case( IMAP_OBJ_RECTANGLE ):
199 ( (IMapRectangleObject*) pObj )->WriteNCSA( rOStm, rBaseURL );
200 break;
202 case( IMAP_OBJ_CIRCLE ):
203 ( (IMapCircleObject*) pObj )->WriteNCSA( rOStm, rBaseURL );
204 break;
206 case( IMAP_OBJ_POLYGON ):
207 ( (IMapPolygonObject*) pObj )->WriteNCSA( rOStm, rBaseURL );
208 break;
210 default:
211 break;
216 sal_uLong ImageMap::Read( SvStream& rIStm, sal_uLong nFormat, const String& rBaseURL )
218 sal_uLong nRet = IMAP_ERR_FORMAT;
220 if ( nFormat == IMAP_FORMAT_DETECT )
221 nFormat = ImpDetectFormat( rIStm );
223 switch ( nFormat )
225 case ( IMAP_FORMAT_BIN ) : Read( rIStm, rBaseURL ); break;
226 case ( IMAP_FORMAT_CERN ) : nRet = ImpReadCERN( rIStm, rBaseURL ); break;
227 case ( IMAP_FORMAT_NCSA ) : nRet = ImpReadNCSA( rIStm, rBaseURL ); break;
229 default:
230 break;
233 if ( !rIStm.GetError() )
234 nRet = IMAP_ERR_OK;
236 return nRet;
239 sal_uLong ImageMap::ImpReadCERN( SvStream& rIStm, const String& rBaseURL )
241 // alten Inhalt loeschen
242 ClearImageMap();
244 OString aStr;
245 while ( rIStm.ReadLine( aStr ) )
246 ImpReadCERNLine( aStr, rBaseURL );
248 return IMAP_ERR_OK;
251 void ImageMap::ImpReadCERNLine( const OString& rLine, const String& rBaseURL )
253 OString aStr = comphelper::string::stripStart(rLine, ' ');
254 aStr = comphelper::string::stripStart(aStr, '\t');
255 aStr = comphelper::string::remove(aStr, ';');
256 aStr = aStr.toAsciiLowerCase();
258 const char* pStr = aStr.getStr();
259 char cChar = *pStr++;
261 // Anweisung finden
262 OStringBuffer aBuf;
263 while( ( cChar >= 'a' ) && ( cChar <= 'z' ) && NOTEOL( cChar ) )
265 aBuf.append(cChar);
266 cChar = *pStr++;
268 OString aToken = aBuf.makeStringAndClear();
270 if ( NOTEOL( cChar ) )
272 if ( ( aToken == "rectangle" ) || ( aToken == "rect" ) )
274 const Point aTopLeft( ImpReadCERNCoords( &pStr ) );
275 const Point aBottomRight( ImpReadCERNCoords( &pStr ) );
276 const String aURL( ImpReadCERNURL( &pStr, rBaseURL ) );
277 const Rectangle aRect( aTopLeft, aBottomRight );
279 IMapRectangleObject* pObj = new IMapRectangleObject( aRect, aURL, String(), String(), String(), String() );
280 maList.push_back( pObj );
282 else if ( ( aToken == "circle" ) || ( aToken == "circ" ) )
284 const Point aCenter( ImpReadCERNCoords( &pStr ) );
285 const long nRadius = ImpReadCERNRadius( &pStr );
286 const String aURL( ImpReadCERNURL( &pStr, rBaseURL ) );
288 IMapCircleObject* pObj = new IMapCircleObject( aCenter, nRadius, aURL, String(), String(), String(), String() );
289 maList.push_back( pObj );
291 else if ( ( aToken == "polygon" ) || ( aToken == "poly" ) )
293 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr,
294 '(') - 1;
295 Polygon aPoly( nCount );
296 String aURL;
298 for ( sal_uInt16 i = 0; i < nCount; i++ )
299 aPoly[ i ] = ImpReadCERNCoords( &pStr );
301 aURL = ImpReadCERNURL( &pStr, rBaseURL );
303 IMapPolygonObject* pObj = new IMapPolygonObject( aPoly, aURL, String(), String(), String(), String() );
304 maList.push_back( pObj );
309 Point ImageMap::ImpReadCERNCoords( const char** ppStr )
311 String aStrX;
312 String aStrY;
313 Point aPt;
314 char cChar = *(*ppStr)++;
316 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
317 cChar = *(*ppStr)++;
319 if ( NOTEOL( cChar ) )
321 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
323 aStrX += cChar;
324 cChar = *(*ppStr)++;
327 if ( NOTEOL( cChar ) )
329 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
330 cChar = *(*ppStr)++;
332 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
334 aStrY += cChar;
335 cChar = *(*ppStr)++;
338 if ( NOTEOL( cChar ) )
339 while( NOTEOL( cChar ) && ( cChar != ')' ) )
340 cChar = *(*ppStr)++;
342 aPt = Point( aStrX.ToInt32(), aStrY.ToInt32() );
346 return aPt;
349 long ImageMap::ImpReadCERNRadius( const char** ppStr )
351 String aStr;
352 char cChar = *(*ppStr)++;
354 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
355 cChar = *(*ppStr)++;
357 if ( NOTEOL( cChar ) )
359 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
361 aStr += cChar;
362 cChar = *(*ppStr)++;
366 return aStr.ToInt32();
369 String ImageMap::ImpReadCERNURL( const char** ppStr, const String& rBaseURL )
371 OUString aStr(OUString::createFromAscii(*ppStr));
373 aStr = comphelper::string::stripStart(aStr, ' ');
374 aStr = comphelper::string::stripStart(aStr, '\t');
375 aStr = comphelper::string::stripEnd(aStr, ' ');
376 aStr = comphelper::string::stripEnd(aStr, '\t');
378 return INetURLObject::GetAbsURL( rBaseURL, aStr );
381 sal_uLong ImageMap::ImpReadNCSA( SvStream& rIStm, const String& rBaseURL )
383 // alten Inhalt loeschen
384 ClearImageMap();
386 OString aStr;
387 while ( rIStm.ReadLine( aStr ) )
388 ImpReadNCSALine( aStr, rBaseURL );
390 return IMAP_ERR_OK;
393 void ImageMap::ImpReadNCSALine( const OString& rLine, const String& rBaseURL )
395 OString aStr = comphelper::string::stripStart(rLine, ' ');
396 aStr = comphelper::string::stripStart(aStr, '\t');
397 aStr = comphelper::string::remove(aStr, ';');
398 aStr = aStr.toAsciiLowerCase();
400 const char* pStr = aStr.getStr();
401 char cChar = *pStr++;
403 // Anweisung finden
404 OStringBuffer aBuf;
405 while( ( cChar >= 'a' ) && ( cChar <= 'z' ) && NOTEOL( cChar ) )
407 aBuf.append(cChar);
408 cChar = *pStr++;
410 OString aToken = aBuf.makeStringAndClear();
412 if ( NOTEOL( cChar ) )
414 if ( aToken == "rect" )
416 const String aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
417 const Point aTopLeft( ImpReadNCSACoords( &pStr ) );
418 const Point aBottomRight( ImpReadNCSACoords( &pStr ) );
419 const Rectangle aRect( aTopLeft, aBottomRight );
421 IMapRectangleObject* pObj = new IMapRectangleObject( aRect, aURL, String(), String(), String(), String() );
422 maList.push_back( pObj );
424 else if ( aToken == "circle" )
426 const String aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
427 const Point aCenter( ImpReadNCSACoords( &pStr ) );
428 const Point aDX( aCenter - ImpReadNCSACoords( &pStr ) );
429 long nRadius = (long) sqrt( (double) aDX.X() * aDX.X() +
430 (double) aDX.Y() * aDX.Y() );
432 IMapCircleObject* pObj = new IMapCircleObject( aCenter, nRadius, aURL, String(), String(), String(), String() );
433 maList.push_back( pObj );
435 else if ( aToken == "poly" )
437 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr,
438 ',') - 1;
439 const String aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
440 Polygon aPoly( nCount );
442 for ( sal_uInt16 i = 0; i < nCount; i++ )
443 aPoly[ i ] = ImpReadNCSACoords( &pStr );
445 IMapPolygonObject* pObj = new IMapPolygonObject( aPoly, aURL, String(), String(), String(), String() );
446 maList.push_back( pObj );
451 String ImageMap::ImpReadNCSAURL( const char** ppStr, const String& rBaseURL )
453 String aStr;
454 char cChar = *(*ppStr)++;
456 while( NOTEOL( cChar ) && ( ( cChar == ' ' ) || ( cChar == '\t' ) ) )
457 cChar = *(*ppStr)++;
459 if ( NOTEOL( cChar ) )
461 while( NOTEOL( cChar ) && ( cChar != ' ' ) && ( cChar != '\t' ) )
463 aStr += cChar;
464 cChar = *(*ppStr)++;
468 return INetURLObject::GetAbsURL( rBaseURL, aStr );
471 Point ImageMap::ImpReadNCSACoords( const char** ppStr )
473 String aStrX;
474 String aStrY;
475 Point aPt;
476 char cChar = *(*ppStr)++;
478 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
479 cChar = *(*ppStr)++;
481 if ( NOTEOL( cChar ) )
483 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
485 aStrX += cChar;
486 cChar = *(*ppStr)++;
489 if ( NOTEOL( cChar ) )
491 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
492 cChar = *(*ppStr)++;
494 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
496 aStrY += cChar;
497 cChar = *(*ppStr)++;
500 aPt = Point( aStrX.ToInt32(), aStrY.ToInt32() );
504 return aPt;
507 sal_uLong ImageMap::ImpDetectFormat( SvStream& rIStm )
509 sal_uLong nPos = rIStm.Tell();
510 sal_uLong nRet = IMAP_FORMAT_BIN;
511 char cMagic[6];
513 rIStm.Read( cMagic, sizeof( cMagic ) );
515 // Falls wir kein internes Format haben,
516 // untersuchen wir das Format
517 if ( memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) )
519 long nCount = 128;
521 rIStm.Seek( nPos );
522 OString aStr;
523 while ( rIStm.ReadLine( aStr ) && nCount-- )
525 aStr = aStr.toAsciiLowerCase();
527 if ( (aStr.indexOfL(RTL_CONSTASCII_STRINGPARAM("rect")) != -1) ||
528 (aStr.indexOfL(RTL_CONSTASCII_STRINGPARAM("circ")) != -1) ||
529 (aStr.indexOfL(RTL_CONSTASCII_STRINGPARAM("poly")) != -1) )
531 if ( ( aStr.indexOf('(') != -1 ) &&
532 ( aStr.indexOf(')') != -1 ) )
534 nRet = IMAP_FORMAT_CERN;
536 else
537 nRet = IMAP_FORMAT_NCSA;
539 break;
544 rIStm.Seek( nPos );
546 return nRet;
549 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */