Bump version to 5.0-14
[LibreOffice.git] / svtools / source / misc / imap2.cxx
blob0ac0804d56754bbd4659a5264d2ede9721793a34
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)
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(") ");
53 void IMapObject::AppendNCSACoords(OStringBuffer& rBuf, const Point& rPoint100)
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 OUString& rBaseURL) const
65 rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative(rBaseURL, aURL), osl_getThreadTextEncoding()));
68 void IMapObject::AppendNCSAURL(OStringBuffer& rBuf, const OUString& rBaseURL) const
70 rBuf.append(OUStringToOString(URIHelper::simpleNormalizedMakeRelative(rBaseURL, aURL), osl_getThreadTextEncoding()));
71 rBuf.append(' ');
74 void IMapRectangleObject::WriteCERN( SvStream& rOStm, const OUString& rBaseURL ) const
76 OStringBuffer aStrBuf("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 OUString& rBaseURL ) const
87 OStringBuffer aStrBuf("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 OUString& rBaseURL ) const
98 OStringBuffer aStrBuf("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 OUString& rBaseURL ) const
110 OStringBuffer aStrBuf("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 OUString& rBaseURL ) const
121 OStringBuffer aStrBuf("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 OUString& rBaseURL ) const
134 OStringBuffer aStrBuf("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 OUString& rBaseURL ) const
147 switch( nFormat )
149 case( IMAP_FORMAT_BIN ) : Write( rOStm, rBaseURL ); break;
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 OUString& rBaseURL ) const
160 size_t nCount = maList.size();
162 for ( size_t i = 0; i < nCount; i++ )
164 IMapObject* pObj = maList[ i ];
166 switch( pObj->GetType() )
168 case( IMAP_OBJ_RECTANGLE ):
169 static_cast<IMapRectangleObject*>( pObj )->WriteCERN( rOStm, rBaseURL );
170 break;
172 case( IMAP_OBJ_CIRCLE ):
173 static_cast<IMapCircleObject*>( pObj )->WriteCERN( rOStm, rBaseURL );
174 break;
176 case( IMAP_OBJ_POLYGON ):
177 static_cast<IMapPolygonObject*>( pObj )->WriteCERN( rOStm, rBaseURL );
178 break;
180 default:
181 break;
186 void ImageMap::ImpWriteNCSA( SvStream& rOStm, const OUString& rBaseURL ) const
188 size_t nCount = maList.size();
190 for ( size_t i = 0; i < nCount; i++ )
192 IMapObject* pObj = maList[ i ];
194 switch( pObj->GetType() )
196 case( IMAP_OBJ_RECTANGLE ):
197 static_cast<IMapRectangleObject*>( pObj )->WriteNCSA( rOStm, rBaseURL );
198 break;
200 case( IMAP_OBJ_CIRCLE ):
201 static_cast<IMapCircleObject*>( pObj )->WriteNCSA( rOStm, rBaseURL );
202 break;
204 case( IMAP_OBJ_POLYGON ):
205 static_cast<IMapPolygonObject*>( pObj )->WriteNCSA( rOStm, rBaseURL );
206 break;
208 default:
209 break;
214 sal_uLong ImageMap::Read( SvStream& rIStm, sal_uLong nFormat, const OUString& rBaseURL )
216 sal_uLong nRet = IMAP_ERR_FORMAT;
218 if ( nFormat == IMAP_FORMAT_DETECT )
219 nFormat = ImpDetectFormat( rIStm );
221 switch ( nFormat )
223 case ( IMAP_FORMAT_BIN ) : Read( rIStm, rBaseURL ); break;
224 case ( IMAP_FORMAT_CERN ) : nRet = ImpReadCERN( rIStm, rBaseURL ); break;
225 case ( IMAP_FORMAT_NCSA ) : nRet = ImpReadNCSA( rIStm, rBaseURL ); break;
227 default:
228 break;
231 if ( !rIStm.GetError() )
232 nRet = IMAP_ERR_OK;
234 return nRet;
237 sal_uLong ImageMap::ImpReadCERN( SvStream& rIStm, const OUString& rBaseURL )
239 // delete old content
240 ClearImageMap();
242 OString aStr;
243 while ( rIStm.ReadLine( aStr ) )
244 ImpReadCERNLine( aStr, rBaseURL );
246 return IMAP_ERR_OK;
249 void ImageMap::ImpReadCERNLine( const OString& rLine, const OUString& rBaseURL )
251 OString aStr = comphelper::string::stripStart(rLine, ' ');
252 aStr = comphelper::string::stripStart(aStr, '\t');
253 aStr = comphelper::string::remove(aStr, ';');
254 aStr = aStr.toAsciiLowerCase();
256 const char* pStr = aStr.getStr();
257 char cChar = *pStr++;
259 // find instruction
260 OStringBuffer aBuf;
261 while( ( cChar >= 'a' ) && ( cChar <= 'z' ) && NOTEOL( cChar ) )
263 aBuf.append(cChar);
264 cChar = *pStr++;
266 OString aToken = aBuf.makeStringAndClear();
268 if ( NOTEOL( cChar ) )
270 if ( ( aToken == "rectangle" ) || ( aToken == "rect" ) )
272 const Point aTopLeft( ImpReadCERNCoords( &pStr ) );
273 const Point aBottomRight( ImpReadCERNCoords( &pStr ) );
274 const OUString aURL( ImpReadCERNURL( &pStr, rBaseURL ) );
275 const Rectangle aRect( aTopLeft, aBottomRight );
277 IMapRectangleObject* pObj = new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() );
278 maList.push_back( pObj );
280 else if ( ( aToken == "circle" ) || ( aToken == "circ" ) )
282 const Point aCenter( ImpReadCERNCoords( &pStr ) );
283 const long nRadius = ImpReadCERNRadius( &pStr );
284 const OUString aURL( ImpReadCERNURL( &pStr, rBaseURL ) );
286 IMapCircleObject* pObj = new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() );
287 maList.push_back( pObj );
289 else if ( ( aToken == "polygon" ) || ( aToken == "poly" ) )
291 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr,
292 '(') - 1;
293 Polygon aPoly( nCount );
294 OUString aURL;
296 for ( sal_uInt16 i = 0; i < nCount; i++ )
297 aPoly[ i ] = ImpReadCERNCoords( &pStr );
299 aURL = ImpReadCERNURL( &pStr, rBaseURL );
301 IMapPolygonObject* pObj = new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() );
302 maList.push_back( pObj );
307 Point ImageMap::ImpReadCERNCoords( const char** ppStr )
309 OUStringBuffer aStrX;
310 OUStringBuffer aStrY;
311 Point aPt;
312 char cChar = *(*ppStr)++;
314 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
315 cChar = *(*ppStr)++;
317 if ( NOTEOL( cChar ) )
319 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
321 aStrX.append( cChar );
322 cChar = *(*ppStr)++;
325 if ( NOTEOL( cChar ) )
327 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
328 cChar = *(*ppStr)++;
330 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
332 aStrY.append( cChar );
333 cChar = *(*ppStr)++;
336 if ( NOTEOL( cChar ) )
337 while( NOTEOL( cChar ) && ( cChar != ')' ) )
338 cChar = *(*ppStr)++;
340 aPt = Point( aStrX.makeStringAndClear().toInt32(), aStrY.makeStringAndClear().toInt32() );
344 return aPt;
347 long ImageMap::ImpReadCERNRadius( const char** ppStr )
349 OUStringBuffer aStr;
350 char cChar = *(*ppStr)++;
352 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
353 cChar = *(*ppStr)++;
355 if ( NOTEOL( cChar ) )
357 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
359 aStr.append( cChar );
360 cChar = *(*ppStr)++;
364 return aStr.makeStringAndClear().toInt32();
367 OUString ImageMap::ImpReadCERNURL( const char** ppStr, const OUString& rBaseURL )
369 OUString aStr(OUString::createFromAscii(*ppStr));
371 aStr = comphelper::string::stripStart(aStr, ' ');
372 aStr = comphelper::string::stripStart(aStr, '\t');
373 aStr = comphelper::string::stripEnd(aStr, ' ');
374 aStr = comphelper::string::stripEnd(aStr, '\t');
376 return INetURLObject::GetAbsURL( rBaseURL, aStr );
379 sal_uLong ImageMap::ImpReadNCSA( SvStream& rIStm, const OUString& rBaseURL )
381 // delete old content
382 ClearImageMap();
384 OString aStr;
385 while ( rIStm.ReadLine( aStr ) )
386 ImpReadNCSALine( aStr, rBaseURL );
388 return IMAP_ERR_OK;
391 void ImageMap::ImpReadNCSALine( const OString& rLine, const OUString& rBaseURL )
393 OString aStr = comphelper::string::stripStart(rLine, ' ');
394 aStr = comphelper::string::stripStart(aStr, '\t');
395 aStr = comphelper::string::remove(aStr, ';');
396 aStr = aStr.toAsciiLowerCase();
398 const char* pStr = aStr.getStr();
399 char cChar = *pStr++;
401 // find instruction
402 OStringBuffer aBuf;
403 while( ( cChar >= 'a' ) && ( cChar <= 'z' ) && NOTEOL( cChar ) )
405 aBuf.append(cChar);
406 cChar = *pStr++;
408 OString aToken = aBuf.makeStringAndClear();
410 if ( NOTEOL( cChar ) )
412 if ( aToken == "rect" )
414 const OUString aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
415 const Point aTopLeft( ImpReadNCSACoords( &pStr ) );
416 const Point aBottomRight( ImpReadNCSACoords( &pStr ) );
417 const Rectangle aRect( aTopLeft, aBottomRight );
419 IMapRectangleObject* pObj = new IMapRectangleObject( aRect, aURL, OUString(), OUString(), OUString(), OUString() );
420 maList.push_back( pObj );
422 else if ( aToken == "circle" )
424 const OUString aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
425 const Point aCenter( ImpReadNCSACoords( &pStr ) );
426 const Point aDX( aCenter - ImpReadNCSACoords( &pStr ) );
427 long nRadius = (long) sqrt( (double) aDX.X() * aDX.X() +
428 (double) aDX.Y() * aDX.Y() );
430 IMapCircleObject* pObj = new IMapCircleObject( aCenter, nRadius, aURL, OUString(), OUString(), OUString(), OUString() );
431 maList.push_back( pObj );
433 else if ( aToken == "poly" )
435 const sal_uInt16 nCount = comphelper::string::getTokenCount(aStr,
436 ',') - 1;
437 const OUString aURL( ImpReadNCSAURL( &pStr, rBaseURL ) );
438 Polygon aPoly( nCount );
440 for ( sal_uInt16 i = 0; i < nCount; i++ )
441 aPoly[ i ] = ImpReadNCSACoords( &pStr );
443 IMapPolygonObject* pObj = new IMapPolygonObject( aPoly, aURL, OUString(), OUString(), OUString(), OUString() );
444 maList.push_back( pObj );
449 OUString ImageMap::ImpReadNCSAURL( const char** ppStr, const OUString& rBaseURL )
451 OUStringBuffer aStr;
452 char cChar = *(*ppStr)++;
454 while( NOTEOL( cChar ) && ( ( cChar == ' ' ) || ( cChar == '\t' ) ) )
455 cChar = *(*ppStr)++;
457 if ( NOTEOL( cChar ) )
459 while( NOTEOL( cChar ) && ( cChar != ' ' ) && ( cChar != '\t' ) )
461 aStr.append( cChar );
462 cChar = *(*ppStr)++;
466 return INetURLObject::GetAbsURL( rBaseURL, aStr.makeStringAndClear() );
469 Point ImageMap::ImpReadNCSACoords( const char** ppStr )
471 OUStringBuffer aStrX;
472 OUStringBuffer aStrY;
473 Point aPt;
474 char cChar = *(*ppStr)++;
476 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
477 cChar = *(*ppStr)++;
479 if ( NOTEOL( cChar ) )
481 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
483 aStrX.append( cChar );
484 cChar = *(*ppStr)++;
487 if ( NOTEOL( cChar ) )
489 while( NOTEOL( cChar ) && ( ( cChar < '0' ) || ( cChar > '9' ) ) )
490 cChar = *(*ppStr)++;
492 while( NOTEOL( cChar ) && ( cChar >= '0' ) && ( cChar <= '9' ) )
494 aStrY.append( cChar );
495 cChar = *(*ppStr)++;
498 aPt = Point( aStrX.makeStringAndClear().toInt32(), aStrY.makeStringAndClear().toInt32() );
502 return aPt;
505 sal_uLong ImageMap::ImpDetectFormat( SvStream& rIStm )
507 sal_uLong nPos = rIStm.Tell();
508 sal_uLong nRet = IMAP_FORMAT_BIN;
509 char cMagic[6];
511 rIStm.Read( cMagic, sizeof( cMagic ) );
513 // if we do not have an internal formats
514 // we check the format
515 if ( memcmp( cMagic, IMAPMAGIC, sizeof( cMagic ) ) )
517 long nCount = 128;
519 rIStm.Seek( nPos );
520 OString aStr;
521 while ( rIStm.ReadLine( aStr ) && nCount-- )
523 aStr = aStr.toAsciiLowerCase();
525 if ( (aStr.indexOf("rect") != -1) ||
526 (aStr.indexOf("circ") != -1) ||
527 (aStr.indexOf("poly") != -1) )
529 if ( ( aStr.indexOf('(') != -1 ) &&
530 ( aStr.indexOf(')') != -1 ) )
532 nRet = IMAP_FORMAT_CERN;
534 else
535 nRet = IMAP_FORMAT_NCSA;
537 break;
542 rIStm.Seek( nPos );
544 return nRet;
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */