diff options
Diffstat (limited to 'include/tools')
55 files changed, 9076 insertions, 0 deletions
diff --git a/include/tools/GenericTypeSerializer.hxx b/include/tools/GenericTypeSerializer.hxx new file mode 100644 index 0000000000..f67d92c845 --- /dev/null +++ b/include/tools/GenericTypeSerializer.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_GENERICTYPESERIALIZER_HXX +#define INCLUDED_TOOLS_GENERICTYPESERIALIZER_HXX + +#include <tools/toolsdllapi.h> +#include <tools/color.hxx> +#include <tools/gen.hxx> +#include <tools/stream.hxx> +#include <tools/fract.hxx> + +namespace tools +{ +class TOOLS_DLLPUBLIC GenericTypeSerializer +{ +public: + SvStream& mrStream; + + GenericTypeSerializer(SvStream& rStream) + : mrStream(rStream) + { + } + + void readColor(Color& rColor); + void writeColor(const Color& rColor); + + void readPoint(Point& rPoint); + void writePoint(const Point& rPoint); + + void readSize(Size& rSize); + void writeSize(const Size& rSize); + + void readRectangle(Rectangle& rRectangle); + void writeRectangle(const Rectangle& rRectangle); + + void readFraction(Fraction& rFraction); + void writeFraction(Fraction const& rFraction); +}; + +} // end namespace tools + +#endif // INCLUDED_TOOLS_GENERICTYPESERIALIZER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/Guid.hxx b/include/tools/Guid.hxx new file mode 100644 index 0000000000..3922a3da9f --- /dev/null +++ b/include/tools/Guid.hxx @@ -0,0 +1,165 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <array> +#include <rtl/uuid.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <algorithm> +#include <stdio.h> +#include <cctype> + +namespace tools +{ +class Guid +{ +private: + typedef std::array<sal_uInt8, 16> GuidArrayType; + + GuidArrayType maGuidArray; + + static sal_uInt8 gethex(char nChar) + { + if (nChar >= '0' && nChar <= '9') + return nChar - '0'; + else if (nChar >= 'a' && nChar <= 'f') + return nChar - 'a' + 10; + else if (nChar >= 'A' && nChar <= 'F') + return nChar - 'A' + 10; + else + return 0; + } + + static sal_uInt8 covertHexChar(char high, char low) + { + return (gethex(high) << 4) + gethex(low); + } + + void parse(std::string_view rString) + { + if (rString.size() != 38) + return; + + if (rString[0] != '{' || rString[37] != '}' || rString[9] != '-' || rString[14] != '-' + || rString[19] != '-' || rString[24] != '-') + return; + + for (size_t x = 1; x <= 8; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 10; x <= 13; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 15; x <= 18; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 20; x <= 23; x++) + if (!std::isxdigit(rString[x])) + return; + for (size_t x = 25; x <= 36; x++) + if (!std::isxdigit(rString[x])) + return; + + maGuidArray[0] = covertHexChar(rString[1], rString[2]); + maGuidArray[1] = covertHexChar(rString[3], rString[4]); + maGuidArray[2] = covertHexChar(rString[5], rString[6]); + maGuidArray[3] = covertHexChar(rString[7], rString[8]); + + maGuidArray[4] = covertHexChar(rString[10], rString[11]); + maGuidArray[5] = covertHexChar(rString[12], rString[13]); + + maGuidArray[6] = covertHexChar(rString[15], rString[16]); + maGuidArray[7] = covertHexChar(rString[17], rString[18]); + + maGuidArray[8] = covertHexChar(rString[20], rString[21]); + maGuidArray[9] = covertHexChar(rString[22], rString[23]); + + maGuidArray[10] = covertHexChar(rString[25], rString[26]); + maGuidArray[11] = covertHexChar(rString[27], rString[28]); + maGuidArray[12] = covertHexChar(rString[29], rString[30]); + maGuidArray[13] = covertHexChar(rString[31], rString[32]); + maGuidArray[14] = covertHexChar(rString[33], rString[34]); + maGuidArray[15] = covertHexChar(rString[35], rString[36]); + } + +public: + /// GenerateTag is used as a flag for generating the GUID + enum GenerateTag + { + Generate = 0 + }; + + /// Constructor which generates the GUID + Guid(enum GenerateTag) { rtl_createUuid(maGuidArray.data(), nullptr, false); } + + /// Default constructor which initializes the values to 0 (empty GUID) + Guid() { maGuidArray.fill(0); } + + /// parse the GUID from the string + Guid(std::string_view rString) + { + maGuidArray.fill(0); + parse(rString); + } + + /// set the GUID from an array + Guid(const sal_uInt8 aGuidArray[16]) + { + std::copy(aGuidArray, aGuidArray + 16, maGuidArray.begin()); + } + + Guid(Guid&&) = delete; + + Guid(Guid const& rOther) { *this = rOther; } + + void operator=(Guid const& rOther) { std::copy(rOther.cbegin(), rOther.cend(), begin()); } + + bool isEmpty() { return *std::max_element(maGuidArray.begin(), maGuidArray.end()) == 0; } + + GuidArrayType::iterator begin() { return maGuidArray.begin(); } + GuidArrayType::iterator end() { return maGuidArray.end(); } + GuidArrayType::const_iterator cbegin() const { return maGuidArray.cbegin(); } + GuidArrayType::const_iterator cend() const { return maGuidArray.cend(); } + + OString getString() const + { + char sBuffer[40]; + snprintf(sBuffer, sizeof(sBuffer), + "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", + maGuidArray[0], maGuidArray[1], maGuidArray[2], maGuidArray[3], maGuidArray[4], + maGuidArray[5], maGuidArray[6], maGuidArray[7], maGuidArray[8], maGuidArray[9], + maGuidArray[10], maGuidArray[11], maGuidArray[12], maGuidArray[13], + maGuidArray[14], maGuidArray[15]); + + return OString(sBuffer); + } + + OUString getOUString() { return OStringToOUString(getString(), RTL_TEXTENCODING_ASCII_US); } + + bool operator==(Guid const& rCompare) const + { + return rtl_compareUuid(maGuidArray.data(), rCompare.maGuidArray.data()) == 0; + } + + bool operator!=(Guid const& rCompare) const { return !(*this == rCompare); } +}; + +template <typename charT, typename traits> +inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& rStream, + tools::Guid const& rGuid) +{ + OString aString = rGuid.getString(); + rStream << "GUID" << aString.getStr(); + return rStream; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/UnitConversion.hxx b/include/tools/UnitConversion.hxx new file mode 100644 index 0000000000..43237e0514 --- /dev/null +++ b/include/tools/UnitConversion.hxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include <o3tl/unit_conversion.hxx> +#include <sal/types.h> +#include <tools/fldunit.hxx> +#include <tools/fract.hxx> +#include <tools/mapunit.hxx> + +constexpr o3tl::Length FieldToO3tlLength(FieldUnit eU, o3tl::Length ePixelValue = o3tl::Length::px) +{ + switch (eU) + { + case FieldUnit::MM: + return o3tl::Length::mm; + case FieldUnit::CM: + return o3tl::Length::cm; + case FieldUnit::M: + return o3tl::Length::m; + case FieldUnit::KM: + return o3tl::Length::km; + case FieldUnit::TWIP: + return o3tl::Length::twip; + case FieldUnit::POINT: + return o3tl::Length::pt; + case FieldUnit::PICA: + return o3tl::Length::pc; + case FieldUnit::INCH: + return o3tl::Length::in; + case FieldUnit::FOOT: + return o3tl::Length::ft; + case FieldUnit::MILE: + return o3tl::Length::mi; + case FieldUnit::CHAR: + return o3tl::Length::ch; + case FieldUnit::LINE: + return o3tl::Length::line; + case FieldUnit::MM_100TH: + return o3tl::Length::mm100; + case FieldUnit::PIXEL: + return ePixelValue; + default: + return o3tl::Length::invalid; + } +} + +constexpr o3tl::Length MapToO3tlLength(MapUnit eU, o3tl::Length ePixelValue = o3tl::Length::px) +{ + switch (eU) + { + case MapUnit::Map100thMM: + return o3tl::Length::mm100; + case MapUnit::Map10thMM: + return o3tl::Length::mm10; + case MapUnit::MapMM: + return o3tl::Length::mm; + case MapUnit::MapCM: + return o3tl::Length::cm; + case MapUnit::Map1000thInch: + return o3tl::Length::in1000; + case MapUnit::Map100thInch: + return o3tl::Length::in100; + case MapUnit::Map10thInch: + return o3tl::Length::in10; + case MapUnit::MapInch: + return o3tl::Length::in; + case MapUnit::MapPoint: + return o3tl::Length::pt; + case MapUnit::MapTwip: + return o3tl::Length::twip; + case MapUnit::MapPixel: + return ePixelValue; + default: + return o3tl::Length::invalid; + } +} + +inline Fraction conversionFract(o3tl::Length from, o3tl::Length to) +{ + const auto & [ mul, div ] = o3tl::getConversionMulDiv(from, to); + return { mul, div }; +} + +template <typename N> constexpr auto convertTwipToMm100(N n) +{ + return o3tl::convert(n, o3tl::Length::twip, o3tl::Length::mm100); +} + +constexpr sal_Int64 sanitiseMm100ToTwip(sal_Int64 n) +{ + return o3tl::convertSaturate(n, o3tl::Length::mm100, o3tl::Length::twip); +} + +template <typename N> constexpr auto convertPointToMm100(N n) +{ + return o3tl::convert(n, o3tl::Length::pt, o3tl::Length::mm100); +} +template <typename N> constexpr auto convertMm100ToPoint(N n) +{ + return o3tl::convert(n, o3tl::Length::mm100, o3tl::Length::pt); +} + +// PPT's "master unit" (1/576 inch) <=> mm/100 +template <typename N> constexpr auto convertMasterUnitToMm100(N n) +{ + return o3tl::convert(n, o3tl::Length::master, o3tl::Length::mm100); +} +template <typename N> constexpr auto convertMm100ToMasterUnit(N n) +{ + return o3tl::convert(n, o3tl::Length::mm100, o3tl::Length::master); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/XmlWalker.hxx b/include/tools/XmlWalker.hxx new file mode 100644 index 0000000000..ba9d18e856 --- /dev/null +++ b/include/tools/XmlWalker.hxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_TOOLS_XMLWALKER_HXX +#define INCLUDED_TOOLS_XMLWALKER_HXX + +#include <tools/toolsdllapi.h> +#include <rtl/string.hxx> +#include <memory> + +class SvStream; + +namespace tools +{ +struct XmlWalkerImpl; + +/** + * XmlWalker main purpose is to make it easier for walking the + * parsed XML DOM tree. + * + * It hides all the libxml2 and C -isms and makes the usage more + * comfortable from LO developer point of view. + * + */ +class TOOLS_DLLPUBLIC XmlWalker final +{ +private: + std::unique_ptr<XmlWalkerImpl> mpImpl; + +public: + XmlWalker(); + + ~XmlWalker(); + + bool open(SvStream* pStream); + + OString name(); + OString namespaceHref(); + OString namespacePrefix(); + + OString content(); + void children(); + void parent(); + void next(); + bool isValid() const; + OString attribute(const OString& sName) const; +}; + +} // end tools namespace + +#endif // INCLUDED_TOOLS_XMLWRITER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/XmlWriter.hxx b/include/tools/XmlWriter.hxx new file mode 100644 index 0000000000..400748611b --- /dev/null +++ b/include/tools/XmlWriter.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_TOOLS_XMLWRITER_HXX +#define INCLUDED_TOOLS_XMLWRITER_HXX + +#include <tools/toolsdllapi.h> +#include <rtl/string.hxx> +#include <memory> +#include <string_view> +#include <vector> + +class SvStream; + +namespace tools +{ +struct XmlWriterImpl; + +/** + * XmlWriter writes a XML to a SvStream. It uses libxml2 for writing but hides + * all the internal libxml2 workings and uses types that are native for LO + * development. + * + * The codepage used for XML is always "utf-8" and the output is indented by + * default so it is easier to read. + * + */ +class TOOLS_DLLPUBLIC XmlWriter final +{ +private: + std::unique_ptr<XmlWriterImpl> mpImpl; + +public: + XmlWriter(SvStream* pStream); + + ~XmlWriter(); + + bool startDocument(sal_Int32 nIndent = 2, bool bWriteXmlHeader = true); + void endDocument(); + + void startElement(const char* sName); + void startElement(const OString& sName); + void startElement(const OString& sPrefix, const OString& sName, const OString& sNamespaceUri); + void endElement(); + + void attribute(const char* sTagName, const OString& aValue); + void attribute(const OString& sTagName, const OString& aValue); + void attribute(const char* sTagName, std::u16string_view aValue); + void attribute(const char* sTagName, sal_Int32 aNumber); + void attributeDouble(const char* sTagName, double aNumber); + void attributeBase64(const char* sTagName, std::vector<sal_uInt8> const& rValueInBytes); + void attributeBase64(const char* sTagName, std::vector<char> const& rValueInBytes); + + void content(const OString& sValue); + void content(std::u16string_view sValue); + + void element(const char* sName); +}; + +} // end tools namespace + +#endif // INCLUDED_TOOLS_XMLWRITER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/b3dtrans.hxx b/include/tools/b3dtrans.hxx new file mode 100644 index 0000000000..2f6752e084 --- /dev/null +++ b/include/tools/b3dtrans.hxx @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_TOOLS_B3DTRANS_HXX +#define INCLUDED_TOOLS_B3DTRANS_HXX + +#define ZBUFFER_DEPTH_RANGE (double(256L * 256L * 256L)) + +#include <basegfx/matrix/b3dhommatrix.hxx> +#include <tools/gen.hxx> +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/point/b3dpoint.hxx> +#include <basegfx/vector/b3dvector.hxx> +#include <tools/toolsdllapi.h> + +/// Transformation sets for 3D output +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC B3dTransformationSet +{ +private: + // Object Matrix Object -> World + basegfx::B3DHomMatrix maObjectTrans; + basegfx::B3DHomMatrix maInvObjectTrans; + + // Orientation Matrix + basegfx::B3DHomMatrix maOrientation; + basegfx::B3DHomMatrix maInvOrientation; + + // Projection Matrix + basegfx::B3DHomMatrix maProjection; + basegfx::B3DHomMatrix maInvProjection; + + // Texture Matrices + basegfx::B2DHomMatrix maTexture; + + // Parameters for ViewportTransformation + basegfx::B3DVector maScale; + basegfx::B3DVector maTranslate; + + // ViewPlane DeviceRectangle (user-defined) + double mfLeftBound; + double mfRightBound; + double mfBottomBound; + double mfTopBound; + + // Aspect ratio of 3D transformation (Y / X) + // default: 1:1 -> 1.0 + // Disable with value 0.0 + double mfRatio; + + // Viewport area in logical coordinates + tools::Rectangle maViewportRectangle; + // Visible area within viewport + tools::Rectangle maVisibleRectangle; + + // Actual coordinates as set by CalcViewport + // of visible viewport area (logical coordinates) + tools::Rectangle maSetBound; + + // Flags + bool mbPerspective : 1; + bool mbProjectionValid : 1; + +public: + B3dTransformationSet(); + virtual ~B3dTransformationSet(); + + B3dTransformationSet(B3dTransformationSet const &) = default; + B3dTransformationSet(B3dTransformationSet &&) = default; + B3dTransformationSet & operator =(B3dTransformationSet const &) = default; + B3dTransformationSet & operator =(B3dTransformationSet &&) = default; + + void Reset(); + + /** Set the orientation + + @param vVRP the View Reference Point (VRP) + @param vVPN the View Plane Normal (VPN) + @param vVUP the View Up Plane (VUP) + */ + void SetOrientation( + const basegfx::B3DPoint& rVRP = basegfx::B3DPoint(0.0,0.0,1.0), + const basegfx::B3DVector& rVPN = basegfx::B3DVector(0.0,0.0,1.0), + const basegfx::B3DVector& rVUP = basegfx::B3DVector(0.0,1.0,0.0)); + + // Projection + void SetProjection(const basegfx::B3DHomMatrix& mProject); + const basegfx::B3DHomMatrix& GetProjection(); + + // Texture + + // aspect ratio accessors and the defined method of keeping defined aspect ratio + double GetRatio() const { return mfRatio; } + void SetRatio(double fNew); + + // Parameters of ViewportTransformation + void SetDeviceRectangle(double fL=-1.0, double fR=1.0, + double fB=-1.0, double fT=1.0); + double GetDeviceRectangleWidth() const { return mfRightBound - mfLeftBound; } + + void SetPerspective(bool bNew); + + void SetViewportRectangle(tools::Rectangle const & rRect, tools::Rectangle const & rVisible); + void SetViewportRectangle(tools::Rectangle const & rRect) { SetViewportRectangle(rRect, rRect); } + + void CalcViewport(); + + // Direct accessors for miscellaneous transformations + basegfx::B3DPoint WorldToEyeCoor(const basegfx::B3DPoint& rVec); + basegfx::B3DPoint EyeToWorldCoor(const basegfx::B3DPoint& rVec); + + static void Frustum( + basegfx::B3DHomMatrix& rTarget, + double fLeft = -1.0, double fRight = 1.0, + double fBottom = -1.0, double fTop = 1.0, + double fNear = 0.001, double fFar = 1.0); + static void Ortho( + basegfx::B3DHomMatrix& rTarget, + double fLeft = -1.0, double fRight = 1.0, + double fBottom = -1.0, double fTop = 1.0, + double fNear = 0.0, double fFar = 1.0); + static void Orientation( + basegfx::B3DHomMatrix& rTarget, + const basegfx::B3DPoint& aVRP = basegfx::B3DPoint(0.0,0.0,1.0), + basegfx::B3DVector aVPN = basegfx::B3DVector(0.0,0.0,1.0), + basegfx::B3DVector aVUP = basegfx::B3DVector(0.0,1.0,0.0)); + +protected: + void PostSetObjectTrans(); + void PostSetOrientation(); + void PostSetProjection(); + + virtual void DeviceRectangleChange(); +}; + +/** Viewport for B3D + + Uses a simplified model, in which a point is described using a View + Reference Point (VRP). +*/ +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC B3dViewport : public B3dTransformationSet +{ +private: + basegfx::B3DPoint aVRP; // View Reference Point + basegfx::B3DVector aVPN; // View Plane Normal + basegfx::B3DVector aVUV; // View Up Vector + +public: + B3dViewport(); + virtual ~B3dViewport() override; + + B3dViewport(B3dViewport const &) = default; + B3dViewport(B3dViewport &&) = default; + B3dViewport & operator =(B3dViewport const &) = default; + B3dViewport & operator =(B3dViewport &&) = default; + + void SetVUV(const basegfx::B3DVector& rNewVUV); + void SetViewportValues( + const basegfx::B3DPoint& rNewVRP, + const basegfx::B3DVector& rNewVPN, + const basegfx::B3DVector& rNewVUV); + + const basegfx::B3DPoint& GetVRP() const { return aVRP; } + const basegfx::B3DVector& GetVPN() const { return aVPN; } + const basegfx::B3DVector& GetVUV() const { return aVUV; } + +protected: + void CalcOrientation(); +}; + +// B3D camera + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC B3dCamera final : public B3dViewport +{ +public: + B3dCamera( + const basegfx::B3DPoint& rPos = basegfx::B3DPoint(0.0, 0.0, 1.0), + const basegfx::B3DVector& rLkAt = basegfx::B3DVector(0.0, 0.0, 0.0), + double fFocLen = 35.0, double fBnkAng = 0.0); + virtual ~B3dCamera() override; + + B3dCamera(B3dCamera const &) = default; + B3dCamera(B3dCamera &&) = default; + B3dCamera & operator =(B3dCamera const &) = default; + B3dCamera & operator =(B3dCamera &&) = default; + +private: + void CalcNewViewportValues(); + void CalcFocalLength(); + + virtual void DeviceRectangleChange() override; + + basegfx::B3DPoint aPosition; + basegfx::B3DVector aLookAt; + double fFocalLength; + double fBankAngle; + +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/bigint.hxx b/include/tools/bigint.hxx new file mode 100644 index 0000000000..f8f57fc45d --- /dev/null +++ b/include/tools/bigint.hxx @@ -0,0 +1,255 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_BIGINT_HXX +#define INCLUDED_TOOLS_BIGINT_HXX + +#include <tools/toolsdllapi.h> +#include <tools/long.hxx> + +#include <cassert> +#include <string_view> + +#define MAX_DIGITS 8 + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC BigInt +{ +private: + // we only use one of these two fields at a time + union { + sal_Int32 nVal; + sal_uInt16 nNum[MAX_DIGITS]; + }; + sal_uInt8 nLen : 5; // current length, if 0, data is in nVal, otherwise data is in nNum + bool bIsNeg : 1; // Is Sign negative? + + TOOLS_DLLPRIVATE void MakeBigInt(BigInt const &); + TOOLS_DLLPRIVATE void Normalize(); + TOOLS_DLLPRIVATE void Mult(BigInt const &, sal_uInt16); + TOOLS_DLLPRIVATE void Div(sal_uInt16, sal_uInt16 &); + TOOLS_DLLPRIVATE bool IsLess(BigInt const &) const; + TOOLS_DLLPRIVATE void AddLong(BigInt &, BigInt &); + TOOLS_DLLPRIVATE void SubLong(BigInt &, BigInt &); + TOOLS_DLLPRIVATE void MultLong(BigInt const &, BigInt &) const; + TOOLS_DLLPRIVATE void DivLong(BigInt const &, BigInt &) const; + TOOLS_DLLPRIVATE void ModLong(BigInt const &, BigInt &) const; + TOOLS_DLLPRIVATE bool ABS_IsLess(BigInt const &) const; + +public: + BigInt() + : nVal(0) + , nLen(0) + , bIsNeg(false) + { + } + + BigInt(sal_Int32 nValue) + : nVal(nValue) + , nLen(0) + , bIsNeg(false) + { + } + +#if SAL_TYPES_SIZEOFLONG == 4 + BigInt(int nValue) + : nVal(nValue) + , nLen(0) + , bIsNeg(false) + { + } +#endif + + BigInt( double nVal ); + BigInt( sal_uInt32 nVal ); + BigInt( sal_Int64 nVal ); + BigInt( const BigInt& rBigInt ); + BigInt( std::u16string_view rString ); + + operator sal_Int16() const; + operator sal_uInt16() const; + operator sal_Int32() const; + operator sal_uInt32() const; + operator double() const; +#if SAL_TYPES_SIZEOFPOINTER == 8 + operator tools::Long() const; +#endif + + bool IsNeg() const; + bool IsZero() const; + bool IsLong() const { return nLen == 0; } + + void Abs(); + + BigInt& operator =( const BigInt& rVal ); + BigInt& operator +=( const BigInt& rVal ); + BigInt& operator -=( const BigInt& rVal ); + BigInt& operator *=( const BigInt& rVal ); + BigInt& operator /=( const BigInt& rVal ); + BigInt& operator %=( const BigInt& rVal ); + + BigInt& operator =( sal_Int32 nValue ); + + /* Scale and round value */ + static tools::Long Scale(tools::Long nVal, tools::Long nMult, tools::Long nDiv); + + friend inline BigInt operator +( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline BigInt operator -( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline BigInt operator *( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline BigInt operator /( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline BigInt operator %( const BigInt& rVal1, const BigInt& rVal2 ); + + TOOLS_DLLPUBLIC friend bool operator==( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline bool operator!=( const BigInt& rVal1, const BigInt& rVal2 ); + TOOLS_DLLPUBLIC friend bool operator< ( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline bool operator> ( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline bool operator<=( const BigInt& rVal1, const BigInt& rVal2 ); + friend inline bool operator>=( const BigInt& rVal1, const BigInt& rVal2 ); + + friend class Fraction; +}; + +inline BigInt::operator sal_Int16() const +{ + if ( nLen == 0 && nVal >= SAL_MIN_INT16 && nVal <= SAL_MAX_INT16 ) + return static_cast<sal_Int16>(nVal); + assert(false && "out of range"); + return 0; +} + +inline BigInt::operator sal_uInt16() const +{ + if ( nLen == 0 && nVal >= 0 && nVal <= SAL_MAX_UINT16 ) + return static_cast<sal_uInt16>(nVal); + assert(false && "out of range"); + return 0; +} + +inline BigInt::operator sal_Int32() const +{ + if (nLen == 0) + return nVal; + assert(false && "out of range"); + return 0; +} + +inline BigInt::operator sal_uInt32() const +{ + if ( nLen == 0 && nVal >= 0 ) + return static_cast<sal_uInt32>(nVal); + assert(false && "out of range"); + return 0; +} + +#if SAL_TYPES_SIZEOFPOINTER == 8 +inline BigInt::operator tools::Long() const +{ + // Clamp to int32 since long is int32 on Windows. + if (nLen == 0) + return nVal; + assert(false && "out of range"); + return 0; +} +#endif + +inline BigInt& BigInt::operator =( sal_Int32 nValue ) +{ + nLen = 0; + nVal = nValue; + + return *this; +} + +inline bool BigInt::IsNeg() const +{ + if ( nLen == 0 ) + return (nVal < 0); + else + return bIsNeg; +} + +inline bool BigInt::IsZero() const +{ + if ( nLen != 0 ) + return false; + else + return (nVal == 0); +} + +inline void BigInt::Abs() +{ + if ( nLen != 0 ) + bIsNeg = false; + else if ( nVal < 0 ) + nVal = -nVal; +} + +inline BigInt operator+( const BigInt &rVal1, const BigInt &rVal2 ) +{ + BigInt aErg( rVal1 ); + aErg += rVal2; + return aErg; +} + +inline BigInt operator-( const BigInt &rVal1, const BigInt &rVal2 ) +{ + BigInt aErg( rVal1 ); + aErg -= rVal2; + return aErg; +} + +inline BigInt operator*( const BigInt &rVal1, const BigInt &rVal2 ) +{ + BigInt aErg( rVal1 ); + aErg *= rVal2; + return aErg; +} + +inline BigInt operator/( const BigInt &rVal1, const BigInt &rVal2 ) +{ + BigInt aErg( rVal1 ); + aErg /= rVal2; + return aErg; +} + +inline BigInt operator%( const BigInt &rVal1, const BigInt &rVal2 ) +{ + BigInt aErg( rVal1 ); + aErg %= rVal2; + return aErg; +} + +inline bool operator!=( const BigInt& rVal1, const BigInt& rVal2 ) +{ + return !(rVal1 == rVal2); +} + +inline bool operator>(const BigInt& rVal1, const BigInt& rVal2) { return rVal2 < rVal1; } + +inline bool operator<=( const BigInt& rVal1, const BigInt& rVal2 ) +{ + return !( rVal1 > rVal2); +} + +inline bool operator>=( const BigInt& rVal1, const BigInt& rVal2 ) +{ + return !(rVal1 < rVal2); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/color.hxx b/include/tools/color.hxx new file mode 100644 index 0000000000..8ab3544589 --- /dev/null +++ b/include/tools/color.hxx @@ -0,0 +1,523 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_COLOR_HXX +#define INCLUDED_TOOLS_COLOR_HXX + +#include <sal/types.h> +#include <tools/toolsdllapi.h> +#include <com/sun/star/uno/Any.hxx> +#include <config_global.h> +#include <basegfx/color/bcolor.hxx> +#include <osl/endian.h> + +namespace color +{ + +constexpr sal_uInt32 extractRGB(sal_uInt32 nColorNumber) +{ + return nColorNumber & 0x00FFFFFF; +} + +constexpr sal_uInt8 ColorChannelMerge(sal_uInt8 nDst, sal_uInt8 nSrc, sal_uInt8 nSrcTrans) +{ + return sal_uInt8(((sal_Int32(nDst) - nSrc) * nSrcTrans + ((nSrc << 8) | nDst)) >> 8); +} + +} + +/** used to deliberately select the right constructor */ +enum ColorTransparencyTag { ColorTransparency = 0 }; +enum ColorAlphaTag { ColorAlpha = 0 }; + +// Color + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Color +{ + union + { + sal_uInt32 mValue; + struct + { +#ifdef OSL_BIGENDIAN + sal_uInt8 T; + sal_uInt8 R; + sal_uInt8 G; + sal_uInt8 B; +#else + sal_uInt8 B; + sal_uInt8 G; + sal_uInt8 R; + sal_uInt8 T; +#endif + }; + }; + +public: + constexpr Color() + : mValue(0) // black + {} + +#if HAVE_CPP_CONSTEVAL + consteval +#else + constexpr +#endif + Color(const sal_uInt32 nColor) + : mValue(nColor) + { + assert(nColor <= 0xffffff && "don't pass transparency to this constructor, use the Color(ColorTransparencyTag,...) or Color(ColorAlphaTag,...) constructor to make it explicit"); + } + + constexpr Color(enum ColorTransparencyTag, sal_uInt32 nColor) + : mValue(nColor) + { + } + + constexpr Color(enum ColorAlphaTag, sal_uInt32 nColor) + : mValue((nColor & 0xffffff) | ((255 - (nColor >> 24)) << 24)) + { + } + + constexpr Color(enum ColorTransparencyTag, sal_uInt8 nTransparency, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue) + : mValue(sal_uInt32(nBlue) | (sal_uInt32(nGreen) << 8) | (sal_uInt32(nRed) << 16) | (sal_uInt32(nTransparency) << 24)) + {} + + constexpr Color(enum ColorAlphaTag, sal_uInt8 nAlpha, sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue) + : Color(ColorTransparency, 255 - nAlpha, nRed, nGreen, nBlue) + {} + + constexpr Color(sal_uInt8 nRed, sal_uInt8 nGreen, sal_uInt8 nBlue) + : Color(ColorTransparency, 0, nRed, nGreen, nBlue) + {} + + // constructor to create a tools-Color from ::basegfx::BColor + explicit Color(const basegfx::BColor& rBColor) + : Color(ColorTransparency, 0, + sal_uInt8(std::lround(rBColor.getRed() * 255.0)), + sal_uInt8(std::lround(rBColor.getGreen() * 255.0)), + sal_uInt8(std::lround(rBColor.getBlue() * 255.0))) + {} + + /** Casts the color to corresponding uInt32. + * Primarily used when passing Color objects to UNO API + * @return corresponding sal_uInt32 + */ + constexpr explicit operator sal_uInt32() const + { + return mValue; + } + + /** Casts the color to corresponding iInt32. + * If there is no transparency, will be positive. + * @return corresponding sal_Int32 + */ + constexpr explicit operator sal_Int32() const + { + return sal_Int32(mValue); + } + + /* Basic RGBA operations */ + + /** Gets the red value. + * @return R + */ + sal_uInt8 GetRed() const + { + return R; + } + + /** Gets the green value. + * @return G + */ + sal_uInt8 GetGreen() const + { + return G; + } + + /** Gets the blue value. + * @return B + */ + sal_uInt8 GetBlue() const + { + return B; + } + + /** Gets the alpha value. + * @return A + */ + sal_uInt8 GetAlpha() const + { + return 255 - T; + } + + /** Is the color transparent? + */ + bool IsTransparent() const + { + return GetAlpha() != 255; + } + + /** Is the color fully transparent i.e. 100% transparency ? + */ + bool IsFullyTransparent() const + { + return T == 255; + } + + /** Sets the red value. + * @param nRed + */ + void SetRed(sal_uInt8 nRed) + { + R = nRed; + } + + /** Sets the green value. + * @param nGreen + */ + void SetGreen(sal_uInt8 nGreen) + { + G = nGreen; + } + + /** Sets the blue value. + * @param nBlue + */ + void SetBlue(sal_uInt8 nBlue) + { + B = nBlue; + } + + /** Sets the alpha value. + * @param nAlpha + */ + void SetAlpha(sal_uInt8 nAlpha) + { + T = 255 - nAlpha; + } + + /** Returns the same color but ignoring the transparency value. + * @return RGB version + */ + Color GetRGBColor() const + { + return {R, G, B}; + } + + /* Comparison and operators */ + + /** Check if the color RGB value is equal than rColor. + * @param rColor + * @return is equal + */ + bool IsRGBEqual( const Color& rColor ) const + { + return ( mValue & 0x00FFFFFF ) == ( rColor.mValue & 0x00FFFFFF ); + } + + /** Check if the color value is lower than aCompareColor. + * @param aCompareColor + * @return is lower + */ + bool operator<(const Color& aCompareColor) const + { + return mValue < aCompareColor.mValue; + } + + /** Check if the color value is greater than aCompareColor. + * @param aCompareColor + * @return is greater + */ + bool operator>(const Color& aCompareColor) const + { + return mValue > aCompareColor.mValue; + } + + /** Check if the color value is equal than rColor. + * @param rColor + * @return is equal + */ + bool operator==(const Color& rColor) const + { + return mValue == rColor.mValue; + } + + /** Check if the color value is unequal than rColor. + * @param rColor + * @return is unequal + */ + bool operator!=(const Color& rColor) const + { + return mValue != rColor.mValue; + } + + /** Gets the color error compared to another. + * It describes how different they are. + * It takes the abs of differences in parameters. + * @param rCompareColor + * @return error + */ + sal_uInt16 GetColorError(const Color& rCompareColor) const + { + return static_cast<sal_uInt16>( + abs(static_cast<int>(GetBlue()) - rCompareColor.GetBlue()) + + abs(static_cast<int>(GetGreen()) - rCompareColor.GetGreen()) + + abs(static_cast<int>(GetRed()) - rCompareColor.GetRed())); + } + + /* Light and contrast */ + + /** Gets the color luminance. It means perceived brightness. + * @return luminance + */ + sal_uInt8 GetLuminance() const + { + return sal_uInt8((B * 29UL + G * 151UL + R * 76UL) >> 8); + } + + /** Increases the color luminance by cLumInc. + * @param cLumInc + */ + void IncreaseLuminance(sal_uInt8 cLumInc); + + /** Decreases the color luminance by cLumDec. + * @param cLumDec + */ + void DecreaseLuminance(sal_uInt8 cLumDec); + + /** Decreases color contrast with white by cContDec. + * @param cContDec + */ + void DecreaseContrast(sal_uInt8 cContDec); + + /** Comparison with luminance thresholds. + * @return is dark + */ + bool IsDark() const + { + // tdf#156182, and band aid for follow-up issues + if (mValue == 0x729fcf) // COL_DEFAULT_SHAPE_FILLING + return GetLuminance() <= 62; + else + return GetLuminance() <= 156; + } + + /** Comparison with luminance thresholds. + * @return is dark + */ + bool IsBright() const + { + return GetLuminance() >= 245; + } + + /* Color filters */ + + /** + * Apply tint or shade to a color. + * + * The input value is the percentage (in 100th of percent) of how much the + * color changes towards the black (shade) or white (tint). If the value + * is positive, the color is tinted, if the value is negative, the color is + * shaded. + **/ + void ApplyTintOrShade(sal_Int16 n100thPercent); + + /** + * Apply luminance offset and/or modulation. + * + * The input values are in percentages (in 100th percents). 100% modulation and 0% offset + * results in no change. + */ + void ApplyLumModOff(sal_Int16 nMod, sal_Int16 nOff); + + /** Inverts color. 1 and 0 are switched. + * Note that the result will be the complementary color. + * For example, if you have red, you will get cyan: FF0000 -> 00FFFF. + */ + void Invert() + { + R = ~R; + G = ~G; + B = ~B; + } + + /** Merges color with rMergeColor. + * Allows to get resulting color when superposing another. + * @param rMergeColor + * @param cTransparency + */ + void Merge(const Color& rMergeColor, sal_uInt8 cTransparency) + { + R = color::ColorChannelMerge(R, rMergeColor.R, cTransparency); + G = color::ColorChannelMerge(G, rMergeColor.G, cTransparency); + B = color::ColorChannelMerge(B, rMergeColor.B, cTransparency); + } + + /* Change of format */ + + /** Color space conversion tools + * The range for h/s/b is: + * - Hue: 0-360 degree + * - Saturation: 0-100% + * - Brightness: 0-100% + * @param nHue + * @param nSaturation + * @param nBrightness + * @return rgb color + */ + static Color HSBtoRGB(sal_uInt16 nHue, sal_uInt16 nSaturation, sal_uInt16 nBrightness); + + /** Converts a string into a color. Supports: + * #RRGGBB + * #rrggbb + * #RGB + * #rgb + * RRGGBB + * rrggbb + * RGB + * rgb + * If fails returns Color(). + */ + static Color STRtoRGB(std::u16string_view colorname); + + /** Color space conversion tools + * @param nHue + * @param nSaturation + * @param nBrightness + */ + void RGBtoHSB(sal_uInt16& nHue, sal_uInt16& nSaturation, sal_uInt16& nBrightness) const; + + /* Return color as RGB hex string: rrggbb + * for example "00ff00" for green color + * @return hex string + */ + OUString AsRGBHexString() const; + + /* Return color as RGB hex string: RRGGBB + * for example "00FF00" for green color + * @return hex string + */ + OUString AsRGBHEXString() const; + + /* get ::basegfx::BColor from this color + * @return basegfx color + */ + basegfx::BColor getBColor() const + { + return basegfx::BColor(R / 255.0, G / 255.0, B / 255.0); + } +}; + +// to reduce the noise when moving these into and out of Any +inline bool operator >>=( const css::uno::Any & rAny, Color & value ) +{ + sal_Int32 nTmp = {}; // spurious -Werror=maybe-uninitialized + if (!(rAny >>= nTmp)) + return false; + value = Color(ColorTransparency, nTmp); + return true; +} + +inline void operator <<=( css::uno::Any & rAny, Color value ) +{ + rAny <<= sal_Int32(value); +} + +namespace com::sun::star::uno { + template<> inline Any::Any(Color const & value): Any(sal_Int32(value)) {} +} + +// Test compile time conversion of Color to sal_uInt32 + +static_assert (sal_uInt32(Color(ColorTransparency, 0x00, 0x12, 0x34, 0x56)) == 0x00123456); +static_assert (sal_uInt32(Color(0x12, 0x34, 0x56)) == 0x00123456); + +// Color types + +inline constexpr ::Color COL_TRANSPARENT ( ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF ); +inline constexpr ::Color COL_AUTO ( ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF ); +// These are used when drawing to the separate alpha channel we use in vcl +inline constexpr ::Color COL_ALPHA_TRANSPARENT ( 0x00, 0x00, 0x00 ); +inline constexpr ::Color COL_ALPHA_OPAQUE ( 0xff, 0xff, 0xff ); + +inline constexpr ::Color COL_BLACK ( 0x00, 0x00, 0x00 ); +inline constexpr ::Color COL_BLUE ( 0x00, 0x00, 0x80 ); +inline constexpr ::Color COL_GREEN ( 0x00, 0x80, 0x00 ); +inline constexpr ::Color COL_CYAN ( 0x00, 0x80, 0x80 ); +inline constexpr ::Color COL_RED ( 0x80, 0x00, 0x00 ); +inline constexpr ::Color COL_MAGENTA ( 0x80, 0x00, 0x80 ); +inline constexpr ::Color COL_BROWN ( 0x80, 0x80, 0x00 ); +inline constexpr ::Color COL_GRAY ( 0x80, 0x80, 0x80 ); +inline constexpr ::Color COL_GRAY3 ( 0xCC, 0xCC, 0xCC ); +inline constexpr ::Color COL_GRAY7 ( 0x66, 0x66, 0x66 ); +inline constexpr ::Color COL_LIGHTGRAY ( 0xC0, 0xC0, 0xC0 ); +inline constexpr ::Color COL_LIGHTBLUE ( 0x00, 0x00, 0xFF ); +inline constexpr ::Color COL_LIGHTGREEN ( 0x00, 0xFF, 0x00 ); +inline constexpr ::Color COL_LIGHTCYAN ( 0x00, 0xFF, 0xFF ); +inline constexpr ::Color COL_LIGHTRED ( 0xFF, 0x00, 0x00 ); +inline constexpr ::Color COL_LIGHTMAGENTA ( 0xFF, 0x00, 0xFF ); +inline constexpr ::Color COL_LIGHTGRAYBLUE ( 0xE0, 0xE0, 0xFF ); +inline constexpr ::Color COL_YELLOW ( 0xFF, 0xFF, 0x00 ); +inline constexpr ::Color COL_WHITE ( 0xFF, 0xFF, 0xFF ); +inline constexpr ::Color COL_AUTHOR1_DARK ( 0xC6, 0x92, 0x00 ); +inline constexpr ::Color COL_AUTHOR1_NORMAL ( 0xFF, 0xFF, 0x9E ); +inline constexpr ::Color COL_AUTHOR1_LIGHT ( 0xFF, 0xFF, 0xC3 ); +inline constexpr ::Color COL_AUTHOR2_DARK ( 0x06, 0x46, 0xA2 ); +inline constexpr ::Color COL_AUTHOR2_NORMAL ( 0xD8, 0xE8, 0xFF ); +inline constexpr ::Color COL_AUTHOR2_LIGHT ( 0xE9, 0xF2, 0xFF ); +inline constexpr ::Color COL_AUTHOR3_DARK ( 0x57, 0x9D, 0x1C ); +inline constexpr ::Color COL_AUTHOR3_NORMAL ( 0xDA, 0xF8, 0xC1 ); +inline constexpr ::Color COL_AUTHOR3_LIGHT ( 0xE2, 0xFA, 0xCF ); +inline constexpr ::Color COL_AUTHOR4_DARK ( 0x69, 0x2B, 0x9D ); +inline constexpr ::Color COL_AUTHOR4_NORMAL ( 0xE4, 0xD2, 0xF5 ); +inline constexpr ::Color COL_AUTHOR4_LIGHT ( 0xEF, 0xE4, 0xF8 ); +inline constexpr ::Color COL_AUTHOR5_DARK ( 0xC5, 0x00, 0x0B ); +inline constexpr ::Color COL_AUTHOR5_NORMAL ( 0xFE, 0xCD, 0xD0 ); +inline constexpr ::Color COL_AUTHOR5_LIGHT ( 0xFF, 0xE3, 0xE5 ); +inline constexpr ::Color COL_AUTHOR6_DARK ( 0x00, 0x80, 0x80 ); +inline constexpr ::Color COL_AUTHOR6_NORMAL ( 0xD2, 0xF6, 0xF6 ); +inline constexpr ::Color COL_AUTHOR6_LIGHT ( 0xE6, 0xFA, 0xFA ); +inline constexpr ::Color COL_AUTHOR7_DARK ( 0x8C, 0x84, 0x00 ); +inline constexpr ::Color COL_AUTHOR7_NORMAL ( 0xED, 0xFC, 0xA3 ); +inline constexpr ::Color COL_AUTHOR7_LIGHT ( 0xF2, 0xFE, 0xB5 ); +inline constexpr ::Color COL_AUTHOR8_DARK ( 0x35, 0x55, 0x6B ); +inline constexpr ::Color COL_AUTHOR8_NORMAL ( 0xD3, 0xDE, 0xE8 ); +inline constexpr ::Color COL_AUTHOR8_LIGHT ( 0xE2, 0xEA, 0xF1 ); +inline constexpr ::Color COL_AUTHOR9_DARK ( 0xD1, 0x76, 0x00 ); +inline constexpr ::Color COL_AUTHOR9_NORMAL ( 0xFF, 0xE2, 0xB9 ); +inline constexpr ::Color COL_AUTHOR9_LIGHT ( 0xFF, 0xE7, 0xC7 ); +inline constexpr ::Color COL_AUTHOR_TABLE_INS ( 0xE1, 0xF2, 0xFA ); +inline constexpr ::Color COL_AUTHOR_TABLE_DEL ( 0xFC, 0xE6, 0xF4 ); + +template<typename charT, typename traits> +inline std::basic_ostream<charT, traits>& operator <<(std::basic_ostream<charT, traits>& rStream, const Color& rColor) +{ + std::ios_base::fmtflags nOrigFlags = rStream.flags(); + rStream << "rgba[" << std::hex << std::setfill ('0') + << std::setw(2) << static_cast<int>(rColor.GetRed()) + << std::setw(2) << static_cast<int>(rColor.GetGreen()) + << std::setw(2) << static_cast<int>(rColor.GetBlue()) + << std::setw(2) << static_cast<int>(rColor.GetAlpha()) << "]"; + rStream.setf(nOrigFlags); + return rStream; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/config.hxx b/include/tools/config.hxx new file mode 100644 index 0000000000..3616d087cf --- /dev/null +++ b/include/tools/config.hxx @@ -0,0 +1,69 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_CONFIG_HXX +#define INCLUDED_TOOLS_CONFIG_HXX + +#include <tools/toolsdllapi.h> +#include <rtl/ustring.hxx> +#include <memory> + +struct ImplConfigData; +struct ImplGroupData; + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Config +{ +private: + OUString maFileName; + OString maGroupName; + std::unique_ptr<ImplConfigData> mpData; + ImplGroupData* mpActGroup; + sal_uInt32 mnDataUpdateId; + + TOOLS_DLLPRIVATE bool ImplUpdateConfig() const; + TOOLS_DLLPRIVATE ImplGroupData* ImplGetGroup() const; + +public: + Config( const OUString& rFileName ); + ~Config(); + + void SetGroup(const OString& rGroup); + const OString& GetGroup() const { return maGroupName; } + void DeleteGroup(std::string_view rGroup); + OString GetGroupName(sal_uInt16 nGroup) const; + sal_uInt16 GetGroupCount() const; + bool HasGroup(std::string_view rGroup) const; + + OString ReadKey(const OString& rKey) const; + OString ReadKey(const OString& rKey, const OString& rDefault) const; + void WriteKey(const OString& rKey, const OString& rValue); + void DeleteKey(std::string_view rKey); + OString GetKeyName(sal_uInt16 nKey) const; + OString ReadKey(sal_uInt16 nKey) const; + sal_uInt16 GetKeyCount() const; + + void Flush(); + +private: + Config( const Config& rConfig ) = delete; + Config& operator = ( const Config& rConfig ) = delete; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/contnr.hxx b/include/tools/contnr.hxx new file mode 100644 index 0000000000..090be0dbee --- /dev/null +++ b/include/tools/contnr.hxx @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_CONTNR_HXX +#define INCLUDED_TOOLS_CONTNR_HXX + +#include <sal/types.h> + +#define TREELIST_APPEND (SAL_MAX_UINT32) +#define TREELIST_ENTRY_NOTFOUND (SAL_MAX_UINT32) + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/cpuid.hxx b/include/tools/cpuid.hxx new file mode 100644 index 0000000000..4f309ff11e --- /dev/null +++ b/include/tools/cpuid.hxx @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#pragma once + +#include <sal/config.h> +#include <tools/toolsdllapi.h> +#include <o3tl/typed_flags_set.hxx> +#include <rtl/ustring.hxx> + +/* + +Do NOT include this header in source files compiled with CPU-specific code. +TODO: For the header to be safe that way, it should be free of any templates +or inline functions, otherwise their possibly emitted copies compiled +with the CPU-specific instructions might be chosen by the linker as the copy +to keep. + +Also see the note at the top of simdsupport.hxx . + +*/ + +namespace cpuid { + +enum class InstructionSetFlags +{ + NONE = 0x00, + HYPER = 0x01, + SSE2 = 0x02, + SSSE3 = 0x04, + SSE41 = 0x08, + SSE42 = 0x10, + AVX = 0x20, + AVX2 = 0x40, + AVX512F = 0x80 +}; + +} // end cpuid + +namespace o3tl { + template<> struct typed_flags<cpuid::InstructionSetFlags> : is_typed_flags<cpuid::InstructionSetFlags, 0x0ff> {}; +} + +namespace cpuid { + +/** Get supported instruction set flags determined at runtime by probing the CPU. + */ +TOOLS_DLLPUBLIC InstructionSetFlags getCpuInstructionSetFlags(); + +/** Check if a certain instruction set is supported by the CPU at runtime. + */ +TOOLS_DLLPUBLIC bool isCpuInstructionSetSupported(InstructionSetFlags eInstructions); + +/** Returns a string of supported instructions. + */ +TOOLS_DLLPUBLIC OUString instructionSetSupportedString(); + +/** Check if SSE2 is supported by the CPU + */ +inline bool hasSSE2() +{ + return isCpuInstructionSetSupported(InstructionSetFlags::SSE2); +} + +/** Check if SSSE3 is supported by the CPU + */ +inline bool hasSSSE3() +{ + return isCpuInstructionSetSupported(InstructionSetFlags::SSSE3); +} + +/** Check if AVX is supported by the CPU + */ +inline bool hasAVX() +{ + return isCpuInstructionSetSupported(InstructionSetFlags::AVX); +} + +/** Check if AVX2 is supported by the CPU + */ +inline bool hasAVX2() +{ + return isCpuInstructionSetSupported(InstructionSetFlags::AVX2); +} + +/** Check if AVX512F is supported by the CPU + */ +inline bool hasAVX512F() +{ + return isCpuInstructionSetSupported(InstructionSetFlags::AVX512F); +} + +/** Check if Hyper Threading is supported + */ +inline bool hasHyperThreading() +{ + return isCpuInstructionSetSupported(InstructionSetFlags::HYPER); +} + +} // end cpuid + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/date.hxx b/include/tools/date.hxx new file mode 100644 index 0000000000..6179d637e8 --- /dev/null +++ b/include/tools/date.hxx @@ -0,0 +1,259 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_DATE_HXX +#define INCLUDED_TOOLS_DATE_HXX + +#include <tools/toolsdllapi.h> + +#include <ostream> + +#include <com/sun/star/util/Date.hpp> + +namespace com::sun::star::util { struct DateTime; } + +enum DayOfWeek { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, + SATURDAY, SUNDAY }; + +/** Represents a date in the proleptic Gregorian calendar. + + Largest representable date is 32767-12-31 = 327671231 + + Smallest representable date is -32768-01-01 = -327680101 + + Due to possible conversions to css::util::Date, which has a short + Year member variable, these limits are fix. + + Year value 0 is unused. The year before year 1 CE is year 1 BCE, which is + the traditional proleptic Gregorian calendar. + + This is not how ISO 8601:2000 defines things (but ISO 8601:1998 Draft + Revision did), but it enables class Date to be used for writing XML files + as XML Schema Part 2 in D.3.2 No Year Zero says + "The year "0000" is an illegal year value.", see + https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#noYearZero + and furthermore the note for 3.2.7 dateTime + https://www.w3.org/TR/2004/REC-xmlschema-2-20041028/#dateTime + + */ +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Date +{ +private: + sal_Int32 mnDate; + void setDateFromDMY( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ); + +public: + enum DateInitSystem + { + SYSTEM + }; + + enum DateInitEmpty + { + EMPTY + }; + + explicit Date( DateInitEmpty ) : mnDate(0) {} + explicit Date( DateInitSystem ); + explicit Date( sal_Int32 nDate ) : mnDate(nDate) {} + Date( const Date& rDate ) : mnDate(rDate.mnDate) {} + + /** nDay and nMonth both must be <100, nYear must be != 0 */ + Date( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ) + { setDateFromDMY(nDay, nMonth, nYear); } + + Date( const css::util::Date& rUDate ) + { + setDateFromDMY(rUDate.Day, rUDate.Month, rUDate.Year); + } + Date( const css::util::DateTime& _rDateTime ); + + bool IsEmpty() const { return mnDate == 0; } + + void SetDate( sal_Int32 nNewDate ); + sal_Int32 GetDate() const { return mnDate; } + /** Type safe access for values that are guaranteed to be unsigned, like Date::SYSTEM. */ + sal_uInt32 GetDateUnsigned() const { return static_cast<sal_uInt32>(mnDate < 0 ? -mnDate : mnDate); } + css::util::Date GetUNODate() const { return css::util::Date(GetDay(), GetMonth(), GetYear()); } + + /** nNewDay must be <100 */ + void SetDay( sal_uInt16 nNewDay ); + /** nNewMonth must be <100 */ + void SetMonth( sal_uInt16 nNewMonth ); + /** nNewYear must be != 0 */ + void SetYear( sal_Int16 nNewYear ); + + sal_uInt16 GetDay() const + { + return mnDate < 0 ? + static_cast<sal_uInt16>(-mnDate % 100) : + static_cast<sal_uInt16>( mnDate % 100); + } + sal_uInt16 GetMonth() const + { + return mnDate < 0 ? + static_cast<sal_uInt16>((-mnDate / 100) % 100) : + static_cast<sal_uInt16>(( mnDate / 100) % 100); + } + sal_Int16 GetYear() const { return static_cast<sal_Int16>(mnDate / 10000); } + /** Type safe access for values that are guaranteed to be unsigned, like Date::SYSTEM. */ + sal_uInt16 GetYearUnsigned() const { return static_cast<sal_uInt16>((mnDate < 0 ? -mnDate : mnDate) / 10000); } + sal_Int16 GetNextYear() const { sal_Int16 nY = GetYear(); return nY == -1 ? 1 : nY + 1; } + sal_Int16 GetPrevYear() const { sal_Int16 nY = GetYear(); return nY == 1 ? -1 : nY - 1; } + + /** Add years skipping year 0 and truncating at limits. If the original + date was on Feb-29 and the resulting date is not a leap year, the + result is adjusted to Feb-28. + */ + void AddYears( sal_Int16 nAddYears ); + + /** Add months skipping year 0 and truncating at limits. If the original + date was on Feb-29 or day 31 and the resulting date is not a leap year + or a month with fewer days, the result is adjusted to Feb-28 or day 30. + */ + void AddMonths( sal_Int32 nAddMonths ); + + /** Add days skipping year 0 and truncating at limits. + */ + void AddDays( sal_Int32 nAddDays ); + + /** Obtain the day of the week for the date. + + Internally normalizes a copy of values. + The result may be unexpected for a non-normalized invalid date like + Date(31,11,2000) or a sequence of aDate.SetDay(31); aDate.SetMonth(11); + */ + DayOfWeek GetDayOfWeek() const; + + /** Obtain the day of the year for the date. + + Internally normalizes a copy of values. + The result may be unexpected for a non-normalized invalid date like + Date(31,11,2000) or a sequence of aDate.SetDay(31); aDate.SetMonth(11); + */ + sal_uInt16 GetDayOfYear() const; + + /** Obtain the week of the year for a date. + + @param nMinimumNumberOfDaysInWeek + How many days of a week must reside in the first week of a year. + + Internally normalizes a copy of values. + The result may be unexpected for a non-normalized invalid date like + Date(31,11,2000) or a sequence of aDate.SetDay(31); aDate.SetMonth(11); + */ + sal_uInt16 GetWeekOfYear( DayOfWeek eStartDay = MONDAY, + sal_Int16 nMinimumNumberOfDaysInWeek = 4 ) const; + + /** Obtain the number of days in the month of the year of the date. + + Internally normalizes a copy of values. + + The result may be unexpected for a non-normalized invalid date like + Date(31,11,2000) or a sequence of aDate.SetDay(31); aDate.SetMonth(11); + + These would result in 31 as --11-31 rolls over to --12-01 and the + number of days in December is returned. + + Instead, to obtain the value for the actual set use the static method + Date::GetDaysInMonth( aDate.GetMonth(), aDate.GetYear()) in such cases. + */ + sal_uInt16 GetDaysInMonth() const; + + sal_uInt16 GetDaysInYear() const { return (IsLeapYear()) ? 366 : 365; } + bool IsLeapYear() const; + + /** If the represented date is valid (1<=month<=12, 1<=day<=(28,29,30,31) + depending on month/year) AND is of the Gregorian calendar (1582-10-15 + <= date) + */ + bool IsValidAndGregorian() const; + + /** If the represented date is valid (1<=month<=12, 1<=day<=(28,29,30,31) + depending on month/year) */ + bool IsValidDate() const; + + // Returns true, if the date is the end of the month, false otherwise. + bool IsEndOfMonth() const; + + /** Normalize date, invalid day or month values are adapted such that they + carry over to the next month or/and year, for example 1999-02-32 + becomes 1999-03-04, 1999-13-01 becomes 2000-01-01, 1999-13-42 becomes + 2000-02-11. Truncates at -32768-01-01 or 32767-12-31, 0001-00-x will + yield the normalized value of -0001-12-x + + This may be necessary after Date ctors or if the SetDate(), SetDay(), + SetMonth(), SetYear() methods set individual non-matching values. + Adding/subtracting to/from dates never produces invalid dates. + */ + void Normalize(); + + bool IsBetween( const Date& rFrom, const Date& rTo ) const + { return ((mnDate >= rFrom.mnDate) && + (mnDate <= rTo.mnDate)); } + + bool operator ==( const Date& rDate ) const + { return (mnDate == rDate.mnDate); } + bool operator !=( const Date& rDate ) const + { return (mnDate != rDate.mnDate); } + bool operator >( const Date& rDate ) const + { return (mnDate > rDate.mnDate); } + bool operator <( const Date& rDate ) const + { return (mnDate < rDate.mnDate); } + bool operator >=( const Date& rDate ) const + { return (mnDate >= rDate.mnDate); } + bool operator <=( const Date& rDate ) const + { return (mnDate <= rDate.mnDate); } + + Date& operator =( const Date& rDate ) + { mnDate = rDate.mnDate; return *this; } + Date& operator =( const css::util::Date& rUDate ) + { setDateFromDMY( rUDate.Day, rUDate.Month, rUDate.Year); return *this; } + Date& operator ++(); + Date& operator --(); + + TOOLS_DLLPUBLIC friend Date operator +( const Date& rDate, sal_Int32 nDays ); + TOOLS_DLLPUBLIC friend Date operator -( const Date& rDate, sal_Int32 nDays ); + TOOLS_DLLPUBLIC friend sal_Int32 operator -( const Date& rDate1, const Date& rDate2 ); + + /** Obtain number of days in a month of a year. + + Internally sanitizes nMonth to values 1 <= nMonth <= 12, does not + normalize values. + */ + static sal_uInt16 GetDaysInMonth( sal_uInt16 nMonth, sal_Int16 nYear ); + + /// Internally normalizes values. + static sal_Int32 DateToDays( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ); + /// Semantically identical to IsValidDate() member method. + static bool IsValidDate( sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear ); + /// Semantically identical to IsEndOfMonth() member method. + static bool IsEndOfMonth(sal_uInt16 nDay, sal_uInt16 nMonth, sal_Int16 nYear); + /// Semantically identical to Normalize() member method. + static bool Normalize( sal_uInt16 & rDay, sal_uInt16 & rMonth, sal_Int16 & rYear ); + + private: + /// An accelerated form of DateToDays on this date + sal_Int32 GetAsNormalizedDays() const; +}; + +TOOLS_DLLPUBLIC std::ostream& operator<<(std::ostream& os, const Date& rDate); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/datetime.hxx b/include/tools/datetime.hxx new file mode 100644 index 0000000000..ddf29896c1 --- /dev/null +++ b/include/tools/datetime.hxx @@ -0,0 +1,151 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_DATETIME_HXX +#define INCLUDED_TOOLS_DATETIME_HXX + +#include <tools/toolsdllapi.h> +#include <tools/date.hxx> +#include <tools/time.hxx> +#include <com/sun/star/util/DateTime.hpp> + +#include <iomanip> + +namespace tools +{ +class Duration; +} + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC DateTime : public Date, public tools::Time +{ +public: + enum DateTimeInitSystem + { + SYSTEM + }; + + enum DateTimeInitEmpty + { + EMPTY + }; + + explicit DateTime( DateTimeInitEmpty ) : Date( Date::EMPTY ), Time( Time::EMPTY ) {} + explicit DateTime( DateTimeInitSystem ); + DateTime( const DateTime& rDateTime ) : + Date( rDateTime ), Time( rDateTime ) {} + DateTime( const Date& rDate ) : Date( rDate ), Time(0) {} + DateTime( const tools::Time& rTime ) : Date(0), Time( rTime ) {} + DateTime( const Date& rDate, const tools::Time& rTime ) : + Date( rDate ), Time( rTime ) {} + DateTime( const css::util::DateTime& rDateTime ); + + css::util::DateTime + GetUNODateTime() const + { return css::util::DateTime(GetNanoSec(), GetSec(), GetMin(), GetHour(), + GetDay(), GetMonth(), GetYear(), false); } + + bool IsBetween( const DateTime& rFrom, + const DateTime& rTo ) const; + + bool IsEqualIgnoreNanoSec( const DateTime& rDateTime ) const + { + if ( Date::operator!=( rDateTime ) ) + return false; + return Time::IsEqualIgnoreNanoSec( rDateTime ); + } + + bool operator ==( const DateTime& rDateTime ) const + { return (Date::operator==( rDateTime ) && + Time::operator==( rDateTime )); } + bool operator !=( const DateTime& rDateTime ) const + { return (Date::operator!=( rDateTime ) || + Time::operator!=( rDateTime )); } + bool operator >( const DateTime& rDateTime ) const; + bool operator <( const DateTime& rDateTime ) const; + bool operator >=( const DateTime& rDateTime ) const; + bool operator <=( const DateTime& rDateTime ) const; + + sal_Int64 GetSecFromDateTime( const Date& rDate ) const; + + void ConvertToUTC() { *this -= Time::GetUTCOffset(); } + void ConvertToLocalTime() { *this += Time::GetUTCOffset(); } + + void AddTime( double fTimeInDays ); + DateTime& operator +=( const tools::Time& rTime ); + DateTime& operator -=( const tools::Time& rTime ); + /** Duration can be negative, so adding it will subtract its value. */ + DateTime& operator +=( const tools::Duration& rDuration ); +private: + void NormalizeTimeRemainderAndApply( tools::Time& rTime ); +public: + + TOOLS_DLLPUBLIC friend DateTime operator +( const DateTime& rDateTime, sal_Int32 nDays ); + TOOLS_DLLPUBLIC friend DateTime operator -( const DateTime& rDateTime, sal_Int32 nDays ); + TOOLS_DLLPUBLIC friend DateTime operator +( const DateTime& rDateTime, double fTimeInDays ); + TOOLS_DLLPUBLIC friend DateTime operator -( const DateTime& rDateTime, double fTimeInDays ) + { return operator+( rDateTime, -fTimeInDays ); } + TOOLS_DLLPUBLIC friend DateTime operator +( const DateTime& rDateTime, const tools::Time& rTime ); + TOOLS_DLLPUBLIC friend DateTime operator -( const DateTime& rDateTime, const tools::Time& rTime ); + /** Use operator-() if a duration is to be remembered or processed. */ + TOOLS_DLLPUBLIC friend tools::Duration operator -( const DateTime& rDateTime1, const DateTime& rDateTime2 ); + /** Use Sub() if the floating point "time in days" value is to be + processed. This also takes a shortcut for whole days values (equal + times), and only for times inflicted values uses an intermediary + tools::Duration for conversion. Note that the resulting floating point + value nevertheless in many cases is not an exact representation down to + nanoseconds. */ + static double Sub( const DateTime& rDateTime1, const DateTime& rDateTime2 ); + TOOLS_DLLPUBLIC friend sal_Int64 operator -( const DateTime& rDateTime, const Date& rDate ) + { return static_cast<const Date&>(rDateTime) - rDate; } + /** Duration can be negative, so adding it will subtract its value. */ + TOOLS_DLLPUBLIC friend DateTime operator +( const DateTime& rDateTime, const tools::Duration& rDuration ); + + DateTime& operator =( const DateTime& rDateTime ); + DateTime& operator =( const css::util::DateTime& rUDateTime ); + + void GetWin32FileDateTime( sal_uInt32 & rLower, sal_uInt32 & rUpper ) const; + static DateTime CreateFromWin32FileDateTime( sal_uInt32 rLower, sal_uInt32 rUpper ); + + /// Creates DateTime given a unix time, which is the number of seconds + /// elapsed since Jan 1st, 1970. + static DateTime CreateFromUnixTime( const double fSecondsSinceEpoch ); +}; + +inline DateTime& DateTime::operator =( const DateTime& rDateTime ) +{ + Date::operator=( rDateTime ); + Time::operator=( rDateTime ); + return *this; +} + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const DateTime& datetime) +{ + return stream << datetime.GetYear() << '-' << + std::setw(2) << std::setfill('0') << datetime.GetMonth() << '-' << + std::setw(2) << std::setfill('0') << datetime.GetDay() << ' ' << + std::setw(2) << std::setfill('0') << datetime.GetHour() << ':' << + std::setw(2) << std::setfill('0') << datetime.GetMin() << ':' << + std::setw(2) << std::setfill('0') << datetime.GetSec() << "." << + std::setw(9) << std::setfill('0') << datetime.GetNanoSec(); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/datetimeutils.hxx b/include/tools/datetimeutils.hxx new file mode 100644 index 0000000000..3df6229cb5 --- /dev/null +++ b/include/tools/datetimeutils.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_TOOLS_DATETIMEUTILS_HXX +#define INCLUDED_TOOLS_DATETIMEUTILS_HXX + +#include <tools/datetime.hxx> + +// This function converts a 'DateTime' object to an 'OString' object +TOOLS_DLLPUBLIC OString DateTimeToOString(const DateTime& rDateTime); + +// This function converts a 'Date' object to an 'OString' object in ISO-8601 representation +TOOLS_DLLPUBLIC OString DateToOString(const Date& rDate); + +// This function converts a 'Date' object to an 'OString' object in DD/MM/YYYY format +TOOLS_DLLPUBLIC OString DateToDDMMYYYYOString(const Date& rDate); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/debug.hxx b/include/tools/debug.hxx new file mode 100644 index 0000000000..c72da4d068 --- /dev/null +++ b/include/tools/debug.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_DEBUG_HXX +#define INCLUDED_TOOLS_DEBUG_HXX + +#include <tools/toolsdllapi.h> + +#include <sal/detail/log.h> + +/** The facilities provided by this header are deprecated. True assertions + (that detect broken program logic) should use standard assert (which aborts + if an assertion fails, and is controlled by the standard NDEBUG macro). + Logging of warnings (e.g., about malformed input) should use the facilities + provided by sal/log.hxx. + + Because the assertion macro (DBG_ASSERT) has been used for + true assertions as well as to log warnings, it maps to SAL_WARN instead of + standard assert. +*/ + +typedef void (*DbgTestSolarMutexProc)(); + +TOOLS_DLLPUBLIC void DbgSetTestSolarMutex( DbgTestSolarMutexProc pParam ); +TOOLS_DLLPUBLIC void DbgTestSolarMutex(); + +#ifndef NDEBUG +// we want the solar mutex checking to be enabled in the assert-enabled builds that the QA people use + +#define DBG_TESTSOLARMUTEX() \ +do \ +{ \ + DbgTestSolarMutex(); \ +} while(false) + +#else + +#define DBG_TESTSOLARMUTEX() ((void)0) + +#endif + +#define DBG_ASSERT( sCon, aError ) \ + SAL_DETAIL_WARN_IF_FORMAT(!(sCon), "legacy.tools", "%s", aError) + + +#endif // INCLUDED_TOOLS_DEBUG_HXX +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/degree.hxx b/include/tools/degree.hxx new file mode 100644 index 0000000000..560f9b115f --- /dev/null +++ b/include/tools/degree.hxx @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include <sal/config.h> + +#include <basegfx/numeric/ftools.hxx> +#include <sal/types.h> +#include <o3tl/strong_int.hxx> +#include <o3tl/unit_conversion.hxx> +#include <cstdlib> +#include <math.h> +#include <numeric> + +template <int N> struct FractionTag; +// 1/Nth fraction of a degree +template <typename I, int N> using Degree = o3tl::strong_int<I, FractionTag<N>>; + +template <typename I, int N> char (&NofDegree(Degree<I, N>))[N]; // helper +// Nof<DegreeN> gives compile-time constant N, needed in templates +template <class D> constexpr int Nof = sizeof(NofDegree(std::declval<D>())); + +/** tenths of a Degree, normally rotation */ +typedef Degree<sal_Int16, 10> Degree10; + +/** custom literal */ +constexpr Degree10 operator""_deg10(unsigned long long n) { return Degree10{ n }; } + +/** hundredths of a Degree, normally rotation */ +typedef Degree<sal_Int32, 100> Degree100; + +// Android has trouble calling the correct overload of std::abs +#ifdef ANDROID +inline Degree100 abs(Degree100 x) { return Degree100(std::abs(static_cast<int>(x.get()))); } +#else +inline Degree100 abs(Degree100 x) { return Degree100(std::abs(x.get())); } +#endif + +/** custom literal */ +constexpr Degree100 operator""_deg100(unsigned long long n) { return Degree100{ n }; } + +/** conversion functions */ + +template <class To, typename IofFrom, int NofFrom> inline To to(Degree<IofFrom, NofFrom> x) +{ + constexpr sal_Int64 m = Nof<To> / std::gcd(Nof<To>, NofFrom); + constexpr sal_Int64 d = NofFrom / std::gcd(Nof<To>, NofFrom); + return To{ o3tl::convert(x.get(), m, d) }; +} + +template <class D> inline double toRadians(D x) { return basegfx::deg2rad<Nof<D>>(x.get()); } +template <class D> inline double toDegrees(D x) { return x.get() / static_cast<double>(Nof<D>); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/tools/duration.hxx b/include/tools/duration.hxx new file mode 100644 index 0000000000..9f032539e1 --- /dev/null +++ b/include/tools/duration.hxx @@ -0,0 +1,104 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <tools/time.hxx> + +class DateTime; + +namespace tools +{ +/** Duration in days and time. Can be negative in which case days is 0 and time + is negative or both days and time are negative. +*/ +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Duration +{ +public: + Duration() {} + + /** Assumes that DateTime are normalized and there are no Time out-of-range + field values. */ + Duration(const ::DateTime& rStart, const ::DateTime& rEnd); + + /** Time can be a limited duration as well. We don't cater for out-of-range + minutes and seconds values here though. */ + Duration(const Time& rStart, const Time& rEnd); + + constexpr static sal_uInt64 kAccuracyEpsilonNanoseconds = 300; + constexpr static sal_uInt64 kAccuracyEpsilonNanosecondsMicroseconds = 999; + + /** Difference in days, like DateTime()-DateTime(). + + Can also be used to round a date+time value to, for example, microseconds. + + @param nAccuracyEpsilonNanoseconds + Round for example by 1 nanosecond if it's just 1 off to a + second, i.e. 0999999999 or 0000000001. This can be loosened if + necessary. For example, if fTimeInDays is a date+time in + "today's" range with a significant seconds resolution, an + accuracy epsilon (=unsharpness) of ~300 is required. Hence default. + Must be 0 <= nAccuracyEpsilonNanoseconds <= Time::nanoSecPerSec - 1. + */ + explicit Duration(double fTimeInDays, + sal_uInt64 nAccuracyEpsilonNanoseconds = kAccuracyEpsilonNanoseconds); + + /** Time can be a limited duration as well and can have out-of-range + values, it will be normalized. Sign of both days and Time must be equal + unless one is 0. */ + Duration(sal_Int32 nDays, const Time& rTime); + + /** Individual time values can be out-of-range, all will be normalized. + Additionally, the resulting time overall hour value is not restricted + to sal_uInt16 like it is with Time, as values >=24 flow over into days. + For a negative duration only a negative nDays can be given, thus a + negative duration of less than one day is not possible. */ + Duration(sal_Int32 nDays, sal_uInt32 nHours, sal_uInt32 nMinutes, sal_uInt32 nSeconds, + sal_uInt64 nNanoseconds); + + bool IsNegative() const { return mnDays < 0 || maTime.GetTime() < 0; } + sal_Int32 GetDays() const { return mnDays; } + const Time& GetTime() const { return maTime; } + double GetInDays() const { return static_cast<double>(GetDays()) + GetTime().GetTimeInDays(); } + + /** Whether a duration is set. */ + operator bool() const { return maTime.GetTime() != 0 || mnDays != 0; } + + /** Unary minus. */ + Duration operator-() const; + + /** Add a duration to this instance. */ + Duration& Add(const Duration& rDuration, bool& rbOverflow); + + /** Get multiple of duration. */ + Duration Mult(sal_Int32 nMult, bool& rbOverflow) const; + +private: + /** Internal days and Time values. */ + Duration(sal_Int32 nDays, sal_Int64 nTime); + + /** Prerequisite: mnDays is already set. */ + void Normalize(sal_uInt64 nHours, sal_uInt64 nMinutes, sal_uInt64 nSeconds, + sal_uInt64 nNanoseconds, bool bNegative); + + /** Prerequisite: mnDays is already correctly set and absolute value of + nanoseconds less than one day. */ + void ApplyTime(sal_Int64 nNS); + + /** Prerequisite: mnDays is already correctly set and Time hour values + are adjusted. */ + void SetTimeDiff(const Time& rStart, const Time& rEnd); + +private: + Time maTime = Time(0); + sal_Int32 mnDays = 0; +}; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/tools/extendapplicationenvironment.hxx b/include/tools/extendapplicationenvironment.hxx new file mode 100644 index 0000000000..0ca8ceca42 --- /dev/null +++ b/include/tools/extendapplicationenvironment.hxx @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_EXTENDAPPLICATIONENVIRONMENT_HXX +#define INCLUDED_TOOLS_EXTENDAPPLICATIONENVIRONMENT_HXX + +#include <sal/config.h> +#include <tools/toolsdllapi.h> + +namespace tools +{ +// Extend the environment of the process in a platform specific way as necessary +// for OOo-related applications; must be called first thing in main: +TOOLS_DLLPUBLIC void extendApplicationEnvironment(); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/fileutil.hxx b/include/tools/fileutil.hxx new file mode 100644 index 0000000000..d2ed87a6df --- /dev/null +++ b/include/tools/fileutil.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_TOOLS_FILEUTIL_HXX +#define INCLUDED_TOOLS_FILEUTIL_HXX + +#include <tools/toolsdllapi.h> +#include <rtl/ustring.hxx> + +namespace tools +{ +// Tests if the path is a UNC or local (drive-based) path that redirects to +// a WebDAV resource (e.g., using redirectors on Windows). +// Currently only implemented for Windows; on other platforms, returns false. +TOOLS_DLLPUBLIC bool IsMappedWebDAVPath(const OUString& rURL, OUString* pRealURL = nullptr); +} + +#endif // INCLUDED_TOOLS_FILEUTIL_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/fix16.hxx b/include/tools/fix16.hxx new file mode 100644 index 0000000000..99de89b28e --- /dev/null +++ b/include/tools/fix16.hxx @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * libfixmath is Copyright (c) 2011-2021 Flatmush <Flatmush@gmail.com>, + * Petteri Aimonen <Petteri.Aimonen@gmail.com>, & libfixmath AUTHORS + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#pragma once + +#include <tools/toolsdllapi.h> +#include <stdint.h> + +typedef int32_t fix16_t; + +/*! Multiplies the two given fix16_t's and returns the result. +*/ +TOOLS_DLLPUBLIC fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1); + +/*! Divides the first given fix16_t by the second and returns the result. +*/ +TOOLS_DLLPUBLIC fix16_t fix16_div(fix16_t inArg0, fix16_t inArg1); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/tools/fldunit.hxx b/include/tools/fldunit.hxx new file mode 100644 index 0000000000..a2838c32ff --- /dev/null +++ b/include/tools/fldunit.hxx @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_FLDUNIT_HXX +#define INCLUDED_TOOLS_FLDUNIT_HXX + +#include <sal/types.h> + +// Corresponds to offapi/com/sun/star/awt/FieldUnit.idl +enum class FieldUnit : sal_uInt16 +{ + NONE, + MM, + CM, + M, + KM, + TWIP, + POINT, + PICA, + INCH, + FOOT, + MILE, + CUSTOM, + PERCENT, + MM_100TH, + CHAR, + LINE, + PIXEL, + DEGREE, + SECOND, + MILLISECOND, +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/fontenum.hxx b/include/tools/fontenum.hxx new file mode 100644 index 0000000000..5fac8dfdb9 --- /dev/null +++ b/include/tools/fontenum.hxx @@ -0,0 +1,457 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_FONTENUM_HXX +#define INCLUDED_TOOLS_FONTENUM_HXX + +#include <sal/types.h> +#include <sal/log.hxx> +#include <o3tl/typed_flags_set.hxx> + +#include <ostream> + +enum FontFamily { FAMILY_DONTKNOW, FAMILY_DECORATIVE, FAMILY_MODERN, + FAMILY_ROMAN, FAMILY_SCRIPT, FAMILY_SWISS, FAMILY_SYSTEM, FontFamily_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontFamily const& family) +{ + switch (family) + { + case FAMILY_DONTKNOW: + return stream << "unknown"; + + case FAMILY_DECORATIVE: + return stream << "decorative"; + + case FAMILY_MODERN: + return stream << "modern"; + + case FAMILY_ROMAN: + return stream << "roman"; + + case FAMILY_SCRIPT: + return stream << "script"; + + case FAMILY_SWISS: + return stream << "swiss"; + + case FAMILY_SYSTEM: + return stream << "system"; + + default: + SAL_WARN("vcl.gdi", "FontFamily out of bounds"); + assert(false && "FontFamily out of bounds"); + return stream << "unknown"; + } +} + +enum FontPitch { PITCH_DONTKNOW, PITCH_FIXED, PITCH_VARIABLE, FontPitch_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontPitch const& pitch) +{ + switch (pitch) + { + case PITCH_DONTKNOW: + return stream << "unknown"; + + case PITCH_FIXED: + return stream << "fixed"; + + case PITCH_VARIABLE: + return stream << "variable"; + + default: + SAL_WARN("vcl.gdi", "FontPitch out of bounds"); + assert(false && "FontPitch out of bounds"); + return stream << "unknown"; + } +} + +enum TextAlign { ALIGN_TOP, ALIGN_BASELINE, ALIGN_BOTTOM, TextAlign_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, TextAlign const& align) +{ + switch (align) + { + case ALIGN_TOP: + return stream << "top"; + + case ALIGN_BASELINE: + return stream << "baseline"; + + case ALIGN_BOTTOM: + return stream << "bottom"; + + default: + SAL_WARN("vcl.gdi", "TextAlign out of bounds"); + assert(false && "TextAlign out of bounds"); + return stream << "unknown"; + } +} + +enum FontWeight { WEIGHT_DONTKNOW, WEIGHT_THIN, WEIGHT_ULTRALIGHT, + WEIGHT_LIGHT, WEIGHT_SEMILIGHT, WEIGHT_NORMAL, + WEIGHT_MEDIUM, WEIGHT_SEMIBOLD, WEIGHT_BOLD, + WEIGHT_ULTRABOLD, WEIGHT_BLACK, FontWeight_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontWeight const& weight) +{ + switch (weight) + { + case WEIGHT_DONTKNOW: + return stream << "unknown"; + + case WEIGHT_THIN: + return stream << "thin"; + + case WEIGHT_ULTRALIGHT: + return stream << "ultralight"; + + case WEIGHT_LIGHT: + return stream << "light"; + + case WEIGHT_SEMILIGHT: + return stream << "semilight"; + + case WEIGHT_NORMAL: + return stream << "normal"; + + case WEIGHT_MEDIUM: + return stream << "medium"; + + case WEIGHT_SEMIBOLD: + return stream << "semibold"; + + case WEIGHT_BOLD: + return stream << "bold"; + + case WEIGHT_ULTRABOLD: + return stream << "ultrabold"; + + case WEIGHT_BLACK: + return stream << "black"; + + default: + SAL_WARN("vcl.gdi", "FontWeight out of bounds"); + assert(false && "FontWeight out of bounds"); + return stream << "unknown"; + } +} + +enum FontWidth { WIDTH_DONTKNOW, WIDTH_ULTRA_CONDENSED, WIDTH_EXTRA_CONDENSED, + WIDTH_CONDENSED, WIDTH_SEMI_CONDENSED, WIDTH_NORMAL, + WIDTH_SEMI_EXPANDED, WIDTH_EXPANDED, WIDTH_EXTRA_EXPANDED, + WIDTH_ULTRA_EXPANDED, + FontWidth_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontWidth const& width) +{ + switch (width) + { + case WIDTH_DONTKNOW: + return stream << "unknown"; + + case WIDTH_ULTRA_CONDENSED: + return stream << "ultra condensed"; + + case WIDTH_EXTRA_CONDENSED: + return stream << "extra ultra condensed"; + + case WIDTH_CONDENSED: + return stream << "condensed"; + + case WIDTH_SEMI_CONDENSED: + return stream << "semi condensed"; + + case WIDTH_NORMAL: + return stream << "normal"; + + case WIDTH_SEMI_EXPANDED: + return stream << "semi expanded"; + + case WIDTH_EXPANDED: + return stream << "expanded"; + + case WIDTH_EXTRA_EXPANDED: + return stream << "extra expanded"; + + case WIDTH_ULTRA_EXPANDED: + return stream << "ultra expanded"; + + default: + SAL_WARN("vcl.gdi", "FontWidth out of bounds"); + assert(false && "FontWidth out of bounds"); + return stream << "unknown"; + } +} + +enum FontItalic { ITALIC_NONE, ITALIC_OBLIQUE, ITALIC_NORMAL, ITALIC_DONTKNOW, FontItalic_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontItalic const& italic) +{ + switch (italic) + { + case ITALIC_DONTKNOW: + return stream << "unknown"; + + case ITALIC_OBLIQUE: + return stream << "oblique"; + + case ITALIC_NORMAL: + return stream << "normal"; + + case ITALIC_NONE: + return stream << "none"; + + default: + SAL_WARN("vcl.gdi", "FontItalic out of bounds"); + assert(false && "FontItalic out of bounds"); + return stream << "unknown"; + } +} + +enum FontLineStyle { LINESTYLE_NONE, LINESTYLE_SINGLE, LINESTYLE_DOUBLE, + LINESTYLE_DOTTED, LINESTYLE_DONTKNOW, + LINESTYLE_DASH, LINESTYLE_LONGDASH, + LINESTYLE_DASHDOT, LINESTYLE_DASHDOTDOT, + LINESTYLE_SMALLWAVE, + LINESTYLE_WAVE, LINESTYLE_DOUBLEWAVE, + LINESTYLE_BOLD, LINESTYLE_BOLDDOTTED, + LINESTYLE_BOLDDASH, LINESTYLE_BOLDLONGDASH, + LINESTYLE_BOLDDASHDOT, LINESTYLE_BOLDDASHDOTDOT, + LINESTYLE_BOLDWAVE, + FontLineStyle_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontLineStyle const& linestyle) +{ + switch (linestyle) + { + case LINESTYLE_NONE: + return stream << "none"; + + case LINESTYLE_SINGLE: + return stream << "single"; + + case LINESTYLE_DOUBLE: + return stream << "double"; + + case LINESTYLE_DOTTED: + return stream << "dotted"; + + case LINESTYLE_DONTKNOW: + return stream << "unknown"; + + case LINESTYLE_DASH: + return stream << "dash"; + + case LINESTYLE_LONGDASH: + return stream << "long dash"; + + case LINESTYLE_DASHDOT: + return stream << "dash dot"; + + case LINESTYLE_DASHDOTDOT: + return stream << "dash dot dot"; + + case LINESTYLE_SMALLWAVE: + return stream << "small wave"; + + case LINESTYLE_WAVE: + return stream << "wave"; + + case LINESTYLE_DOUBLEWAVE: + return stream << "double wave"; + + case LINESTYLE_BOLD: + return stream << "bold"; + + case LINESTYLE_BOLDDOTTED: + return stream << "bold dotted"; + + case LINESTYLE_BOLDDASH: + return stream << "bold dash"; + + case LINESTYLE_BOLDLONGDASH: + return stream << "bold long dash"; + + case LINESTYLE_BOLDDASHDOT: + return stream << "bold dash dot"; + + case LINESTYLE_BOLDDASHDOTDOT: + return stream << "bold dash dot dot"; + + case LINESTYLE_BOLDWAVE: + return stream << "bold wave"; + + default: + SAL_WARN("vcl.gdi", "FontLineStyle out of bounds"); + assert(false && "FontLineStyle out of bounds"); + return stream << "unknown"; + } +} + +enum FontStrikeout { STRIKEOUT_NONE, STRIKEOUT_SINGLE, STRIKEOUT_DOUBLE, + STRIKEOUT_DONTKNOW, STRIKEOUT_BOLD, + STRIKEOUT_SLASH, STRIKEOUT_X, + FontStrikeout_FORCE_EQUAL_SIZE=SAL_MAX_ENUM }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontStrikeout const& strikeout) +{ + switch (strikeout) + { + case STRIKEOUT_NONE: + return stream << "none"; + + case STRIKEOUT_SINGLE: + return stream << "single"; + + case STRIKEOUT_DOUBLE: + return stream << "double"; + + case STRIKEOUT_DONTKNOW: + return stream << "unknown"; + + case STRIKEOUT_BOLD: + return stream << "bold"; + + case STRIKEOUT_SLASH: + return stream << "slash"; + + case STRIKEOUT_X: + return stream << "x"; + + default: + SAL_WARN("vcl.gdi", "FontStrikeout out of bounds"); + assert(false && "FontStrikeout out of bounds"); + return stream << "unknown"; + } +} + +enum class FontEmphasisMark { + NONE = 0x0000, // capitalisation to avoid conflict with X11 macro + Dot = 0x0001, + Circle = 0x0002, + Disc = 0x0003, + Accent = 0x0004, + Style = 0x000f, + PosAbove = 0x1000, + PosBelow = 0x2000 +}; +namespace o3tl +{ + template<> struct typed_flags<FontEmphasisMark> : is_typed_flags<FontEmphasisMark, 0x300f> {}; +} + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontEmphasisMark const& emphasismark) +{ + switch (emphasismark) + { + case FontEmphasisMark::NONE: + return stream << "none"; + + case FontEmphasisMark::Dot: + return stream << "Dot"; + + case FontEmphasisMark::Circle: + return stream << "Circle"; + + case FontEmphasisMark::Disc: + return stream << "Disc"; + + case FontEmphasisMark::Accent: + return stream << "Accent"; + + case FontEmphasisMark::Style: + return stream << "Style"; + + case FontEmphasisMark::PosAbove: + return stream << "PosAbove"; + + case FontEmphasisMark::PosBelow: + return stream << "PosBelow"; + + default: + SAL_WARN("vcl.gdi", "FontEmphasisMark out of bounds"); + assert(false && "FontEmphasisMark out of bounds"); + return stream << "unknown"; + } +} + +enum FontEmbeddedBitmap { EMBEDDEDBITMAP_DONTKNOW, EMBEDDEDBITMAP_FALSE, EMBEDDEDBITMAP_TRUE }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontEmbeddedBitmap const& embeddedbitmap) +{ + switch (embeddedbitmap) + { + case EMBEDDEDBITMAP_DONTKNOW: + return stream << "unknown"; + + case EMBEDDEDBITMAP_FALSE: + return stream << "false"; + + case EMBEDDEDBITMAP_TRUE: + return stream << "true"; + } + + return stream << "unknown"; +} + +enum FontAntiAlias { ANTIALIAS_DONTKNOW, ANTIALIAS_FALSE, ANTIALIAS_TRUE }; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, FontAntiAlias const& antialias) +{ + switch (antialias) + { + case ANTIALIAS_DONTKNOW: + return stream << "unknown"; + + case ANTIALIAS_FALSE: + return stream << "false"; + + case ANTIALIAS_TRUE: + return stream << "true"; + } + + return stream << "unknown"; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/fract.hxx b/include/tools/fract.hxx new file mode 100644 index 0000000000..e1305ca8a8 --- /dev/null +++ b/include/tools/fract.hxx @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_FRACT_HXX +#define INCLUDED_TOOLS_FRACT_HXX + +#include <sal/types.h> +#include <tools/toolsdllapi.h> +#include <tools/long.hxx> +#include <ostream> +#include <type_traits> + +class SvStream; + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Fraction final +{ + /// these two fields form a boost::rational, but I didn't want to put more boost headers into the global space + sal_Int32 mnNumerator = 0; + sal_Int32 mnDenominator = 1; + bool mbValid = true; +public: + Fraction() = default; + Fraction( const Fraction & rFrac ) = default; + Fraction( Fraction && rFrac ) = default; + explicit Fraction( double dVal ); + Fraction( double nNum, double nDen ); + Fraction( sal_Int64 nNum, sal_Int64 nDen ); + // just to prevent ambiguity between the sal_Int64 and double constructors + template<typename T1, typename T2> Fraction( + T1 nNum, T2 nDen, + typename std::enable_if<std::is_integral<T1>::value && std::is_integral<T2>::value, int>::type = 0) + : Fraction( sal_Int64(nNum), sal_Int64(nDen) ) {} + + bool IsValid() const { return mbValid; } + + sal_Int32 GetNumerator() const; + sal_Int32 GetDenominator() const; + + explicit operator sal_Int32() const; +#if SAL_TYPES_SIZEOFPOINTER == 8 + explicit operator ::tools::Long() const { return operator sal_Int32(); } +#endif + explicit operator double() const; + + Fraction& operator=( const Fraction& rfrFrac ) = default; + Fraction& operator=( Fraction&& rfrFrac ) = default; + Fraction& operator=( double v ) { return operator=(Fraction(v)); } + + Fraction& operator+=( const Fraction& rfrFrac ); + Fraction& operator-=( const Fraction& rfrFrac ); + Fraction& operator*=( const Fraction& rfrFrac ); + Fraction& operator/=( const Fraction& rfrFrac ); + Fraction& operator+=( double v ) { return operator+=(Fraction(v)); } + Fraction& operator-=( double v ) { return operator-=(Fraction(v)); } + Fraction& operator*=( double v ) { return operator*=(Fraction(v)); } + Fraction& operator/=( double v ) { return operator/=(Fraction(v)); } + + void ReduceInaccurate( unsigned nSignificantBits ); + + /// Multiply the two fractions represented here and reduce inaccuracy to 32-bits, used by vcl + static Fraction MakeFraction(tools::Long nN1, tools::Long nN2, tools::Long nD1, tools::Long nD2); + + // Compute value usable as hash. + size_t GetHashValue() const; + + TOOLS_DLLPUBLIC friend Fraction operator+( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend Fraction operator-( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend Fraction operator*( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend Fraction operator/( const Fraction& rVal1, const Fraction& rVal2 ); + + TOOLS_DLLPUBLIC friend bool operator==( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend bool operator!=( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend bool operator< ( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend bool operator> ( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend bool operator<=( const Fraction& rVal1, const Fraction& rVal2 ); + TOOLS_DLLPUBLIC friend bool operator>=( const Fraction& rVal1, const Fraction& rVal2 ); +}; + +TOOLS_DLLPUBLIC Fraction operator+( const Fraction& rVal1, const Fraction& rVal2 ); +TOOLS_DLLPUBLIC Fraction operator-( const Fraction& rVal1, const Fraction& rVal2 ); +TOOLS_DLLPUBLIC Fraction operator*( const Fraction& rVal1, const Fraction& rVal2 ); +TOOLS_DLLPUBLIC Fraction operator/( const Fraction& rVal1, const Fraction& rVal2 ); +TOOLS_DLLPUBLIC bool operator !=( const Fraction& rVal1, const Fraction& rVal2 ); +TOOLS_DLLPUBLIC bool operator <=( const Fraction& rVal1, const Fraction& rVal2 ); +TOOLS_DLLPUBLIC bool operator >=( const Fraction& rVal1, const Fraction& rVal2 ); + +inline Fraction operator+( double v1, const Fraction& rVal2 ) { return Fraction(v1) + rVal2; } +inline Fraction operator-( double v1, const Fraction& rVal2 ) { return Fraction(v1) - rVal2; } +inline Fraction operator*( double v1, const Fraction& rVal2 ) { return Fraction(v1) * rVal2; } +inline Fraction operator/( double v1, const Fraction& rVal2 ) { return Fraction(v1) / rVal2; } + +inline Fraction operator+( const Fraction& rVal1, double v2 ) { return rVal1 + Fraction(v2); } +inline Fraction operator-( const Fraction& rVal1, double v2 ) { return rVal1 - Fraction(v2); } +inline Fraction operator*( const Fraction& rVal1, double v2 ) { return rVal1 * Fraction(v2); } +inline Fraction operator/( const Fraction& rVal1, double v2 ) { return rVal1 / Fraction(v2); } + +template<typename charT, typename traits> +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & rStream, const Fraction& rFraction) +{ + rStream << "(" << rFraction.GetNumerator() << "/" << rFraction.GetDenominator() << ")"; + return rStream; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/gen.hxx b/include/tools/gen.hxx new file mode 100644 index 0000000000..d6ac5f2ec7 --- /dev/null +++ b/include/tools/gen.hxx @@ -0,0 +1,925 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <tools/toolsdllapi.h> + +#include <tools/long.hxx> +#include <tools/degree.hxx> +#include <limits.h> +#include <algorithm> +#include <ostream> +#include <o3tl/unit_conversion.hxx> + +class SvStream; +namespace rtl +{ + class OString; +} + +enum TriState { TRISTATE_FALSE, TRISTATE_TRUE, TRISTATE_INDET }; + +// Pair + +class SAL_WARN_UNUSED Pair +{ +public: + constexpr Pair() : mnA(0), mnB(0) {} + constexpr Pair( tools::Long nA, tools::Long nB ) : mnA(nA), mnB(nB) {} + + tools::Long A() const { return mnA; } + tools::Long B() const { return mnB; } + + tools::Long& A() { return mnA; } + tools::Long& B() { return mnB; } + + TOOLS_DLLPUBLIC rtl::OString toString() const; + + // Compute value usable as hash. + TOOLS_DLLPUBLIC size_t GetHashValue() const; + +protected: + tools::Long mnA; + tools::Long mnB; +}; + +namespace tools::detail { + +// Used to implement operator == for subclasses of Pair: +inline bool equal(Pair const & p1, Pair const & p2) +{ + return p1.A() == p2.A() && p1.B() == p2.B(); +} + +} + +// Point + +class RectangleTemplateBase; + +class TOOLS_DLLPUBLIC PointTemplateBase : protected Pair +{ +friend class RectangleTemplateBase; +public: + PointTemplateBase() = default; +protected: + constexpr PointTemplateBase( tools::Long nX, tools::Long nY ) : Pair( nX, nY ) {} + // Rotate parameter point using This as origin; store result back into parameter point + void RotateAround( tools::Long& rX, tools::Long& rY, Degree10 nOrientation ) const; + void RotateAround( PointTemplateBase&, Degree10 nOrientation ) const; + +public: + constexpr tools::Long X() const { return mnA; } + constexpr tools::Long Y() const { return mnB; } +}; + +template<class PointT, class SizeT> +class PointTemplate : public PointTemplateBase +{ +public: + using SizeType = SizeT; + + constexpr PointTemplate() {} + constexpr PointTemplate( tools::Long nX, tools::Long nY ) : PointTemplateBase( nX, nY ) {} + + void Move( tools::Long nHorzMove, tools::Long nVertMove ) + { + mnA += nHorzMove; + mnB += nVertMove; + } + void Move( SizeT const & s ) + { + AdjustX(s.Width()); + AdjustY(s.Height()); + } + + tools::Long AdjustX( tools::Long nHorzMove ) { mnA += nHorzMove; return mnA; } + tools::Long AdjustY( tools::Long nVertMove ) { mnB += nVertMove; return mnB; } + + void RotateAround( tools::Long& rX, tools::Long& rY, Degree10 nOrientation ) const + { PointTemplateBase::RotateAround(rX, rY, nOrientation); } + void RotateAround( PointT& p, Degree10 nOrientation ) const + { PointTemplateBase::RotateAround(p, nOrientation); } + + PointT& operator+=( const PointT& rPoint ) + { + mnA += rPoint.mnA; + mnB += rPoint.mnB; + return static_cast<PointT&>(*this); + } + PointT& operator-=( const PointT& rPoint ) + { + mnA -= rPoint.mnA; + mnB -= rPoint.mnB; + return static_cast<PointT&>(*this); + } + PointT& operator*=( const tools::Long nVal ) + { + mnA *= nVal; + mnB *= nVal; + return static_cast<PointT&>(*this); + } + PointT& operator/=( const tools::Long nVal ) + { + mnA /= nVal; + mnB /= nVal; + return static_cast<PointT&>(*this); + } + + constexpr tools::Long getX() const { return X(); } + constexpr tools::Long getY() const { return Y(); } + void setX(tools::Long nX) { mnA = nX; } + void setY(tools::Long nY) { mnB = nY; } + + Pair const & toPair() const { return *this; } + Pair & toPair() { return *this; } + + // Scales relative to 0,0 + constexpr PointT scale(sal_Int64 nMulX, sal_Int64 nDivX, + sal_Int64 nMulY, sal_Int64 nDivY) const + { + return PointT(o3tl::convert(getX(), nMulX, nDivX), + o3tl::convert(getY(), nMulY, nDivY)); + } + + using Pair::toString; + using Pair::GetHashValue; +}; + +class Size; +class AbsoluteScreenPixelSize; +class Point; +class AbsoluteScreenPixelPoint; +namespace tools { class Rectangle; } +class AbsoluteScreenPixelRectangle; + +class SAL_WARN_UNUSED Point : public PointTemplate<::Point, ::Size> +{ +public: + constexpr Point() {} + constexpr Point( tools::Long nX, tools::Long nY ) : PointTemplate( nX, nY ) {} + // TODO delete this to expose more problems + constexpr explicit Point(const AbsoluteScreenPixelPoint&); +}; + +// A point relative to top-level parent or screen, in screen pixels +class AbsoluteScreenPixelSize; +class SAL_WARN_UNUSED AbsoluteScreenPixelPoint : public PointTemplate<AbsoluteScreenPixelPoint, AbsoluteScreenPixelSize> { +public: + constexpr AbsoluteScreenPixelPoint() {} + constexpr AbsoluteScreenPixelPoint( tools::Long nX, tools::Long nY ) : PointTemplate( nX, nY ) {} + constexpr explicit AbsoluteScreenPixelPoint(const Point & pt) : PointTemplate(pt.X(), pt.Y()) {} +}; + +inline Point operator+( const Point &rVal1, const Point &rVal2 ) +{ + return Point( rVal1.X()+rVal2.X(), rVal1.Y()+rVal2.Y() ); +} +inline AbsoluteScreenPixelPoint operator+( const AbsoluteScreenPixelPoint &rVal1, const AbsoluteScreenPixelPoint &rVal2 ) +{ + return AbsoluteScreenPixelPoint( rVal1.X()+rVal2.X(), rVal1.Y()+rVal2.Y() ); +} + +inline Point operator-( const Point &rVal1, const Point &rVal2 ) +{ + return Point( rVal1.X()-rVal2.X(), rVal1.Y()-rVal2.Y() ); +} +inline AbsoluteScreenPixelPoint operator-( const AbsoluteScreenPixelPoint &rVal1, const AbsoluteScreenPixelPoint &rVal2 ) +{ + return AbsoluteScreenPixelPoint( rVal1.X()-rVal2.X(), rVal1.Y()-rVal2.Y() ); +} + +inline Point operator*( const Point &rVal1, const tools::Long nVal2 ) +{ + return Point( rVal1.X()*nVal2, rVal1.Y()*nVal2 ); +} +inline AbsoluteScreenPixelPoint operator*( const AbsoluteScreenPixelPoint &rVal1, const tools::Long nVal2 ) +{ + return AbsoluteScreenPixelPoint( rVal1.X()*nVal2, rVal1.Y()*nVal2 ); +} + +inline Point operator/( const Point &rVal1, const tools::Long nVal2 ) +{ + return Point( rVal1.X()/nVal2, rVal1.Y()/nVal2 ); +} +inline AbsoluteScreenPixelPoint operator/( const AbsoluteScreenPixelPoint &rVal1, const tools::Long nVal2 ) +{ + return AbsoluteScreenPixelPoint( rVal1.X()/nVal2, rVal1.Y()/nVal2 ); +} + +inline bool operator ==(Point const & p1, Point const & p2) +{ + return tools::detail::equal(p1.toPair(), p2.toPair()); +} +inline bool operator ==(AbsoluteScreenPixelPoint const & p1, AbsoluteScreenPixelPoint const & p2) +{ + return tools::detail::equal(p1.toPair(), p2.toPair()); +} + +inline bool operator !=(Point const & p1, Point const & p2) +{ + return !(p1 == p2); +} +inline bool operator !=(AbsoluteScreenPixelPoint const & p1, AbsoluteScreenPixelPoint const & p2) +{ + return !(p1 == p2); +} + + +constexpr Point::Point(const AbsoluteScreenPixelPoint& p) : Point(p.X(), p.Y()) {} + +namespace o3tl +{ +template <class PointT, + std::enable_if_t<std::is_base_of_v<PointTemplate<PointT, typename PointT::SizeType>, PointT>, int> = 0> +constexpr auto convert(const PointT& rPoint, o3tl::Length eFrom, o3tl::Length eTo) +{ + const auto [num, den] = o3tl::getConversionMulDiv(eFrom, eTo); + return rPoint.scale(num, den, num, den); +} +} // namespace o3tl + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const PointTemplateBase& point ) +{ + return stream << point.X() << ',' << point.Y(); +} + +// Size + +class SizeTemplateBase : protected Pair +{ +public: + constexpr SizeTemplateBase() = default; + constexpr SizeTemplateBase( tools::Long nWidth, tools::Long nHeight ) : Pair( nWidth, nHeight ) {} + + constexpr tools::Long Width() const { return mnA; } + constexpr tools::Long Height() const { return mnB; } + +}; + +template<class SizeT> +class SizeTemplate : public SizeTemplateBase +{ +public: + constexpr SizeTemplate() {} + constexpr SizeTemplate( tools::Long nWidth, tools::Long nHeight ) : SizeTemplateBase( nWidth, nHeight ) {} + + tools::Long AdjustWidth( tools::Long n ) { mnA += n; return mnA; } + tools::Long AdjustHeight( tools::Long n ) { mnB += n; return mnB; } + + constexpr tools::Long getWidth() const { return Width(); } + constexpr tools::Long getHeight() const { return Height(); } + void setWidth(tools::Long nWidth) { mnA = nWidth; } + void setHeight(tools::Long nHeight) { mnB = nHeight; } + + bool IsEmpty() const { return mnA <= 0 || mnB <= 0; } + + void extendBy(tools::Long x, tools::Long y) + { + mnA += x; + mnB += y; + } + + Pair const & toPair() const { return *this; } + Pair & toPair() { return *this; } + + using Pair::toString; + using Pair::GetHashValue; + + SizeT& operator += ( const SizeT& rSize ) + { + mnA += rSize.mnA; + mnB += rSize.mnB; + return static_cast<SizeT&>(*this); + } + SizeT& operator -= ( const SizeT& rSize ) + { + mnA -= rSize.mnA; + mnB -= rSize.mnB; + return static_cast<SizeT&>(*this); + } + SizeT& operator *= ( const tools::Long nVal ) + { + mnA *= nVal; + mnB *= nVal; + return static_cast<SizeT&>(*this); + } + SizeT& operator /= ( const tools::Long nVal ) + { + mnA /= nVal; + mnB /= nVal; + return static_cast<SizeT&>(*this); + } + + constexpr SizeT scale(sal_Int64 nMulX, sal_Int64 nDivX, + sal_Int64 nMulY, sal_Int64 nDivY) const + { + return SizeT(o3tl::convert(Width(), nMulX, nDivX), + o3tl::convert(Height(), nMulY, nDivY)); + } +}; + +class SAL_WARN_UNUSED Size : public SizeTemplate<::Size> +{ +public: + constexpr Size() {} + constexpr Size( tools::Long nWidth, tools::Long nHeight ) : SizeTemplate( nWidth, nHeight ) {} + // TODO delete to find more problems + constexpr explicit Size(const AbsoluteScreenPixelSize& pt); +}; + +// Screen pixels +class SAL_WARN_UNUSED AbsoluteScreenPixelSize : public SizeTemplate<AbsoluteScreenPixelSize> +{ +public: + constexpr AbsoluteScreenPixelSize() {} + constexpr AbsoluteScreenPixelSize( tools::Long nWidth, tools::Long nHeight ) : SizeTemplate( nWidth, nHeight ) {} + constexpr explicit AbsoluteScreenPixelSize(const Size & pt) : SizeTemplate(pt.Width(), pt.Height()) {} +}; + +constexpr Size::Size(const AbsoluteScreenPixelSize& pt) : SizeTemplate(pt.Width(), pt.Height()) {} + +inline bool operator ==(Size const & s1, Size const & s2) +{ + return tools::detail::equal(s1.toPair(), s2.toPair()); +} +inline bool operator ==(AbsoluteScreenPixelSize const & s1, AbsoluteScreenPixelSize const & s2) +{ + return tools::detail::equal(s1.toPair(), s2.toPair()); +} + +inline bool operator !=(Size const & s1, Size const & s2) +{ + return !(s1 == s2); +} +inline bool operator !=(AbsoluteScreenPixelSize const & s1, AbsoluteScreenPixelSize const & s2) +{ + return !(s1 == s2); +} + +inline Size operator+( const Size &rVal1, const Size &rVal2 ) +{ + return Size( rVal1.Width()+rVal2.Width(), rVal1.Height()+rVal2.Height() ); +} +inline AbsoluteScreenPixelSize operator+( const AbsoluteScreenPixelSize &rVal1, const AbsoluteScreenPixelSize &rVal2 ) +{ + return AbsoluteScreenPixelSize( rVal1.Width()+rVal2.Width(), rVal1.Height()+rVal2.Height() ); +} + +inline Size operator-( const Size &rVal1, const Size &rVal2 ) +{ + return Size( rVal1.Width()-rVal2.Width(), rVal1.Height()-rVal2.Height() ); +} +inline AbsoluteScreenPixelSize operator-( const AbsoluteScreenPixelSize &rVal1, const AbsoluteScreenPixelSize &rVal2 ) +{ + return AbsoluteScreenPixelSize( rVal1.Width()-rVal2.Width(), rVal1.Height()-rVal2.Height() ); +} + +inline Size operator*( const Size &rVal1, const tools::Long nVal2 ) +{ + return Size( rVal1.Width()*nVal2, rVal1.Height()*nVal2 ); +} +inline AbsoluteScreenPixelSize operator*( const AbsoluteScreenPixelSize &rVal1, const tools::Long nVal2 ) +{ + return AbsoluteScreenPixelSize( rVal1.Width()*nVal2, rVal1.Height()*nVal2 ); +} + +inline Size operator/( const Size &rVal1, const tools::Long nVal2 ) +{ + return Size( rVal1.Width()/nVal2, rVal1.Height()/nVal2 ); +} +inline AbsoluteScreenPixelSize operator/( const AbsoluteScreenPixelSize &rVal1, const tools::Long nVal2 ) +{ + return AbsoluteScreenPixelSize( rVal1.Width()/nVal2, rVal1.Height()/nVal2 ); +} + +namespace o3tl +{ + +template <class SizeT, + std::enable_if_t<std::is_base_of_v<SizeTemplate<SizeT>, SizeT>, int> = 0> +constexpr auto convert(const SizeT& rSize, o3tl::Length eFrom, o3tl::Length eTo) +{ + const auto [num, den] = o3tl::getConversionMulDiv(eFrom, eTo); + return rSize.scale(num, den, num, den); +} + +} // end o3tl + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const SizeTemplateBase& size ) +{ + return stream << size.Width() << 'x' << size.Height(); +} + +// Range + +#define RANGE_MAX LONG_MAX + +class SAL_WARN_UNUSED Range final : protected Pair +{ +public: + constexpr Range() {} + constexpr Range( tools::Long nMin, tools::Long nMax ) : Pair( nMin, nMax ) {} + + tools::Long Min() const { return mnA; } + tools::Long Max() const { return mnB; } + tools::Long Len() const { return mnB - mnA + 1; } + + tools::Long& Min() { return mnA; } + tools::Long& Max() { return mnB; } + + bool Contains( tools::Long nIs ) const; + + void Normalize(); + + Pair const & toPair() const { return *this; } + Pair & toPair() { return *this; } + + using Pair::toString; +}; + +inline bool Range::Contains( tools::Long nIs ) const +{ + return ((mnA <= nIs) && (nIs <= mnB )); +} + +inline void Range::Normalize() +{ + if ( mnA > mnB ) + std::swap(mnA, mnB); +} + +inline bool operator ==(Range const & r1, Range const & r2) +{ + return tools::detail::equal(r1.toPair(), r2.toPair()); +} + +inline bool operator !=(Range const & r1, Range const & r2) +{ + return !(r1 == r2); +} + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const Range& range ) +{ + return stream << range.Min() << '-' << range.Max(); +} + +// Selection + +#define SELECTION_MIN LONG_MIN +#define SELECTION_MAX LONG_MAX + +class SAL_WARN_UNUSED Selection final : protected Pair +{ +public: + Selection() {} + Selection( tools::Long nPos ) : Pair( nPos, nPos ) {} + Selection( tools::Long nMin, tools::Long nMax ) : Pair( nMin, nMax ) {} + + tools::Long Min() const { return mnA; } + tools::Long Max() const { return mnB; } + tools::Long Len() const { return mnB - mnA; } + + tools::Long& Min() { return mnA; } + tools::Long& Max() { return mnB; } + + bool Contains( tools::Long nIs ) const; + + void Normalize(); + + bool operator !() const { return !Len(); } + + tools::Long getMin() const { return Min(); } + void setMin(tools::Long nMin) { Min() = nMin; } + void setMax(tools::Long nMax) { Max() = nMax; } + + Pair const & toPair() const { return *this; } + Pair & toPair() { return *this; } + + using Pair::toString; +}; + +inline bool Selection::Contains( tools::Long nIs ) const +{ + return ((mnA <= nIs) && (nIs < mnB )); +} + +inline void Selection::Normalize() +{ + if ( mnA > mnB ) + std::swap(mnA, mnB); +} + +inline bool operator ==(Selection const & s1, Selection const & s2) +{ + return tools::detail::equal(s1.toPair(), s2.toPair()); +} + +inline bool operator !=(Selection const & s1, Selection const & s2) +{ + return !(s1 == s2); +} + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const Selection& selection ) +{ + return stream << selection.Min() << '-' << selection.Max(); +} +// Rectangle + +#define RECT_MAX LONG_MAX +#define RECT_MIN LONG_MIN + +/// Note: this class is a true marvel of engineering: because the author +/// could not decide whether it's better to have a closed or half-open +/// interval, they just implemented *both* in the same class! +/// +/// If you have the misfortune of having to use this class, don't immediately +/// despair but first take note that the uppercase GetWidth() / GetHeight() +/// etc. methods interpret the interval as closed. To use the half open versions, +/// use GetOpenWidth() / GetOpenHeight(). +/// +/// If you want to work with Size, you must use the closed interval functions! +/// And don't add GetOpenSize() / setSize; this will probably just introduce +/// bugs, especially when used in combination with list-initialization. +/// +/// (Eventually you might notice, that the same engineer was also working on +/// Qt at some point; see documentation on QRect::bottom / QRect::right ;-). + +class TOOLS_DLLPUBLIC RectangleTemplateBase +{ +public: + static constexpr short RECT_EMPTY = -32767; + + constexpr RectangleTemplateBase() = default; + constexpr RectangleTemplateBase( tools::Long nLeft, tools::Long nTop, + tools::Long nRight, tools::Long nBottom ) + : mnLeft( nLeft ), mnTop( nTop ), mnRight( nRight ), mnBottom( nBottom ) + {} + /// Constructs an empty Rectangle, with top/left at the specified params + constexpr RectangleTemplateBase( tools::Long nLeft, tools::Long nTop ) + : mnLeft(nLeft), mnTop(nTop) + {} + /// Constructs a closed interval rectangle + constexpr RectangleTemplateBase( const PointTemplateBase& rLT, const SizeTemplateBase& rSize ) + : mnLeft( rLT.X()) + , mnTop( rLT.Y()) + , mnRight(rSize.Width() ? mnLeft + (rSize.Width() + (rSize.Width() > 0 ? -1 : 1)) : RECT_EMPTY) + , mnBottom(rSize.Height() ? mnTop + (rSize.Height() + (rSize.Height() > 0 ? -1 : 1)) : RECT_EMPTY) + {} + + constexpr tools::Long Left() const { return mnLeft; } + constexpr tools::Long Right() const { return IsWidthEmpty() ? mnLeft : mnRight; } + constexpr tools::Long Top() const { return mnTop; } + constexpr tools::Long Bottom() const { return IsHeightEmpty() ? mnTop : mnBottom; } + + constexpr void SetLeft(tools::Long v) { mnLeft = v; } + constexpr void SetRight(tools::Long v) { mnRight = v; } + constexpr void SetTop(tools::Long v) { mnTop = v; } + constexpr void SetBottom(tools::Long v) { mnBottom = v; } + + void SetEmpty() { mnRight = mnBottom = RECT_EMPTY; } + constexpr bool IsEmpty() const { return IsWidthEmpty() || IsHeightEmpty(); } + constexpr bool IsWidthEmpty() const { return mnRight == RECT_EMPTY; } + constexpr bool IsHeightEmpty() const { return mnBottom == RECT_EMPTY; } + void SetWidthEmpty() { mnRight = RECT_EMPTY; } + void SetHeightEmpty() { mnBottom = RECT_EMPTY; } + + tools::Long getX() const { return mnLeft; } + tools::Long getY() const { return mnTop; } + /// Returns the difference between right and left, assuming the range includes one end, but not the other. + tools::Long getOpenWidth() const { return Right() - Left(); } + /// Returns the difference between bottom and top, assuming the range includes one end, but not the other. + tools::Long getOpenHeight() const { return Bottom() - Top(); } + void setWidth( tools::Long n ) { mnRight = mnLeft + n; } + void setHeight( tools::Long n ) { mnBottom = mnTop + n; } + + /// Returns the difference between right and left, assuming the range is inclusive. + constexpr tools::Long GetWidth() const + { + tools::Long n = 0; + + if (!IsWidthEmpty()) + { + n = mnRight - mnLeft; + if (n < 0) + n--; + else + n++; + } + + return n; + } + /// Returns the difference between bottom and top, assuming the range is inclusive. + constexpr tools::Long GetHeight() const + { + tools::Long n = 0; + + if (!IsHeightEmpty()) + { + n = mnBottom - mnTop; + if (n < 0) + n--; + else + n++; + } + + return n; + } + + + tools::Long AdjustLeft( tools::Long nHorzMoveDelta ) { mnLeft += nHorzMoveDelta; return mnLeft; } + tools::Long AdjustRight( tools::Long nHorzMoveDelta ); + tools::Long AdjustTop( tools::Long nVertMoveDelta ) { mnTop += nVertMoveDelta; return mnTop; } + tools::Long AdjustBottom( tools::Long nVertMoveDelta ); + /// Set the left edge of the rectangle to x, preserving the width + void SetPosX(tools::Long x) + { + if (!IsWidthEmpty()) + mnRight += x - mnLeft; + mnLeft = x; + } + /// Set the top edge of the rectangle to y, preserving the height + void SetPosY(tools::Long y) + { + if (!IsHeightEmpty()) + mnBottom += y - mnTop; + mnTop = y; + } + + void SaturatingSetPosX(tools::Long x); + void SaturatingSetPosY(tools::Long y); + + void SetWidth(tools::Long nWidth) + { + if (nWidth < 0) + mnRight = mnLeft + nWidth + 1; + else if (nWidth > 0) + mnRight = mnLeft + nWidth - 1; + else + SetWidthEmpty(); + } + void SetHeight(tools::Long nHeight) + { + if (nHeight < 0) + mnBottom = mnTop + nHeight + 1; + else if (nHeight > 0) + mnBottom = mnTop + nHeight - 1; + else + SetHeightEmpty(); + } + + void Normalize(); + + /** + * Expands the rectangle in all directions by the input value. + */ + void expand(tools::Long nExpandBy); + void shrink(tools::Long nShrinkBy); + + /// Move the top and left edges by a delta, preserving width and height + void Move( tools::Long nHorzMoveDelta, tools::Long nVertMoveDelta ) + { + mnLeft += nHorzMoveDelta; + mnTop += nVertMoveDelta; + if (!IsWidthEmpty()) + mnRight += nHorzMoveDelta; + if (!IsHeightEmpty()) + mnBottom += nVertMoveDelta; + } + + /// Returns the string representation of the rectangle, format is "x, y, width, height". + rtl::OString toString() const; + +protected: + void SaturatingSetSize(const SizeTemplateBase& rSize); + void Union( const RectangleTemplateBase& rRect ); + void Intersection( const RectangleTemplateBase& rRect ); + bool Contains( const PointTemplateBase& rPOINT ) const; + bool Contains( const RectangleTemplateBase& rRect ) const; + bool Overlaps( const RectangleTemplateBase& rRect ) const; + + tools::Long mnLeft = 0; + tools::Long mnTop = 0; + tools::Long mnRight = RECT_EMPTY; + tools::Long mnBottom = RECT_EMPTY; +}; + +template<class RectangleT, class PointT, class SizeT> +class RectangleTemplate : public RectangleTemplateBase +{ +friend class ::tools::Rectangle; +friend class AbsoluteScreenPixelRectangle; +public: + using PointType = PointT; + using SizeType = SizeT; + +public: + constexpr RectangleTemplate() = default; + constexpr RectangleTemplate( const PointT& rLT, const PointT& rRB ) + : RectangleTemplate(rLT.X(), rLT.Y(), rRB.X(), rRB.Y()) {} + constexpr RectangleTemplate( tools::Long nLeft, tools::Long nTop, + tools::Long nRight, tools::Long nBottom ) + : RectangleTemplateBase(nLeft, nTop, nRight, nBottom ) + {} + /// Constructs an empty Rectangle, with top/left at the specified params + constexpr RectangleTemplate( tools::Long nLeft, tools::Long nTop ) + : RectangleTemplateBase(nLeft, nTop) + {} + /// Constructs a closed interval rectangle + constexpr RectangleTemplate( const PointT& rLT, const SizeT& rSize ) + : RectangleTemplateBase( rLT, rSize ) + {} + + using RectangleTemplateBase::Normalize; + constexpr static RectangleT Normalize(const PointT& rLT, const PointT& rRB) + { + const std::pair<tools::Long, tools::Long> aLeftRight = std::minmax(rLT.X(), rRB.X()); + const std::pair<tools::Long, tools::Long> aTopBottom = std::minmax(rLT.Y(), rRB.Y()); + return { aLeftRight.first, aTopBottom.first, aLeftRight.second, aTopBottom.second }; + } + + constexpr PointT TopLeft() const { return { Left(), Top() }; } + constexpr PointT TopRight() const { return { Right(), Top() }; } + constexpr PointT TopCenter() const { return { (Left() + Right()) / 2, Top() }; } + constexpr PointT BottomLeft() const { return { Left(), Bottom() }; } + constexpr PointT BottomRight() const { return { Right(), Bottom() }; } + constexpr PointT BottomCenter() const { return { (Left() + Right()) / 2, Bottom() }; } + constexpr PointT LeftCenter() const { return { Left(), (Top() + Bottom()) / 2 }; } + constexpr PointT RightCenter() const { return { Right(), (Top() + Bottom()) / 2 }; } + constexpr PointT Center() const { return { (Left() + Right()) / 2, (Top() + Bottom()) / 2 }; } + + using RectangleTemplateBase::Move; + void Move( SizeT const & s ) { Move(s.Width(), s.Height()); } + void SetPos( const PointT& rPoint ) + { + SetPosX(rPoint.X()); + SetPosY(rPoint.Y()); + } + void SetSize(const SizeT& rSize) + { + SetWidth(rSize.Width()); + SetHeight(rSize.Height()); + } + + constexpr PointT GetPos() const { return TopLeft(); } + constexpr SizeT GetSize() const { return { GetWidth(), GetHeight() }; } + + RectangleT& Union( const RectangleTemplate& rRect ) { RectangleTemplateBase::Union(rRect); return static_cast<RectangleT&>(*this); } + RectangleT& Intersection( const RectangleTemplate& rRect ) { RectangleTemplateBase::Intersection(rRect); return static_cast<RectangleT&>(*this); } + RectangleT GetUnion( const RectangleT& rRect ) const + { + RectangleT aTmpRect( rRect ); + return aTmpRect.Union( *this ); + } + RectangleT GetIntersection( const RectangleT& rRect ) const + { + RectangleT aTmpRect( rRect ); + return aTmpRect.Intersection( *this ); + } + + bool Contains( const PointT& rPt ) const { return RectangleTemplateBase::Contains(rPt); } + bool Contains( const RectangleT& rRect ) const { return RectangleTemplateBase::Contains(rRect); } + bool Overlaps( const RectangleT& rRect ) const { return RectangleTemplateBase::Overlaps(rRect); } + + bool operator == ( const RectangleTemplate& rRect ) const + { + return (mnLeft == rRect.mnLeft ) && + (mnTop == rRect.mnTop ) && + (mnRight == rRect.mnRight ) && + (mnBottom == rRect.mnBottom ); + } + bool operator != ( const RectangleTemplate& rRect ) const + { + return (mnLeft != rRect.mnLeft ) || + (mnTop != rRect.mnTop ) || + (mnRight != rRect.mnRight ) || + (mnBottom != rRect.mnBottom ); + } + + RectangleT& operator += ( const PointT& rPt ) + { + Move(rPt.X(), rPt.Y()); + return static_cast<RectangleT&>(*this); + } + RectangleT& operator -= ( const PointT& rPt ) + { + Move(-rPt.X(), -rPt.Y()); + return static_cast<RectangleT&>(*this); + } + + RectangleT operator+( const Point& rPt ) const + { + RectangleT aTmp(mnLeft, mnTop, mnRight, mnBottom); + aTmp += rPt; + return aTmp; + } + RectangleT operator-( const Point& rPt ) const + { + RectangleT aTmp(mnLeft, mnTop, mnRight, mnBottom); + aTmp -= rPt; + return aTmp; + } + + /** + * Sanitizing variants for handling data from the outside + */ + void SaturatingSetSize(const SizeT& rSize) { RectangleTemplateBase::SaturatingSetSize(rSize); } + + // Scales relative to 0,0 + constexpr RectangleT scale(sal_Int64 nMulX, sal_Int64 nDivX, + sal_Int64 nMulY, sal_Int64 nDivY) const + { + // 1. Create an empty rectangle with correct left and top + RectangleT aRect(o3tl::convert(Left(), nMulX, nDivX), + o3tl::convert(Top(), nMulY, nDivY)); + // 2. If source has width/height, set respective right and bottom + if (!IsWidthEmpty()) + aRect.SetRight(o3tl::convert(Right(), nMulX, nDivX)); + if (!IsHeightEmpty()) + aRect.SetBottom(o3tl::convert(Bottom(), nMulY, nDivY)); + return aRect; + } +}; + +namespace tools +{ +class SAL_WARN_UNUSED Rectangle final : public RectangleTemplate<Rectangle, Point, Size> +{ +public: + using RectangleTemplate::RectangleTemplate; + // TODO remove this to find more issues + constexpr Rectangle(const AbsoluteScreenPixelPoint& pt, const Size& sz) : RectangleTemplate(Point(pt.X(), pt.Y()), sz) {} + // TODO remove this to find more issues + constexpr Rectangle(const Point& pt, const AbsoluteScreenPixelSize& sz) : RectangleTemplate(pt, Size(sz.Width(), sz.Height())) {} + // TODO remove this to find more issues + constexpr explicit Rectangle(const AbsoluteScreenPixelRectangle & r); +}; + +} // namespace tools + + +// A rectangle relative to top-level screen, in screen pixels +class SAL_WARN_UNUSED AbsoluteScreenPixelRectangle : public RectangleTemplate<AbsoluteScreenPixelRectangle, AbsoluteScreenPixelPoint, AbsoluteScreenPixelSize> { +public: + using RectangleTemplate::RectangleTemplate; + // TODO remove + constexpr explicit AbsoluteScreenPixelRectangle(const tools::Rectangle & r) : RectangleTemplate(r.mnLeft, r.mnTop, r.mnRight, r.mnBottom) {} + // TODO remove + constexpr AbsoluteScreenPixelRectangle(const AbsoluteScreenPixelPoint& pt, const Size& sz) : RectangleTemplate(pt, AbsoluteScreenPixelSize(sz.Width(), sz.Height())) {} +}; + +namespace tools +{ + constexpr Rectangle::Rectangle(const AbsoluteScreenPixelRectangle & r) : RectangleTemplate(r.mnLeft, r.mnTop, r.mnRight, r.mnBottom) {} +} + +namespace o3tl +{ + +template <class RectangleT, + std::enable_if_t<std::is_base_of_v<RectangleTemplate<RectangleT, typename RectangleT::PointType, typename RectangleT::SizeType>, RectangleT>, int> = 0> +constexpr auto convert(const RectangleT& rRectangle, o3tl::Length eFrom, o3tl::Length eTo) +{ + const auto [num, den] = o3tl::getConversionMulDiv(eFrom, eTo); + return rRectangle.scale(num, den, num, den); +} + +} // end o3tl + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const RectangleTemplateBase& rectangle ) +{ + if (rectangle.IsEmpty()) + return stream << "EMPTY"; + else + return stream << rectangle.GetWidth() << 'x' << rectangle.GetHeight() + << "@(" << rectangle.getX() << ',' << rectangle.getY() << ")"; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/globname.hxx b/include/tools/globname.hxx new file mode 100644 index 0000000000..50c3fc27b9 --- /dev/null +++ b/include/tools/globname.hxx @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_GLOBNAME_HXX +#define INCLUDED_TOOLS_GLOBNAME_HXX + +#include <tools/toolsdllapi.h> +#include <com/sun/star/uno/Sequence.hxx> + +struct SAL_WARN_UNUSED SvGUID +{ + sal_uInt32 Data1; + sal_uInt16 Data2; + sal_uInt16 Data3; + sal_uInt8 Data4[8]; +}; + +class SvStream; + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC SvGlobalName +{ +public: + SvGlobalName() = default; + SvGlobalName(const SvGlobalName& rObj) = default; + + SvGlobalName( sal_uInt32 n1, sal_uInt16 n2, sal_uInt16 n3, + sal_uInt8 b8, sal_uInt8 b9, sal_uInt8 b10, sal_uInt8 b11, + sal_uInt8 b12, sal_uInt8 b13, sal_uInt8 b14, sal_uInt8 b15 ); + + // create SvGlobalName from a platform independent representation + SvGlobalName( const css::uno::Sequence< sal_Int8 >& aSeq ); + + SvGlobalName( const SvGUID & rId ); + + SvGlobalName & operator = ( const SvGlobalName & rObj ) = default; + + TOOLS_DLLPUBLIC friend SvStream & operator >> ( SvStream &, SvGlobalName & ); + TOOLS_DLLPUBLIC friend SvStream & WriteSvGlobalName( SvStream &, const SvGlobalName & ); + + bool operator < ( const SvGlobalName & rObj ) const; + + bool operator == ( const SvGlobalName & rObj ) const; + bool operator != ( const SvGlobalName & rObj ) const + { return !(*this == rObj); } + + void MakeFromMemory( void const * pData ); + bool MakeId( std::u16string_view rId ); + OUString GetHexName() const; + + const SvGUID& GetCLSID() const { return m_aData; } + + // platform independent representation of a "GlobalName" + // maybe transported remotely + css::uno::Sequence < sal_Int8 > GetByteSequence() const; + +private: + SvGUID m_aData = {}; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/helpers.hxx b/include/tools/helpers.hxx new file mode 100644 index 0000000000..05ee59960f --- /dev/null +++ b/include/tools/helpers.hxx @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include <sal/config.h> +#include <sal/types.h> +#include <tools/long.hxx> +#include <cassert> +#include <limits> +#include <type_traits> + +inline sal_uInt32 AlignedWidth4Bytes(sal_uInt32 nWidthBits) +{ + if (nWidthBits > SAL_MAX_UINT32 - 31) + nWidthBits = SAL_MAX_UINT32; + else + nWidthBits += 31; + return (nWidthBits >> 5) << 2; +} + +inline tools::Long FRound( double fVal ) +{ + return fVal > 0.0 + ? fVal == double(std::numeric_limits<tools::Long>::max()) + ? std::numeric_limits<tools::Long>::max() : static_cast<tools::Long>( fVal + 0.5 ) + : static_cast<tools::Long>( fVal - 0.5 ); +} + +//valid range: (-180,180] +template <typename T> +[[nodiscard]] inline typename std::enable_if<std::is_signed<T>::value, T>::type +NormAngle180(T angle) +{ + while (angle <= -180) + angle += 360; + while (angle > 180) + angle -= 360; + return angle; +} + +//valid range: [0,360) +template <typename T> [[nodiscard]] inline T NormAngle360(T angle) +{ + while (angle < 0) + angle += 360; + while (angle >= 360) + angle -= 360; + return angle; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/inetmime.hxx b/include/tools/inetmime.hxx new file mode 100644 index 0000000000..bd0ba36bb1 --- /dev/null +++ b/include/tools/inetmime.hxx @@ -0,0 +1,240 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_INETMIME_HXX +#define INCLUDED_TOOLS_INETMIME_HXX + +#include <tools/toolsdllapi.h> +#include <rtl/character.hxx> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +#include <unordered_map> + +struct INetContentTypeParameter +{ + /** The optional character set specification (see RFC 2231), in US-ASCII + encoding and converted to lower case. + */ + OString m_sCharset; + + /** The optional language specification (see RFC 2231), in US-ASCII + encoding and converted to lower case. + */ + OString m_sLanguage; + + /** The attribute value. If the value is a quoted-string, it is + 'unpacked.' If a character set is specified, and the value can be + converted to Unicode, this is done. Also, if no character set is + specified, it is first tried to convert the value from UTF-8 encoding + to Unicode, and if that doesn't work (because the value is not in + UTF-8 encoding), it is converted from ISO-8859-1 encoding to Unicode + (which will always work). But if a character set is specified and the + value cannot be converted from that character set to Unicode, special + action is taken to produce a value that can possibly be transformed + back into its original form: Any 8-bit character from a non-encoded + part of the original value is directly converted to Unicode + (effectively handling it as if it was ISO-8859-1 encoded), and any + 8-bit character from an encoded part of the original value is mapped + to the range U+F800..U+F8FF at the top of the Corporate Use Subarea + within Unicode's Private Use Area (effectively adding 0xF800 to the + character's numeric value). + */ + OUString m_sValue; + + /** This is true if the value is successfully converted to Unicode, and + false if the value is a special mixture of ISO-LATIN-1 characters and + characters from Unicode's Private Use Area. + */ + bool m_bConverted; +}; + +/** The key is the name of the attribute, in US-ASCII encoding and converted + to lower case. If a parameter value is split as described in RFC 2231, + there will only be one item for the complete parameter, with the attribute + name lacking any section suffix. + */ +typedef std::unordered_map<OString, INetContentTypeParameter> + INetContentTypeParameterList; + + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC INetMIME +{ +public: + /** Check for US-ASCII visible character. + + @param nChar Some UCS-4 character. + + @return True if nChar is a US-ASCII visible character (US-ASCII + 0x21--0x7E). + */ + static inline bool isVisible(sal_uInt32 nChar); + + /** Check whether some character is valid within an RFC 822 <atom>. + + @param nChar Some UCS-4 character. + + @return True if nChar is valid within an RFC 822 <atom> (US-ASCII + 'A'--'Z', 'a'--'z', '0'--'9', '!', '#', '$', '%', '&', ''', '*', '+', + '-', '/', '=', '?', '^', '_', '`', '{', '|', '}', or '~'). + */ + static bool isAtomChar(sal_uInt32 nChar); + + /** Check whether some character is valid within an RFC 2060 <atom>. + + @param nChar Some UCS-4 character. + + @return True if nChar is valid within an RFC 2060 <atom> (US-ASCII + 'A'--'Z', 'a'--'z', '0'--'9', '!', '#', '$', '&', ''', '+', ',', '-', + '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', ']', '^', '_', '`', + '|', '}', or '~'). + */ + static bool isIMAPAtomChar(sal_uInt32 nChar); + + /** Get the digit weight of a US-ASCII character. + + @param nChar Some UCS-4 character. + + @return If nChar is a US-ASCII (decimal) digit character (US-ASCII + '0'--'9'), return the corresponding weight (0--9); otherwise, + return -1. + */ + static inline int getWeight(sal_uInt32 nChar); + + /** Get the hexadecimal digit weight of a US-ASCII character. + + @param nChar Some UCS-4 character. + + @return If nChar is a US-ASCII hexadecimal digit character (US-ASCII + '0'--'9', 'A'--'F', or 'a'--'f'), return the corresponding weight + (0--15); otherwise, return -1. + */ + static inline int getHexWeight(sal_uInt32 nChar); + + /** Check two US-ASCII strings for equality, ignoring case. + + @param pBegin1 Points to the start of the first string, must not be + null. + + @param pEnd1 Points past the end of the first string, must be >= + pBegin1. + + @param pString2 Points to the start of the null terminated second + string, must not be null. + + @return True if the two strings are equal, ignoring the case of US- + ASCII alphabetic characters (US-ASCII 'A'--'Z' and 'a'--'z'). + */ + static bool equalIgnoreCase(const sal_Unicode * pBegin1, + const sal_Unicode * pEnd1, + const char * pString2); + + static bool scanUnsigned(const sal_Unicode *& rBegin, + const sal_Unicode * pEnd, bool bLeadingZeroes, + sal_uInt32 & rValue); + + /** Parse the body of an RFC 2045 Content-Type header field. + + @param pBegin The range (that must be valid) from non-null pBegin, + inclusive. to non-null pEnd, exclusive, forms the body of the + Content-Type header field. It must be of the form + + token "/" token *(";" token "=" (token / quoted-string)) + + with intervening linear white space and comments (cf. RFCs 822, 2045). + The RFC 2231 extensions are supported. The encoding of rMediaType + should be US-ASCII, but any Unicode values in the range U+0080..U+FFFF + are interpreted 'as appropriate.' + + @param pType If not null, returns the type (the first of the above + tokens), in US-ASCII encoding and converted to lower case. + + @param pSubType If not null, returns the sub-type (the second of the + above tokens), in US-ASCII encoding and converted to lower case. + + @param pParameters If not null, returns the parameters as a list of + INetContentTypeParameters (the attributes are in US-ASCII encoding and + converted to lower case, the values are in Unicode encoding). If + null, only the syntax of the parameters is checked, but they are not + returned. + + @return Null if the syntax of the field body is incorrect (i.e., does + not start with type and sub-type tokens). Otherwise, a pointer past the + longest valid input prefix. If null is returned, none of the output + parameters will be modified. + */ + static sal_Unicode const * scanContentType( + std::u16string_view rStr, + OUString * pType = nullptr, OUString * pSubType = nullptr, + INetContentTypeParameterList * pParameters = nullptr); + + static OUString decodeHeaderFieldBody(const OString& rBody); + + /** Get the UTF-32 character at the head of a UTF-16 encoded string. + + @param rBegin Points to the start of the UTF-16 encoded string, must + not be null. On exit, it points past the first UTF-32 character's + encoding. + + @param pEnd Points past the end of the UTF-16 encoded string, must be + strictly greater than rBegin. + + @return The UCS-4 character at the head of the UTF-16 encoded string. + If the string does not start with the UTF-16 encoding of a UCS-32 + character, the first UTF-16 value is returned. + */ + static inline sal_uInt32 getUTF32Character(const sal_Unicode *& rBegin, + const sal_Unicode * pEnd); +}; + +// static +inline bool INetMIME::isVisible(sal_uInt32 nChar) +{ + return nChar >= '!' && nChar <= '~'; +} + +// static +inline int INetMIME::getWeight(sal_uInt32 nChar) +{ + return rtl::isAsciiDigit(nChar) ? int(nChar - '0') : -1; +} + +// static +inline int INetMIME::getHexWeight(sal_uInt32 nChar) +{ + return rtl::isAsciiDigit(nChar) ? int(nChar - '0') : + nChar >= 'A' && nChar <= 'F' ? int(nChar - 'A' + 10) : + nChar >= 'a' && nChar <= 'f' ? int(nChar - 'a' + 10) : -1; +} + +// static +inline sal_uInt32 INetMIME::getUTF32Character(const sal_Unicode *& rBegin, + const sal_Unicode * pEnd) +{ + assert(rBegin && rBegin < pEnd && + "INetMIME::getUTF32Character(): Bad sequence"); + sal_uInt32 nUTF32 = *rBegin++; + if (rBegin < pEnd && rtl::isHighSurrogate(nUTF32) && rtl::isLowSurrogate(rBegin[0])) + nUTF32 = rtl::combineSurrogates(nUTF32, *rBegin++); + return nUTF32; +} + + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/inetmsg.hxx b/include/tools/inetmsg.hxx new file mode 100644 index 0000000000..8617b0b91b --- /dev/null +++ b/include/tools/inetmsg.hxx @@ -0,0 +1,187 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_INETMSG_HXX +#define INCLUDED_TOOLS_INETMSG_HXX + +#include <tools/toolsdllapi.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <tools/inetmime.hxx> +#include <tools/stream.hxx> + +#include <string_view> +#include <utility> +#include <vector> +#include <map> +#include <memory> +#include <config_options.h> + +class DateTime; + +class SAL_WARN_UNUSED INetMessageHeader +{ + OString m_aName; + OString m_aValue; + +public: + INetMessageHeader() + {} + + INetMessageHeader(OString aName, OString aValue) + : m_aName (std::move(aName)), m_aValue (std::move(aValue)) + {} + + INetMessageHeader ( + const INetMessageHeader& rHdr) + : m_aName (rHdr.m_aName), m_aValue (rHdr.m_aValue) + {} + + INetMessageHeader& operator= (const INetMessageHeader& rHdr) + { + m_aName = rHdr.m_aName; + m_aValue = rHdr.m_aValue; + return *this; + } + + const OString& GetName() const { return m_aName; } + const OString& GetValue() const { return m_aValue; } +}; + +enum class InetMessageMime +{ + VERSION = 0, + CONTENT_DISPOSITION = 1, + CONTENT_TYPE = 2, + CONTENT_TRANSFER_ENCODING = 3, + NUMHDR = 4, +}; + +class SAL_WARN_UNUSED UNLESS_MERGELIBS(TOOLS_DLLPUBLIC) INetMIMEMessage +{ + ::std::vector< std::unique_ptr<INetMessageHeader> > + m_aHeaderList; + + SvLockBytesRef m_xDocLB; + + ::std::map<InetMessageMime, sal_uInt32> m_nMIMEIndex; + INetMIMEMessage* pParent; + ::std::vector< std::unique_ptr<INetMIMEMessage> > + aChildren; + OString m_aBoundary; + + OUString GetHeaderValue_Impl ( + sal_uInt32 nIndex) const + { + if ( nIndex < m_aHeaderList.size() ) { + return INetMIME::decodeHeaderFieldBody(m_aHeaderList[ nIndex ]->GetValue()); + } else { + return OUString(); + } + } + + void SetHeaderField_Impl ( + const INetMessageHeader &rHeader, sal_uInt32 &rnIndex) + { + INetMessageHeader *p = new INetMessageHeader (rHeader); + if (m_aHeaderList.size() <= rnIndex) + { + rnIndex = m_aHeaderList.size(); + m_aHeaderList.emplace_back( p ); + } + else + { + m_aHeaderList[ rnIndex ].reset(p); + } + } + + void SetHeaderField_Impl ( + const OString &rName, + const OUString &rValue, + sal_uInt32 &rnIndex); + + bool IsMessage() const + { + OUString aType (GetContentType()); + return aType.matchIgnoreAsciiCase("message/"); + } + + INetMIMEMessage (const INetMIMEMessage& rMsg) = delete; + INetMIMEMessage& operator= (const INetMIMEMessage& rMsg) = delete; + +public: + INetMIMEMessage(); + ~INetMIMEMessage(); + + sal_uInt32 GetHeaderCount() const { return m_aHeaderList.size(); } + + INetMessageHeader GetHeaderField (sal_uInt32 nIndex) const + { + if ( nIndex < m_aHeaderList.size() ) { + return *m_aHeaderList[ nIndex ]; + } else { + return INetMessageHeader(); + } + } + + SvLockBytes* GetDocumentLB() const { return m_xDocLB.get(); } + void SetDocumentLB (SvLockBytes *pDocLB) { m_xDocLB = pDocLB; } + + static bool ParseDateField ( + std::u16string_view rDateField, DateTime& rDateTime); + + void SetMIMEVersion (const OUString& rVersion); + void SetContentDisposition (const OUString& rDisposition); + void SetContentType (const OUString& rType); + OUString GetContentType() const + { + return GetHeaderValue_Impl( + m_nMIMEIndex.at(InetMessageMime::CONTENT_TYPE)); + } + + void SetContentTransferEncoding (const OUString& rEncoding); + + OUString GetDefaultContentType (); + + // Message container methods. + + bool IsContainer() const + { + return (IsMessage() || IsMultipart()); + } + bool IsMultipart() const + { + OUString aType (GetContentType()); + return aType.matchIgnoreAsciiCase("multipart/"); + } + + INetMIMEMessage* GetChild (sal_uInt32 nIndex) const + { + return ( nIndex < aChildren.size() ) ? aChildren[ nIndex ].get() : nullptr; + } + INetMIMEMessage* GetParent() const { return pParent; } + + void EnableAttachMultipartFormDataChild(); + void AttachChild( std::unique_ptr<INetMIMEMessage> pChildMsg ); + + const OString& GetMultipartBoundary() const { return m_aBoundary; } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/inetstrm.hxx b/include/tools/inetstrm.hxx new file mode 100644 index 0000000000..50b0d25f43 --- /dev/null +++ b/include/tools/inetstrm.hxx @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <tools/toolsdllapi.h> +#include <tools/stream.hxx> +#include <sal/types.h> +#include <vector> +#include <memory> +#include <config_options.h> + +class INetMIMEMessage; + +class UNLESS_MERGELIBS(TOOLS_DLLPUBLIC) INetMIMEMessageStream +{ + INetMIMEMessage *pSourceMsg; + bool bHeaderGenerated; + + std::vector<char> mvBuffer; + char *pRead; + char *pWrite; + + std::unique_ptr<SvStream> + pMsgStrm; + SvMemoryStream maMsgBuffer; + char *pMsgRead; + char *pMsgWrite; + + bool done; + + sal_uInt32 nChildIndex; + std::unique_ptr<INetMIMEMessageStream> pChildStrm; + + INetMIMEMessageStream (const INetMIMEMessageStream& rStrm) = delete; + INetMIMEMessageStream& operator= (const INetMIMEMessageStream& rStrm) = delete; + + int GetHeaderLine(char *pData, sal_uInt32 nSize); + int GetBodyLine(char *pData, sal_uInt32 nSize); + int GetMsgLine(char *pData, sal_uInt32 nSize); + +public: + explicit INetMIMEMessageStream(INetMIMEMessage *pMsg, bool headerGenerated); + ~INetMIMEMessageStream(); + + int Read (char *pData, sal_uInt32 nSize); +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/json_writer.hxx b/include/tools/json_writer.hxx new file mode 100644 index 0000000000..c5faf542f1 --- /dev/null +++ b/include/tools/json_writer.hxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include <sal/config.h> + +#include <tools/toolsdllapi.h> +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> + +#include <string_view> + +/** Simple JSON encoder designed specifically for LibreOfficeKit purposes. + * + * (1) Minimal allocations/re-allocations/copying + * (2) Small/simple JSON documents + * (3) ascii property names + */ +namespace tools +{ +class ScopedJsonWriterNode; +class ScopedJsonWriterArray; +class ScopedJsonWriterStruct; + +class TOOLS_DLLPUBLIC JsonWriter +{ + friend class ScopedJsonWriterNode; + friend class ScopedJsonWriterArray; + friend class ScopedJsonWriterStruct; + + char* mpBuffer; + char* mPos; + int mSpaceAllocated; + int mStartNodeCount; + bool mbFirstFieldInNode; + bool mbClosed; // cannot add to it anymore + +public: + JsonWriter(); + ~JsonWriter(); + + [[nodiscard]] ScopedJsonWriterNode startNode(std::string_view); + [[nodiscard]] ScopedJsonWriterArray startArray(std::string_view); + [[nodiscard]] ScopedJsonWriterStruct startStruct(); + + void put(std::u16string_view pPropName, const OUString& rPropValue); + + void put(std::string_view pPropName, const OUString& rPropValue); + // Assumes utf-8 property value encoding + void put(std::string_view pPropName, std::string_view rPropValue); + void put(std::string_view pPropName, const char* pPropVal) + { + put(pPropName, std::string_view(pPropVal)); + } + template <size_t N> void put(std::string_view pPropName, const char (&pPropVal)[N]) + { + put(pPropName, std::string_view(pPropVal, N)); + } + + template <typename N, std::enable_if_t<std::is_arithmetic_v<N>, int> = 0> + void put(std::string_view pPropName, N n) + { + putLiteral(pPropName, OString::number(n)); + } + void put(std::string_view pPropName, bool); + + void putSimpleValue(const OUString& rPropValue); + + /// This assumes that this data belongs at this point in the stream, and is valid, and properly encoded + void putRaw(std::string_view); + + /** Closes the tags, and returns data. + * After this no more document modifications may be written. */ + OString finishAndGetAsOString(); + + /** returns true if the current JSON data matches the string */ + bool isDataEquals(std::string_view) const; + +private: + void endNode(); + void endArray(); + void endStruct(); + void addCommaBeforeField(); + void writeEscapedOUString(const OUString& rPropVal); + void closeDocument(); + void ensureSpace(int noMoreBytesRequired); + void ensureSpaceAndWriteNameColon(std::string_view name, int valSize); + void putLiteral(std::string_view propName, std::string_view propValue); + + // overflow validation in debug mode + static constexpr unsigned char JSON_WRITER_DEBUG_MARKER = 0xde; + + inline void addValidationMark() + { +#ifndef NDEBUG + *(mpBuffer + mSpaceAllocated - 1) = JSON_WRITER_DEBUG_MARKER; +#endif + } + + inline void validate() + { +#ifndef NDEBUG + unsigned char c = *(mpBuffer + mSpaceAllocated - 1); + assert(c == JSON_WRITER_DEBUG_MARKER); +#endif + } +}; + +/** + * Auto-closes the node. + */ +class ScopedJsonWriterNode +{ + friend class JsonWriter; + + JsonWriter& mrWriter; + + ScopedJsonWriterNode(JsonWriter& rWriter) + : mrWriter(rWriter) + { + } + +public: + ~ScopedJsonWriterNode() { mrWriter.endNode(); } +}; + +/** + * Auto-closes the node. + */ +class ScopedJsonWriterArray +{ + friend class JsonWriter; + + JsonWriter& mrWriter; + + ScopedJsonWriterArray(JsonWriter& rWriter) + : mrWriter(rWriter) + { + } + +public: + ~ScopedJsonWriterArray() { mrWriter.endArray(); } +}; + +/** + * Auto-closes the node. + */ +class ScopedJsonWriterStruct +{ + friend class JsonWriter; + + JsonWriter& mrWriter; + + ScopedJsonWriterStruct(JsonWriter& rWriter) + : mrWriter(rWriter) + { + } + +public: + ~ScopedJsonWriterStruct() { mrWriter.endStruct(); } +}; +} +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/tools/line.hxx b/include/tools/line.hxx new file mode 100644 index 0000000000..97cf449fc1 --- /dev/null +++ b/include/tools/line.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_LINE_HXX +#define INCLUDED_TOOLS_LINE_HXX + +#include <tools/toolsdllapi.h> +#include <tools/gen.hxx> + +namespace tools +{ + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Line +{ +private: + Point maStart; + Point maEnd; + +public: + Line( const Point& rStartPt, const Point& rEndPt ) : maStart( rStartPt ), maEnd( rEndPt ) {} + + void SetStart( const Point& rStartPt ) { maStart = rStartPt; } + const Point& GetStart() const { return maStart; } + + void SetEnd( const Point& rEndPt ) { maEnd = rEndPt; } + const Point& GetEnd() const { return maEnd; } + + double GetLength() const; + + bool Intersection( const tools::Line& rLine, double& rIntersectionX, double& rIntersectionY ) const; + bool Intersection( const tools::Line& rLine, Point& rIntersection ) const; + + double GetDistance( const double& rPtX, const double& rPtY ) const; + double GetDistance( const Point& rPoint ) const { return GetDistance( rPoint.X(), rPoint.Y() ); } +}; + +} // namespace tools + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/lineend.hxx b/include/tools/lineend.hxx new file mode 100644 index 0000000000..165d8b5495 --- /dev/null +++ b/include/tools/lineend.hxx @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_TOOLS_LINEEND_HXX +#define INCLUDED_TOOLS_LINEEND_HXX + +#include <rtl/string.hxx> +#include <rtl/ustring.hxx> +#include <tools/toolsdllapi.h> + +enum LineEnd { LINEEND_CR, LINEEND_LF, LINEEND_CRLF }; + +inline LineEnd GetSystemLineEnd() +{ +#if defined(_WIN32) + return LINEEND_CRLF; +#else + return LINEEND_LF; +#endif +} + +TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd); +TOOLS_DLLPUBLIC OUString convertLineEnd(const OUString &rIn, LineEnd eLineEnd); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/link.hxx b/include/tools/link.hxx new file mode 100644 index 0000000000..ec88bf9533 --- /dev/null +++ b/include/tools/link.hxx @@ -0,0 +1,180 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_TOOLS_LINK_HXX +#define INCLUDED_TOOLS_LINK_HXX + +#include <sal/config.h> + +#include <sal/macros.h> +#include <sal/types.h> + +#define DECL_LINK(Member, ArgType, RetType) \ + static RetType LinkStub##Member(void *, ArgType); \ + RetType Member(ArgType) + +#define DECL_STATIC_LINK(Class, Member, ArgType, RetType) \ + static RetType LinkStub##Member(void *, ArgType); \ + static RetType Member(Class *, ArgType) + +#define DECL_DLLPRIVATE_LINK(Member, ArgType, RetType) \ + SAL_DLLPRIVATE static RetType LinkStub##Member(void *, ArgType); \ + SAL_DLLPRIVATE RetType Member(ArgType) + +#define DECL_DLLPRIVATE_STATIC_LINK(Class, Member, ArgType, RetType) \ + SAL_DLLPRIVATE static RetType LinkStub##Member(void *, ArgType); \ + SAL_DLLPRIVATE static RetType Member(Class *, ArgType) + +#define IMPL_LINK(Class, Member, ArgType, ArgName, RetType) \ + RetType Class::LinkStub##Member(void * instance, ArgType data) { \ + return static_cast<Class *>(instance)->Member(data); \ + } \ + RetType Class::Member(ArgType ArgName) + +#define IMPL_LINK_NOARG(Class, Member, ArgType, RetType) \ + RetType Class::LinkStub##Member(void * instance, ArgType data) { \ + return static_cast<Class *>(instance)->Member(data); \ + } \ + RetType Class::Member(SAL_UNUSED_PARAMETER ArgType) + +#define IMPL_STATIC_LINK( \ + Class, Member, ArgType, ArgName, RetType) \ + RetType Class::LinkStub##Member(void * instance, ArgType data) { \ + return Member(static_cast<Class *>(instance), data); \ + } \ + RetType Class::Member(SAL_UNUSED_PARAMETER Class *, ArgType ArgName) + +#define IMPL_STATIC_LINK_NOARG( \ + Class, Member, ArgType, RetType) \ + RetType Class::LinkStub##Member(void * instance, ArgType data) { \ + return Member(static_cast<Class *>(instance), data); \ + } \ + RetType Class::Member( \ + SAL_UNUSED_PARAMETER Class *, SAL_UNUSED_PARAMETER ArgType) + +#ifdef DBG_UTIL +#define LINK(Instance, Class, Member) ::tools::detail::makeLink( \ + ::tools::detail::castTo<Class *>(Instance), &Class::LinkStub##Member, __FILE__, __LINE__, SAL_STRINGIFY(Class::LinkStub##Member)) +#else +#define LINK(Instance, Class, Member) ::tools::detail::makeLink( \ + ::tools::detail::castTo<Class *>(Instance), &Class::LinkStub##Member) +#endif + +template<typename Arg, typename Ret> +class SAL_WARN_UNUSED Link { +public: + typedef Ret Stub(void *, Arg); + +#ifdef DBG_UTIL + Link() + : function_(nullptr) + , instance_(nullptr) + , file_("unknown") + , line_(0) + , target_("unknown") + { + } + + Link(void* instance, Stub* function, const char* const file = "unknown", const int line = 0, + const char* const target = "unknown") + : function_(function) + , instance_(instance) + , file_(file) + , line_(line) + , target_(target) + { + } +#else + Link(): function_(nullptr), instance_(nullptr) {} + + Link(void * instance, Stub * function): + function_(function), instance_(instance) {} +#endif + + Ret Call(Arg data) const + { return function_ == nullptr ? Ret() : (*function_)(instance_, data); } + + bool IsSet() const { return function_ != nullptr; } + + bool operator !() const { return !IsSet(); } + + bool operator <(Link const & other) const { + char* ptr1 = reinterpret_cast<char*>(function_); + char* ptr2 = reinterpret_cast<char*>(other.function_); + if (ptr1 < ptr2) + return true; + else if (ptr1 > ptr2) + return false; + else + return instance_ < other.instance_; + }; + + bool operator ==(Link const & other) const + { return function_ == other.function_ && instance_ == other.instance_; }; + + void *GetInstance() const { return instance_; } + +#ifdef DBG_UTIL + const char* getSourceFilename() const { return file_; } + int getSourceLineNumber() const { return line_; } + const char* getTargetName() const { return target_; } +#endif + +private: + Stub * function_; + void * instance_; + +#ifdef DBG_UTIL + /// Support tracing link source and target. + /// When debugging async events, it's often critical + /// to find out not only where a link leads (i.e. the target + /// function), but also where it was created (file:line). + const char* file_; + int line_; + const char* target_; +#endif +}; + +// Class used to indicate that the Call() parameter is not in use: +class LinkParamNone { LinkParamNone() = delete; }; + +namespace tools::detail { + +// Avoids loplugin:redundantcast in LINK macro, in the common case that Instance +// is already of type Class * (instead of a derived type): +template<typename To, typename From> To castTo(From from) +{ return static_cast<To>(from); } + +#ifdef DBG_UTIL +template<typename Arg, typename Ret> +Link<Arg, Ret> makeLink(void * instance, Ret (* function)(void *, Arg), const char* file, int line, const char* target) { + return Link<Arg, Ret>(instance, function, file, line, target); +} +#else +template<typename Arg, typename Ret> +Link<Arg, Ret> makeLink(void * instance, Ret (* function)(void *, Arg)) { + return Link<Arg, Ret>(instance, function); +} +#endif + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/long.hxx b/include/tools/long.hxx new file mode 100644 index 0000000000..2388565df0 --- /dev/null +++ b/include/tools/long.hxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +#pragma once + +#include <sal/types.h> + +/** + * We have an unfortunate problem in that, on Windows (both 32 and 64-bit), long is always 32-bit. + * But on Linux (64-bit) long is 64-bit. Which leads to nasty situations where things that work + * on Linux, failed on Windows. + * So....., + * (1) introduce a typedef that replaces (almost) all previous usage + * (2) on 64-bit Windows, this typedef is forced to 64-bit (32-bit platforms, including 32-bit Windows, are left alone) + * (3) fix fallout from (2) + * + * As a consequence of the above, it would be best, over the long term, to regard usage + * of tools::Long in the codebase as meaning "we're not sure what the ideal size of the datatype is", + * and where possible, replace it with a better datatype like sal_Int32/sal_Int64/etc. + * + * NOTE: If you change this, make sure HAVE_FEATURE_JUMBO_SHEETS matches this, as it requires at least 64bit tools::Long. + */ +namespace tools +{ +#if defined _WIN64 +typedef sal_Int64 Long; +typedef sal_uInt64 ULong; +#else +typedef long Long; +typedef unsigned long ULong; +#endif +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/tools/mapunit.hxx b/include/tools/mapunit.hxx new file mode 100644 index 0000000000..881a90713c --- /dev/null +++ b/include/tools/mapunit.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <sal/types.h> + +enum class MapUnit : sal_uInt8 +{ + Map100thMM, Map10thMM, MapMM, MapCM, + Map1000thInch, Map100thInch, Map10thInch, MapInch, + MapPoint, MapTwip, + MapPixel, + MapSysFont, MapAppFont, + MapRelative, + LAST = MapRelative, + LASTENUMDUMMY // used as an error return +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/multisel.hxx b/include/tools/multisel.hxx new file mode 100644 index 0000000000..edb572acb1 --- /dev/null +++ b/include/tools/multisel.hxx @@ -0,0 +1,169 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_MULTISEL_HXX +#define INCLUDED_TOOLS_MULTISEL_HXX + +#include <tools/toolsdllapi.h> +#include <tools/gen.hxx> + +#include <cstddef> +#include <vector> +#include <o3tl/sorted_vector.hxx> + +#define SFX_ENDOFSELECTION (-1) + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC MultiSelection +{ +private: + std::vector< Range > + aSels; // array of SV-selections + Range aTotRange; // total range of indexes + std::size_t nCurSubSel; // index in aSels of current selected index + sal_Int32 nCurIndex; // current selected entry + sal_Int32 nSelCount; // number of selected indexes + bool bCurValid; // are nCurIndex and nCurSubSel valid + + TOOLS_DLLPRIVATE void ImplClear(); + TOOLS_DLLPRIVATE std::size_t ImplFindSubSelection( sal_Int32 nIndex ) const; + TOOLS_DLLPRIVATE void ImplMergeSubSelections( sal_Int32 nPos1, std::size_t nPos2 ); + +public: + MultiSelection(); + MultiSelection( const MultiSelection& rOrig ); + MultiSelection( const Range& rRange ); + ~MultiSelection(); + + MultiSelection& operator= ( const MultiSelection& rOrig ); + + void SelectAll( bool bSelect = true ); + bool Select( sal_Int32 nIndex, bool bSelect = true ); + void Select( const Range& rIndexRange, bool bSelect = true ); + bool IsSelected( sal_Int32 nIndex ) const; + bool IsAllSelected() const + { return nSelCount == aTotRange.Len(); } + sal_Int32 GetSelectCount() const { return nSelCount; } + + void SetTotalRange( const Range& rTotRange ); + void Insert( sal_Int32 nIndex, sal_Int32 nCount = 1 ); + void Remove( sal_Int32 nIndex ); + void Reset(); + + const Range& GetTotalRange() const { return aTotRange; } + sal_Int32 FirstSelected(); + sal_Int32 LastSelected(); + sal_Int32 NextSelected(); + + sal_Int32 GetRangeCount() const { return aSels.size(); } + const Range& GetRange( sal_Int32 nRange ) const { return aSels[nRange]; } +}; + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC StringRangeEnumerator +{ + struct Range + { + sal_Int32 nFirst; + sal_Int32 nLast; + + Range( sal_Int32 i_nFirst, sal_Int32 i_nLast ) : nFirst( i_nFirst ), nLast( i_nLast ) {} + }; + std::vector< StringRangeEnumerator::Range > maSequence; + sal_Int32 mnCount; + sal_Int32 mnMin; + sal_Int32 mnMax; + sal_Int32 mnOffset; + bool mbValidInput; + + bool setRange( std::u16string_view i_rNewRange ); + bool insertRange( sal_Int32 nFirst, sal_Int32 nLast, bool bSequence ); + void insertJoinedRanges( const std::vector< sal_Int32 >& rNumbers ); + bool checkValue( sal_Int32, const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const; +public: + class TOOLS_DLLPUBLIC Iterator + { + const StringRangeEnumerator* pEnumerator; + const o3tl::sorted_vector< sal_Int32 >* pPossibleValues; + sal_Int32 nRangeIndex; + sal_Int32 nCurrent; + + friend class StringRangeEnumerator; + Iterator( const StringRangeEnumerator* i_pEnum, + const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues, + sal_Int32 i_nRange, + sal_Int32 i_nCurrent ) + : pEnumerator( i_pEnum ), pPossibleValues( i_pPossibleValues ) + , nRangeIndex( i_nRange ), nCurrent( i_nCurrent ) {} + + public: + Iterator& operator++(); + sal_Int32 operator*() const { return nCurrent;} + bool operator==(const Iterator&) const; + bool operator!=(const Iterator& i_rComp) const + { return ! (*this == i_rComp); } + }; + + friend class StringRangeEnumerator::Iterator; + + StringRangeEnumerator( std::u16string_view i_rInput, + sal_Int32 i_nMinNumber, + sal_Int32 i_nMaxNumber, + sal_Int32 i_nLogicalOffset = -1 + ); + + sal_Int32 size() const { return mnCount; } + Iterator begin( const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const; + Iterator end( const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const; + + bool hasValue( sal_Int32 nValue, const o3tl::sorted_vector< sal_Int32 >* i_pPossibleValues = nullptr ) const; + + /** + i_rPageRange: the string to be changed into a sequence of numbers + valid format example "5-3,9,9,7-8" ; instead of ',' ';' or ' ' are allowed as well + o_rPageVector: the output sequence of numbers + i_nLogicalOffset: an offset to be applied to each number in the string before inserting it in the resulting sequence + example: a user enters page numbers from 1 to n (since that is logical) + of course usable page numbers in code would start from 0 and end at n-1 + so the logical offset would be -1 + i_nMinNumber: the minimum allowed number + i_nMaxNumber: the maximum allowed number + + @returns: true if the input string was valid, o_rPageVector will contain the resulting sequence + false if the input string was invalid, o_rPageVector will contain + the sequence that parser is able to extract + + behavior: + - only non-negative sequence numbers are allowed + - only non-negative values in the input string are allowed + - the string "-3" means the sequence i_nMinNumber to 3 + - the string "3-" means the sequence 3 to i_nMaxNumber + - the string "-" means the sequence i_nMinNumber to i_nMaxNumber + - single number that doesn't fit in [i_nMinNumber,i_nMaxNumber] will be ignored + - range that doesn't fit in [i_nMinNumber,i_nMaxNumber] will be adjusted + */ + static bool getRangesFromString( std::u16string_view i_rPageRange, + std::vector< sal_Int32 >& o_rPageVector, + sal_Int32 i_nMinNumber, + sal_Int32 i_nMaxNumber, + sal_Int32 i_nLogicalOffset = -1, + o3tl::sorted_vector< sal_Int32 > const * i_pPossibleValues = nullptr + ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/pathutils.hxx b/include/tools/pathutils.hxx new file mode 100644 index 0000000000..045ec4b96b --- /dev/null +++ b/include/tools/pathutils.hxx @@ -0,0 +1,72 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_PATHUTILS_HXX +#define INCLUDED_TOOLS_PATHUTILS_HXX + +#include <sal/config.h> + +#if defined(_WIN32) +#include <cstddef> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +// The compiled code is not part of the tl dynamic library, but is delivered as +// pathutils-obj and pathutils-slo objects (it is linked into special +// executables and dynamic libraries that do not link against OOo libraries): +namespace tools +{ +/** Determine the filename part of a path. + @param path + A non-NULL pointer to a null-terminated path. + @return + A pointer to the trailing filename part of the given path. +*/ +WCHAR* filename(WCHAR* path); + +/** Concatenate two paths. + + Either the first path is empty and the second path is an absolute path. Or + the first path is an absolute path that ends in a backslash and the second + path is a relative path. In the latter case, to avoid paths that grow too + long, leading .. segments of the second path are removed together with + trailing segments from the first path. This should not cause problems as long + as there are no symbolic links on Windows (as with symbolic links, x\y\.. and + x might denote different directories). + + @param path + An output parameter taking the resulting path; must point at a valid + range of memory of size at least MAX_PATH. If NULL is returned, the + content is unspecified. + @param frontBegin, frontEnd + Forms a valid range [frontBegin .. frontEnd) of less than MAX_PATH size. + @param backBegin, backLength + Forms a valid range [backBegin .. backBegin + backLength) of less than + MAX_PATH size. + @return + A pointer to the terminating null character of the concatenation, or NULL + if a failure occurred. +*/ +WCHAR* buildPath(WCHAR* path, WCHAR const* frontBegin, WCHAR const* frontEnd, + WCHAR const* backBegin, std::size_t backLength); +} + +#endif +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/poly.hxx b/include/tools/poly.hxx new file mode 100644 index 0000000000..36aea7a11a --- /dev/null +++ b/include/tools/poly.hxx @@ -0,0 +1,317 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_POLY_HXX +#define INCLUDED_TOOLS_POLY_HXX + +#include <rtl/ustring.hxx> +#include <tools/toolsdllapi.h> +#include <tools/gen.hxx> +#include <tools/degree.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <o3tl/cow_wrapper.hxx> + +#include <vector> + +#define POLY_APPEND (0xFFFF) +#define POLYPOLY_APPEND (0xFFFF) + +enum class PolyOptimizeFlags { + NONE = 0x0000, + CLOSE = 0x0001, + NO_SAME = 0x0002, + EDGES = 0x0004, +}; +namespace o3tl +{ + template<> struct typed_flags<PolyOptimizeFlags> : is_typed_flags<PolyOptimizeFlags, 0x0007> {}; +} + +enum class PolyStyle +{ + Arc = 1, + Pie = 2, + Chord = 3 +}; + +enum class PolyFlags : sal_uInt8 +{ + Normal, // start-/endpoint of a curve or a line + Smooth, // smooth transition between curves + Control, // control handles of a Bezier curve + Symmetric // smooth and symmetrical transition between curves +}; + +class SvStream; +class ImplPolygon; +struct ImplPolyPolygon; + +namespace basegfx +{ + class B2DPolygon; + class B2DPolyPolygon; +} + +namespace tools { + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Polygon +{ +public: + typedef o3tl::cow_wrapper<ImplPolygon> ImplType; +private: + ImplType mpImplPolygon; + +public: + static void ImplReduceEdges( tools::Polygon& rPoly, const double& rArea, sal_uInt16 nPercent ); + void ImplRead( SvStream& rIStream ); + void ImplWrite( SvStream& rOStream ) const; + +public: + Polygon(); + explicit Polygon( sal_uInt16 nSize ); + Polygon( sal_uInt16 nPoints, const Point* pPtAry, + const PolyFlags* pFlagAry = nullptr ); + explicit Polygon( const tools::Rectangle& rRect ); + Polygon( const tools::Rectangle& rRect, + sal_uInt32 nHorzRound, sal_uInt32 nVertRound ); + Polygon( const Point& rCenter, + tools::Long nRadX, tools::Long nRadY ); + Polygon( const tools::Rectangle& rBound, + const Point& rStart, const Point& rEnd, + PolyStyle ePolyStyle = PolyStyle::Arc, + const bool bClockWiseArcDirection = false); + Polygon( const Point& rBezPt1, const Point& rCtrlPt1, + const Point& rBezPt2, const Point& rCtrlPt2, + sal_uInt16 nPoints ); + + Polygon( const tools::Polygon& rPoly ); + Polygon( tools::Polygon&& rPoly) noexcept; + ~Polygon(); + + void SetPoint( const Point& rPt, sal_uInt16 nPos ); + const Point& GetPoint( sal_uInt16 nPos ) const; + + void SetFlags( sal_uInt16 nPos, PolyFlags eFlags ); + PolyFlags GetFlags( sal_uInt16 nPos ) const; + bool HasFlags() const; + + bool IsRect() const; + + void SetSize( sal_uInt16 nNewSize ); + sal_uInt16 GetSize() const; + sal_uInt16 size() const { return GetSize(); } //for vector compatibility + + void Clear(); + + tools::Rectangle GetBoundRect() const; + bool Contains( const Point& rPt ) const; + double CalcDistance( sal_uInt16 nPt1, sal_uInt16 nPt2 ) const; + void Clip( const tools::Rectangle& rRect ); + void Optimize( PolyOptimizeFlags nOptimizeFlags ); + + /** Adaptive subdivision of polygons with curves + + This method adaptively subdivides bezier arcs within the + polygon to straight line segments and returns the resulting + polygon. + + @param rResult + The resulting subdivided polygon + + @param d + This parameter controls the amount of subdivision. The + original curve is guaranteed to not differ by more than this + amount per bezier segment from the subdivided + lines. Concretely, if the polygon is in device coordinates and + d equals 1.0, then the difference between the subdivided and + the original polygon is guaranteed to be smaller than one + pixel. + */ + void AdaptiveSubdivide( tools::Polygon& rResult, const double d = 1.0 ) const; + static Polygon SubdivideBezier( const Polygon& rPoly ); + + void Move( tools::Long nHorzMove, tools::Long nVertMove ); + void Translate( const Point& rTrans ); + void Scale( double fScaleX, double fScaleY ); + void Rotate( const Point& rCenter, double fSin, double fCos ); + void Rotate( const Point& rCenter, Degree10 nAngle10 ); + + void Insert( sal_uInt16 nPos, const Point& rPt ); + void Insert( sal_uInt16 nPos, const tools::Polygon& rPoly ); + + const Point& operator[]( sal_uInt16 nPos ) const { return GetPoint( nPos ); } + Point& operator[]( sal_uInt16 nPos ); + + tools::Polygon& operator=( const tools::Polygon& rPoly ); + tools::Polygon& operator=( tools::Polygon&& rPoly ) noexcept; + bool operator==( const tools::Polygon& rPoly ) const; + bool operator!=( const tools::Polygon& rPoly ) const + { return !(Polygon::operator==( rPoly )); } + bool IsEqual( const tools::Polygon& rPoly ) const; + + // streaming a Polygon does ignore PolyFlags, so use the Write Or Read + // method to take care of PolyFlags + TOOLS_DLLPUBLIC friend SvStream& ReadPolygon( SvStream& rIStream, tools::Polygon& rPoly ); + TOOLS_DLLPUBLIC friend SvStream& WritePolygon( SvStream& rOStream, const tools::Polygon& rPoly ); + + void Read( SvStream& rIStream ); + void Write( SvStream& rOStream ) const; + + Point * GetPointAry(); + const Point* GetConstPointAry() const; + const PolyFlags* GetConstFlagAry() const; + + // convert to ::basegfx::B2DPolygon and return + ::basegfx::B2DPolygon getB2DPolygon() const; + + // constructor to convert from ::basegfx::B2DPolygon + // #i76339# made explicit + explicit Polygon(const ::basegfx::B2DPolygon& rPolygon); +}; + + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC PolyPolygon +{ +private: + o3tl::cow_wrapper<ImplPolyPolygon> mpImplPolyPolygon; + + enum class PolyClipOp { + INTERSECT, + UNION + }; + TOOLS_DLLPRIVATE void ImplDoOperation( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult, PolyClipOp nOperation ) const; + +public: + explicit PolyPolygon( sal_uInt16 nInitSize = 16 ); + explicit PolyPolygon( const tools::Polygon& rPoly ); + explicit PolyPolygon( const tools::Rectangle& ); + PolyPolygon( const tools::PolyPolygon& rPolyPoly ); + PolyPolygon( tools::PolyPolygon&& rPolyPoly ) noexcept; + ~PolyPolygon(); + + void Insert( const tools::Polygon& rPoly, sal_uInt16 nPos = POLYPOLY_APPEND ); + void Remove( sal_uInt16 nPos ); + void Replace( const Polygon& rPoly, sal_uInt16 nPos ); + const tools::Polygon& GetObject( sal_uInt16 nPos ) const; + + bool IsRect() const; + + void Clear(); + + sal_uInt16 Count() const; + tools::Rectangle GetBoundRect() const; + void Clip( const tools::Rectangle& rRect ); + void Optimize( PolyOptimizeFlags nOptimizeFlags ); + + /** Adaptive subdivision of polygons with curves + + This method adaptively subdivides bezier arcs within the + polygon to straight line segments and returns the resulting + polygon. + + @param rResult + The resulting subdivided polygon + + If the polygon is in device coordinates, then the difference between the subdivided and + the original polygon is guaranteed to be smaller than one + pixel. + */ + void AdaptiveSubdivide( tools::PolyPolygon& rResult ) const; + static tools::PolyPolygon SubdivideBezier( const tools::PolyPolygon& rPolyPoly ); + + void GetIntersection( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const; + void GetUnion( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rResult ) const; + + void Move( tools::Long nHorzMove, tools::Long nVertMove ); + void Translate( const Point& rTrans ); + void Scale( double fScaleX, double fScaleY ); + void Rotate( const Point& rCenter, double fSin, double fCos ); + void Rotate( const Point& rCenter, Degree10 nAngle10 ); + + const tools::Polygon& operator[]( sal_uInt16 nPos ) const { return GetObject( nPos ); } + tools::Polygon& operator[]( sal_uInt16 nPos ); + + tools::PolyPolygon& operator=( const tools::PolyPolygon& rPolyPoly ); + tools::PolyPolygon& operator=( tools::PolyPolygon&& rPolyPoly ) noexcept; + bool operator==( const tools::PolyPolygon& rPolyPoly ) const; + bool operator!=( const tools::PolyPolygon& rPolyPoly ) const + { return !(PolyPolygon::operator==( rPolyPoly )); } + + TOOLS_DLLPUBLIC friend SvStream& ReadPolyPolygon( SvStream& rIStream, tools::PolyPolygon& rPolyPoly ); + TOOLS_DLLPUBLIC friend SvStream& WritePolyPolygon( SvStream& rOStream, const tools::PolyPolygon& rPolyPoly ); + + void Read( SvStream& rIStream ); + void Write( SvStream& rOStream ) const; + + // convert to ::basegfx::B2DPolyPolygon and return + ::basegfx::B2DPolyPolygon getB2DPolyPolygon() const; + + // constructor to convert from ::basegfx::B2DPolyPolygon + // #i76339# made explicit + explicit PolyPolygon(const ::basegfx::B2DPolyPolygon& rPolyPolygon); +}; + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const Polygon& poly ) +{ + stream << "<" << poly.GetSize() << ":"; + for (sal_uInt16 i = 0; i < poly.GetSize(); i++) + { + if (i > 0) + stream << "--"; + stream << poly.GetPoint(i); + + OUString aFlag; + if (poly.GetFlags(i) == PolyFlags::Normal) + aFlag = "Normal"; + else if (poly.GetFlags(i) == PolyFlags::Smooth) + aFlag = "Smooth"; + else if (poly.GetFlags(i) == PolyFlags::Control) + aFlag = "Control"; + else if (poly.GetFlags(i) == PolyFlags::Symmetric) + aFlag = "Symmetric"; + + stream << ";f=" << aFlag; + } + stream << ">"; + return stream; +} + +template< typename charT, typename traits > +inline std::basic_ostream<charT, traits> & operator <<( + std::basic_ostream<charT, traits> & stream, const PolyPolygon& poly ) +{ + stream << "[" << poly.Count() << ":"; + for (sal_uInt16 i = 0; i < poly.Count(); i++) + { + if (i > 0) + stream << ","; + stream << poly.GetObject(i); + } + stream << "]"; + return stream; +} + +} /* namespace tools */ + +typedef std::vector< tools::PolyPolygon > PolyPolyVector; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/ref.hxx b/include/tools/ref.hxx new file mode 100644 index 0000000000..3f245bf08e --- /dev/null +++ b/include/tools/ref.hxx @@ -0,0 +1,234 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_REF_HXX +#define INCLUDED_TOOLS_REF_HXX + +#include <sal/config.h> +#include <cassert> +#include <tools/toolsdllapi.h> +#include <utility> + +/** + This implements similar functionality to boost::intrusive_ptr +*/ + +namespace tools { + +/** T must be a class that extends SvRefBase */ +template<typename T> class SAL_DLLPUBLIC_RTTI SvRef final { +public: + SvRef(): pObj(nullptr) {} + + SvRef(SvRef&& rObj) noexcept + { + pObj = rObj.pObj; + rObj.pObj = nullptr; + } + + SvRef(SvRef const & rObj): pObj(rObj.pObj) + { + if (pObj != nullptr) pObj->AddNextRef(); + } + + SvRef(T * pObjP): pObj(pObjP) + { + if (pObj != nullptr) pObj->AddFirstRef(); + } + + ~SvRef() + { + if (pObj != nullptr) pObj->ReleaseRef(); + } + + void clear() + { + if (pObj != nullptr) { + T * pRefObj = pObj; + pObj = nullptr; + pRefObj->ReleaseRef(); + } + } + + SvRef & operator =(SvRef const & rObj) + { + if (rObj.pObj != nullptr) { + rObj.pObj->AddNextRef(); + } + T * pRefObj = pObj; + pObj = rObj.pObj; + if (pRefObj != nullptr) { + pRefObj->ReleaseRef(); + } + return *this; + } + + SvRef & operator =(SvRef && rObj) + { + if (pObj != nullptr) { + pObj->ReleaseRef(); + } + pObj = rObj.pObj; + rObj.pObj = nullptr; + return *this; + } + + bool is() const { return pObj != nullptr; } + + explicit operator bool() const { return is(); } + + T * get() const { return pObj; } + + T * operator ->() const { assert(pObj != nullptr); return pObj; } + + T & operator *() const { assert(pObj != nullptr); return *pObj; } + + bool operator ==(const SvRef<T> &rhs) const { return pObj == rhs.pObj; } + bool operator !=(const SvRef<T> &rhs) const { return !(*this == rhs); } + +private: + T * pObj; +}; + +/** + * This implements similar functionality to std::make_shared. + */ +template<typename T, typename... Args> +SvRef<T> make_ref(Args&& ... args) +{ + return SvRef<T>(new T(std::forward<Args>(args)...)); +} + +} + +/** Classes that want to be referenced-counted via SvRef<T>, should extend this base class */ +class TOOLS_DLLPUBLIC SvRefBase +{ + // work around a clang 3.5 optimization bug: if the bNoDelete is *first* + // it mis-compiles "if (--nRefCount == 0)" and never deletes any object + unsigned int nRefCount : 31; + // the only reason this is not bool is because MSVC cannot handle mixed type bitfields + unsigned int bNoDelete : 1; + +protected: + virtual ~SvRefBase() COVERITY_NOEXCEPT_FALSE; + +public: + SvRefBase() : nRefCount(0), bNoDelete(1) {} + SvRefBase(const SvRefBase &) : nRefCount(0), bNoDelete(1) {} + + SvRefBase & operator=(const SvRefBase &) { return *this; } + + void RestoreNoDelete() + { bNoDelete = 1; } + + void AddNextRef() + { + assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" ); + ++nRefCount; + } + + void AddFirstRef() + { + assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" ); + if( bNoDelete ) + bNoDelete = 0; + ++nRefCount; + } + + void ReleaseRef() + { + assert( nRefCount >= 1); + if( --nRefCount == 0 && !bNoDelete) + { + // I'm not sure about the original purpose of this line, but right now + // it serves the purpose that anything that attempts to do an AddRef() + // after an object is deleted will trip an assert. + nRefCount = 1 << 30; + delete this; + } + } + + unsigned int GetRefCount() const + { return nRefCount; } +}; + +template<typename T> +class SvCompatWeakBase; + +/** SvCompatWeakHdl acts as an intermediary between SvCompatWeakRef<T> and T. +*/ +template<typename T> +class SvCompatWeakHdl final : public SvRefBase +{ + friend class SvCompatWeakBase<T>; + T* _pObj; + + SvCompatWeakHdl( T* pObj ) : _pObj( pObj ) {} + +public: + void ResetWeakBase( ) { _pObj = nullptr; } + T* GetObj() { return _pObj; } +}; + +/** We only have one place that extends this, in include/sfx2/frame.hxx, class SfxFrame. + Its function is to notify the SvCompatWeakHdl when an SfxFrame object is deleted. +*/ +template<typename T> +class SvCompatWeakBase +{ + tools::SvRef< SvCompatWeakHdl<T> > _xHdl; + +public: + /** Does not use initializer due to compiler warnings, + because the lifetime of the _xHdl object can exceed the lifetime of this class. + */ + SvCompatWeakBase( T* pObj ) { _xHdl = new SvCompatWeakHdl<T>( pObj ); } + + ~SvCompatWeakBase() { _xHdl->ResetWeakBase(); } + + SvCompatWeakHdl<T>* GetHdl() { return _xHdl.get(); } +}; + +/** We only have one weak reference in LO, in include/sfx2/frame.hxx, class SfxFrameWeak. +*/ +template<typename T> +class SAL_WARN_UNUSED SvCompatWeakRef +{ + tools::SvRef< SvCompatWeakHdl<T> > _xHdl; +public: + SvCompatWeakRef( ) {} + SvCompatWeakRef( T* pObj ) + { if( pObj ) _xHdl = pObj->GetHdl(); } +#if defined(__COVERITY__) + ~SvCompatWeakRef() COVERITY_NOEXCEPT_FALSE {} +#endif + SvCompatWeakRef& operator = ( T * pObj ) + { _xHdl = pObj ? pObj->GetHdl() : nullptr; return *this; } + bool is() const + { return _xHdl.is() && _xHdl->GetObj(); } + explicit operator bool() const { return is(); } + T* operator -> () const + { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } + operator T* () const + { return _xHdl.is() ? _xHdl->GetObj() : nullptr; } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/resary.hxx b/include/tools/resary.hxx new file mode 100644 index 0000000000..9573a9affd --- /dev/null +++ b/include/tools/resary.hxx @@ -0,0 +1,26 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_RESARY_HXX +#define INCLUDED_TOOLS_RESARY_HXX + +#define RESARRAY_INDEX_NOTFOUND (0xffffffff) + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/simd.hxx b/include/tools/simd.hxx new file mode 100644 index 0000000000..bdfdb89282 --- /dev/null +++ b/include/tools/simd.hxx @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_TOOLS_SIMD_HXX +#define INCLUDED_TOOLS_SIMD_HXX + +namespace simd +{ +template <typename T, unsigned int N> inline bool isAligned(const T* pointer) +{ + return 0 == (uintptr_t(pointer) % N); +} + +template <typename T> inline T roundDown(T value, unsigned int multiple) +{ + return value & ~(multiple - 1); +} + +} // end namespace simd + +#endif // INCLUDED_TOOLS_SIMD_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/simdsupport.hxx b/include/tools/simdsupport.hxx new file mode 100644 index 0000000000..fa8923bb09 --- /dev/null +++ b/include/tools/simdsupport.hxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +// IMPORTANT: Having CPU-specific routines turned out to be a maintenance +// problem, because of various problems such as compilers moving CPU-specific +// code out of #ifdef code into static initialization or our code using C++ +// features that caused the compiler to emit code that used CPU-specific +// instructions (even cpuid.hxx isn't safe, see the comment there). +// The only safe usage is using CPU-specific code that's always available, +// such as SSE2-specific code for x86_64. Do not use for anything else +// unless you really know what you are doing (and you check git history +// to learn from past problems). + +// Determine the compiler support for SIMD compiler intrinsics. +// This changes from one compiled unit to the other, depending if +// the support has been detected and if the compiled unit contains +// code using intrinsics or not. So we have to (re)set them again +// every time this file has been included. + +// In other words... DO NOT ADD "#pragma once" here + +#undef LO_SSE2_AVAILABLE +#undef LO_SSSE3_AVAILABLE +#undef LO_AVX_AVAILABLE +#undef LO_AVX2_AVAILABLE +#undef LO_AVX512F_AVAILABLE + +#if defined(_MSC_VER) // VISUAL STUDIO COMPILER + +// With MSVC using -arch is in fact not necessary for being able +// to use CPU intrinsics, code using AVX512F intrinsics will compile +// even if compiled with -arch:AVX, the -arch option really only affects +// instructions generated for C/C++ code. +#if defined(_M_X64) || defined(_M_X86) +// As such, if we're building for X86 or X64, support for these is always available +// with MSVC2019+. +#define LO_SSE2_AVAILABLE +#define LO_SSSE3_AVAILABLE +#define LO_AVX_AVAILABLE +#define LO_AVX2_AVAILABLE +#define LO_AVX512F_AVAILABLE +#include <intrin.h> +#include <immintrin.h> +#endif + +#else // compiler Clang and GCC + +#if defined(__SSE2__) || defined(__x86_64__) // SSE2 is required for X64 +#define LO_SSE2_AVAILABLE +#include <emmintrin.h> +#endif // defined(__SSE2__) + +#if defined(__SSSE3__) +#define LO_SSSE3_AVAILABLE +#include <tmmintrin.h> +#endif // defined(__SSSE3__) + +#if defined(__AVX__) +#define LO_AVX_AVAILABLE +#include <immintrin.h> +#endif // defined(__AVX__) + +#if defined(__AVX2__) +#define LO_AVX2_AVAILABLE +#include <immintrin.h> +#endif // defined(__AVX2__) + +#if defined(__AVX512F__) +#define LO_AVX512F_AVAILABLE +#include <immintrin.h> +#else +#endif // defined(__AVX512F__) + +#endif // end compiler Clang and GCC + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/solar.h b/include/tools/solar.h new file mode 100644 index 0000000000..ae7c5288c4 --- /dev/null +++ b/include/tools/solar.h @@ -0,0 +1,119 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_TOOLS_SOLAR_H +#define INCLUDED_TOOLS_SOLAR_H + +#include <sal/types.h> +#include <osl/endian.h> + +/** Intermediate type to solve type clash with Windows headers. + Should be removed as soon as all code parts have been reviewed + and the correct type is known. Most of the times ULONG is meant + to be a 32-Bit unsigned integer type as sal_uInt32 is often + used for data exchange or for similar method args. */ +typedef sal_uIntPtr sal_uLong; /* Replaces type ULONG */ + +// misc. macros to leverage platform and compiler differences + +// solar binary types + +/* Solar (portable) Binary (exchange) Type; OSI 6 subset + always little endian; + not necessarily aligned */ + +typedef sal_uInt8 SVBT16[2]; +typedef sal_uInt8 SVBT32[4]; +typedef sal_uInt8 SVBT64[8]; + +#ifdef __cplusplus + +inline sal_uInt16 SVBT16ToUInt16( const SVBT16 p ) { return static_cast<sal_uInt16> + (static_cast<sal_uInt16>(p[0]) + + (static_cast<sal_uInt16>(p[1]) << 8)); } +inline sal_Int16 SVBT16ToInt16( const SVBT16 p ) { return sal_Int16(SVBT16ToUInt16(p)); } +inline sal_uInt32 SVBT32ToUInt32 ( const SVBT32 p ) { return static_cast<sal_uInt32> + (static_cast<sal_uInt32>(p[0]) + + (static_cast<sal_uInt32>(p[1]) << 8) + + (static_cast<sal_uInt32>(p[2]) << 16) + + (static_cast<sal_uInt32>(p[3]) << 24)); } +#if defined OSL_LITENDIAN +inline double SVBT64ToDouble( const SVBT64 p ) +{ + double n; + reinterpret_cast<sal_uInt8*>(&n)[0] = p[0]; + reinterpret_cast<sal_uInt8*>(&n)[1] = p[1]; + reinterpret_cast<sal_uInt8*>(&n)[2] = p[2]; + reinterpret_cast<sal_uInt8*>(&n)[3] = p[3]; + reinterpret_cast<sal_uInt8*>(&n)[4] = p[4]; + reinterpret_cast<sal_uInt8*>(&n)[5] = p[5]; + reinterpret_cast<sal_uInt8*>(&n)[6] = p[6]; + reinterpret_cast<sal_uInt8*>(&n)[7] = p[7]; + return n; +} +#else +inline double SVBT64ToDouble( const SVBT64 p ) { double n; + reinterpret_cast<sal_uInt8*>(&n)[0] = p[7]; + reinterpret_cast<sal_uInt8*>(&n)[1] = p[6]; + reinterpret_cast<sal_uInt8*>(&n)[2] = p[5]; + reinterpret_cast<sal_uInt8*>(&n)[3] = p[4]; + reinterpret_cast<sal_uInt8*>(&n)[4] = p[3]; + reinterpret_cast<sal_uInt8*>(&n)[5] = p[2]; + reinterpret_cast<sal_uInt8*>(&n)[6] = p[1]; + reinterpret_cast<sal_uInt8*>(&n)[7] = p[0]; + return n; } +#endif + +inline void ShortToSVBT16( sal_uInt16 n, SVBT16 p ) +{ + p[0] = static_cast<sal_uInt8>(n); + p[1] = static_cast<sal_uInt8>(n >> 8); +} +inline void UInt32ToSVBT32 ( sal_uInt32 n, SVBT32 p ) +{ + p[0] = static_cast<sal_uInt8>(n); + p[1] = static_cast<sal_uInt8>(n >> 8); + p[2] = static_cast<sal_uInt8>(n >> 16); + p[3] = static_cast<sal_uInt8>(n >> 24); +} +inline void Int32ToSVBT32 ( sal_Int32 n, SVBT32 p ) { UInt32ToSVBT32(sal_uInt32(n), p); } +#if defined OSL_LITENDIAN +inline void DoubleToSVBT64( double n, SVBT64 p ) { p[0] = reinterpret_cast<sal_uInt8*>(&n)[0]; + p[1] = reinterpret_cast<sal_uInt8*>(&n)[1]; + p[2] = reinterpret_cast<sal_uInt8*>(&n)[2]; + p[3] = reinterpret_cast<sal_uInt8*>(&n)[3]; + p[4] = reinterpret_cast<sal_uInt8*>(&n)[4]; + p[5] = reinterpret_cast<sal_uInt8*>(&n)[5]; + p[6] = reinterpret_cast<sal_uInt8*>(&n)[6]; + p[7] = reinterpret_cast<sal_uInt8*>(&n)[7]; } +#else +inline void DoubleToSVBT64( double n, SVBT64 p ) { p[0] = reinterpret_cast<sal_uInt8*>(&n)[7]; + p[1] = reinterpret_cast<sal_uInt8*>(&n)[6]; + p[2] = reinterpret_cast<sal_uInt8*>(&n)[5]; + p[3] = reinterpret_cast<sal_uInt8*>(&n)[4]; + p[4] = reinterpret_cast<sal_uInt8*>(&n)[3]; + p[5] = reinterpret_cast<sal_uInt8*>(&n)[2]; + p[6] = reinterpret_cast<sal_uInt8*>(&n)[1]; + p[7] = reinterpret_cast<sal_uInt8*>(&n)[0]; } +#endif +#endif + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/stream.hxx b/include/tools/stream.hxx new file mode 100644 index 0000000000..d3e741bbd0 --- /dev/null +++ b/include/tools/stream.hxx @@ -0,0 +1,685 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <config_options.h> +#include <tools/toolsdllapi.h> +#include <tools/lineend.hxx> +#include <tools/long.hxx> +#include <tools/ref.hxx> +#include <comphelper/errcode.hxx> +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <memory> +#include <string_view> + +class StreamData; + +inline rtl_TextEncoding GetStoreCharSet( rtl_TextEncoding eEncoding ) +{ + if ( eEncoding == RTL_TEXTENCODING_ISO_8859_1 ) + return RTL_TEXTENCODING_MS_1252; + else + return eEncoding; +} + +// StreamTypes + +// read, write, create,... options +enum class StreamMode { + NONE = 0x0000, + READ = 0x0001, ///< allow read accesses + WRITE = 0x0002, ///< allow write accesses +// file i/o + NOCREATE = 0x0004, ///< 1 == Don't create file + TRUNC = 0x0008, ///< Truncate _existing_ file to zero length + COPY_ON_SYMLINK = 0x0010, ///< copy-on-write for symlinks (Unix-only) + TEMPORARY = 0x0020, ///< temporary file attribute (Windows-only) + DELETE_ON_CLOSE = 0x0040, ///< only for temporary files (Windows-only) +// sharing options + SHARE_DENYNONE = 0x0100, + SHARE_DENYREAD = 0x0200, // overrides denynone + SHARE_DENYWRITE = 0x0400, // overrides denynone + SHARE_DENYALL = 0x0800, // overrides denyread,write,none +// masks + READWRITE = READ | WRITE, + STD_READ = READ | SHARE_DENYNONE | NOCREATE, + STD_WRITE = WRITE | SHARE_DENYALL, + STD_READWRITE = READWRITE | SHARE_DENYALL +}; +namespace o3tl +{ + template<> struct typed_flags<StreamMode> : is_typed_flags<StreamMode, 0x0f7f> {}; +} + +#define STREAM_SEEK_TO_BEGIN 0L +#define STREAM_SEEK_TO_END SAL_MAX_UINT64 + +enum class SvStreamEndian { BIG, LITTLE }; + +enum class SvStreamCompressFlags { + NONE = 0x0000, + ZBITMAP = 0x0001, + NATIVE = 0x0010, +}; +namespace o3tl +{ + template<> struct typed_flags<SvStreamCompressFlags> : is_typed_flags<SvStreamCompressFlags, 0x0011> {}; +} + +class SvStream; + +typedef SvStream& (*SvStrPtr)( SvStream& ); + +inline SvStream& operator<<( SvStream& rStr, SvStrPtr f ); + +// SvLockBytes + +struct SvLockBytesStat +{ + std::size_t nSize; + + SvLockBytesStat() : nSize(0) {} +}; + +class TOOLS_DLLPUBLIC SvLockBytes: public SvRefBase +{ + SvStream * m_pStream; + bool m_bOwner; + bool m_bSync; + +protected: + void close(); + +public: + + SvLockBytes() : m_pStream(nullptr), m_bOwner(false), m_bSync(false) {} + + SvLockBytes(SvStream * pTheStream, bool bTheOwner = false) : + m_pStream(pTheStream), m_bOwner(bTheOwner), m_bSync(false) {} + + virtual ~SvLockBytes() override { close(); } + + const SvStream * GetStream() const { return m_pStream; } + + void SetSynchronMode(bool bTheSync = true) { m_bSync = bTheSync; } + bool IsSynchronMode() const { return m_bSync; } + + virtual ErrCode ReadAt(sal_uInt64 nPos, void * pBuffer, std::size_t nCount, + std::size_t * pRead) const; + virtual ErrCode WriteAt(sal_uInt64 nPos, const void * pBuffer, std::size_t nCount, + std::size_t * pWritten); + + virtual ErrCode Flush() const; + + virtual ErrCode SetSize(sal_uInt64 nSize); + + virtual ErrCode Stat(SvLockBytesStat * pStat) const; +}; + +typedef tools::SvRef<SvLockBytes> SvLockBytesRef; + +// SvStream + +class TOOLS_DLLPUBLIC SvStream +{ +private: + // LockBytes Interface + SvLockBytesRef m_xLockBytes; ///< Default implementation + sal_uInt64 m_nActPos; + + // buffer management + std::unique_ptr<sal_uInt8[]> + m_pRWBuf; ///< Points to read/write buffer + sal_uInt8* m_pBufPos; ///< m_pRWBuf + m_nBufActualPos + sal_uInt16 m_nBufSize; ///< Allocated size of buffer + sal_uInt16 m_nBufActualLen; ///< Length of used segment of buffer + ///< = m_nBufSize, if EOF did not occur + sal_uInt16 m_nBufActualPos; ///< current position in buffer (0..m_nBufSize-1) + sal_uInt16 m_nBufFree; ///< number of free slots in buffer to IO of type eIOMode + bool m_isIoRead; + bool m_isIoWrite; + + // Error codes, conversion, compression, ... + bool m_isDirty; ///< true: Stream != buffer content + bool m_isSwap; + bool m_isEof; + ErrCode m_nError; + SvStreamCompressFlags m_nCompressMode; + LineEnd m_eLineDelimiter; + rtl_TextEncoding m_eStreamCharSet; + + // Encryption + OString m_aCryptMaskKey;// aCryptMaskKey.getLength != 0 -> Encryption used + unsigned char m_nCryptMask; + + // Userdata + sal_Int32 m_nVersion; // for external use + + SvStream ( const SvStream& rStream ) = delete; + SvStream& operator=( const SvStream& rStream ) = delete; + +protected: + sal_uInt64 m_nBufFilePos; ///< File position of pBuf[0] + StreamMode m_eStreamMode; + bool m_isWritable; + + virtual std::size_t GetData( void* pData, std::size_t nSize ); + virtual std::size_t PutData( const void* pData, std::size_t nSize ); + virtual sal_uInt64 SeekPos( sal_uInt64 nPos ); + virtual void FlushData(); + virtual void SetSize(sal_uInt64 nSize); + + SAL_DLLPRIVATE void ClearError(); + SAL_DLLPRIVATE void ClearBuffer(); + + // encrypt and write in blocks + SAL_DLLPRIVATE std::size_t CryptAndWriteBuffer( const void* pStart, std::size_t nLen ); + SAL_DLLPRIVATE void EncryptBuffer( void* pStart, std::size_t nLen ) const; + +public: + SvStream(); + SvStream( SvLockBytes *pLockBytes); + virtual ~SvStream(); + + SvLockBytes* GetLockBytes() const { return m_xLockBytes.get(); } + + ErrCode GetError() const { return m_nError.IgnoreWarning(); } + ErrCode const & GetErrorCode() const { return m_nError; } + void SetError( ErrCode nErrorCode ); + virtual void ResetError(); + + void SetEndian( SvStreamEndian SvStreamEndian ); + SvStreamEndian GetEndian() const; + /// returns status of endian swap flag + bool IsEndianSwap() const { return m_isSwap; } + + void SetCompressMode( SvStreamCompressFlags nNewMode ) + { m_nCompressMode = nNewMode; } + SvStreamCompressFlags GetCompressMode() const { return m_nCompressMode; } + + void SetCryptMaskKey(const OString& rCryptMaskKey); + + void SetStreamCharSet( rtl_TextEncoding eCharSet ) + { m_eStreamCharSet = eCharSet; } + rtl_TextEncoding GetStreamCharSet() const { return m_eStreamCharSet; } + + void SetLineDelimiter( LineEnd eLineEnd ) + { m_eLineDelimiter = eLineEnd; } + LineEnd GetLineDelimiter() const { return m_eLineDelimiter; } + + SvStream& ReadUInt16( sal_uInt16& rUInt16 ); + SvStream& ReadUInt32( sal_uInt32& rUInt32 ); + SvStream& ReadUInt64( sal_uInt64& rUInt64 ); + SvStream& ReadInt16( sal_Int16& rInt16 ); + SvStream& ReadInt32( sal_Int32& rInt32 ); + SvStream& ReadInt64(sal_Int64 & rInt64); + SvStream& ReadSChar( signed char& rChar ); + SvStream& ReadChar( char& rChar ); + SvStream& ReadUChar( unsigned char& rChar ); + SvStream& ReadUtf16( sal_Unicode& rUtf16 ); + SvStream& ReadCharAsBool( bool& rBool ); + SvStream& ReadFloat( float& rFloat ); + SvStream& ReadDouble( double& rDouble ); + SvStream& ReadStream( SvStream& rStream ); + + SvStream& WriteUInt16( sal_uInt16 nUInt16 ); + SvStream& WriteUInt32( sal_uInt32 nUInt32 ); + SvStream& WriteUInt64( sal_uInt64 nuInt64 ); + SvStream& WriteInt16( sal_Int16 nInt16 ); + SvStream& WriteInt32( sal_Int32 nInt32 ); + SvStream& WriteInt64( sal_Int64 nInt64 ); + SvStream& WriteUInt8( sal_uInt8 nuInt8 ); + SvStream& WriteUnicode( sal_Unicode ); + SvStream& WriteOString(std::string_view rStr) + { WriteBytes(rStr.data(), rStr.size()); return *this; } + SvStream& WriteStream( SvStream& rStream ); + sal_uInt64 WriteStream( SvStream& rStream, sal_uInt64 nSize ); + + SvStream& WriteBool( bool b ) + { return WriteUChar(static_cast<unsigned char>(b)); } + SvStream& WriteSChar( signed char nChar ); + SvStream& WriteChar( char nChar ); + SvStream& WriteUChar( unsigned char nChar ); + SvStream& WriteFloat( float nFloat ); + SvStream& WriteDouble( const double& rDouble ); + + template <typename N> + SvStream& WriteNumberAsString( N n ) { return WriteOString(OString::number(n)); } + + std::size_t ReadBytes( void* pData, std::size_t nSize ); + std::size_t WriteBytes( const void* pData, std::size_t nSize ); + sal_uInt64 Seek( sal_uInt64 nPos ); + sal_uInt64 SeekRel( sal_Int64 nPos ); + sal_uInt64 Tell() const { return m_nBufFilePos + m_nBufActualPos; } + virtual sal_uInt64 TellEnd(); + // length between current (Tell()) pos and end of stream + sal_uInt64 remainingSize(); + /// If we have data in our internal buffers, write them out + void FlushBuffer(); + /// Call FlushBuffer() and then call flush on the underlying OS stream + void Flush(); + // next Tell() <= nSize + bool SetStreamSize( sal_uInt64 nSize ); + + /** Read a line of bytes. + + @param nMaxBytesToRead + Maximum of bytes to read, if line is longer it will be + truncated. + + @note NOTE that the default is one character less than STRING_MAXLEN to + prevent problems after conversion to String that may be lurking + in various places doing something like + @code + for (sal_uInt16 i=0; i < aString.Len(); ++i) + @endcode + causing endless loops ... + */ + bool ReadLine( OStringBuffer& rStr, sal_Int32 nMaxBytesToRead = 0xFFFE ); + bool ReadLine( OString& rStr, sal_Int32 nMaxBytesToRead = 0xFFFE ); + bool WriteLine( std::string_view rStr ); + + /** Read a line of bytes. + + @param nMaxBytesToRead + Maximum of bytes to read, if line is longer it will be + truncated. + + @note NOTE that the default is one character less than STRING_MAXLEN to + prevent problems after conversion to String that may be lurking + in various places doing something like + @code + for (sal_uInt16 i=0; i < aString.Len(); ++i) + @endcode + causing endless loops ... + */ + bool ReadByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet, + sal_Int32 nMaxBytesToRead = 0xFFFE ); + bool WriteByteStringLine( std::u16string_view rStr, rtl_TextEncoding eDestCharSet ); + + /// Switch to no endian swapping and write 0xfeff + void StartWritingUnicodeText(); + + /** If eReadBomCharSet==RTL_TEXTENCODING_DONTKNOW: read 16bit, if 0xfeff do + nothing (UTF-16), if 0xfffe switch endian swapping (UTF-16), if 0xefbb + or 0xbbef read another byte and check for UTF-8. If no UTF-* BOM was + detected put all read bytes back. This means that if 2 bytes were read + it was an UTF-16 BOM, if 3 bytes were read it was an UTF-8 BOM. There + is no UTF-7, UTF-32 or UTF-EBCDIC BOM detection! + + If eReadBomCharSet!=RTL_TEXTENCODING_DONTKNOW: only read a BOM of that + encoding and switch endian swapping if UTF-16 and 0xfffe. */ + void StartReadingUnicodeText( rtl_TextEncoding eReadBomCharSet ); + + /** Read a line of Unicode. + + @param nMaxCodepointsToRead + Maximum of codepoints (UCS-2 or UTF-16 pairs, not bytes) to + read, if line is longer it will be truncated. + */ + SAL_DLLPRIVATE bool ReadUniStringLine(OUString& rStr, sal_Int32 nMaxCodepointsToRead); + /** Read a 32bit length prefixed sequence of utf-16 if + eSrcCharSet==RTL_TEXTENCODING_UNICODE, otherwise read a 16bit length + prefixed sequence of bytes and convert from eSrcCharSet */ + OUString ReadUniOrByteString(rtl_TextEncoding eSrcCharSet); + /** Write a 32bit length prefixed sequence of utf-16 if + eSrcCharSet==RTL_TEXTENCODING_UNICODE, otherwise convert to eSrcCharSet + and write a 16bit length prefixed sequence of bytes */ + SvStream& WriteUniOrByteString( std::u16string_view rStr, rtl_TextEncoding eDestCharSet ); + + /** Read a line of Unicode if eSrcCharSet==RTL_TEXTENCODING_UNICODE, + otherwise read a line of Bytecode and convert from eSrcCharSet + + @param nMaxCodepointsToRead + Maximum of codepoints (2 bytes if Unicode, bytes if not + Unicode) to read, if line is longer it will be truncated. + + @note NOTE that the default is one character less than STRING_MAXLEN to + prevent problems after conversion to String that may be lurking in + various places doing something like + @code + for (sal_uInt16 i=0; i < aString.Len(); ++i) + @endcode + causing endless loops ... + */ + bool ReadUniOrByteStringLine( OUString& rStr, rtl_TextEncoding eSrcCharSet, + sal_Int32 nMaxCodepointsToRead = 0xFFFE ); + /** Write a sequence of Unicode characters if + eDestCharSet==RTL_TEXTENCODING_UNICODE, otherwise write a sequence of + Bytecodes converted to eDestCharSet */ + bool WriteUnicodeOrByteText(std::u16string_view rStr, rtl_TextEncoding eDestCharSet ); + bool WriteUnicodeOrByteText(std::u16string_view rStr ) + { return WriteUnicodeOrByteText( rStr, GetStreamCharSet() ); } + + /** Write a Unicode character if eDestCharSet==RTL_TEXTENCODING_UNICODE, + otherwise write as Bytecode converted to eDestCharSet. + + This may result in more than one byte being written if a multi byte + encoding (e.g. UTF7, UTF8) is chosen. */ + bool WriteUniOrByteChar( sal_Unicode ch, rtl_TextEncoding eDestCharSet ); + bool WriteUniOrByteChar( sal_Unicode ch ) + { return WriteUniOrByteChar( ch, GetStreamCharSet() ); } + + void SetBufferSize( sal_uInt16 m_nBufSize ); + sal_uInt16 GetBufferSize() const { return m_nBufSize; } + + void RefreshBuffer(); + + bool IsWritable() const { return m_isWritable; } + StreamMode GetStreamMode() const { return m_eStreamMode; } + + sal_Int32 GetVersion() const { return m_nVersion; } + void SetVersion( sal_Int32 n ) { m_nVersion = n; } + + friend SvStream& operator<<( SvStream& rStr, SvStrPtr f ); // for Manips + + /// end of input seen during previous i/o operation + bool eof() const { return m_isEof; } + + /// stream is broken + bool bad() const { return GetError() != ERRCODE_NONE; } + + /** Get state + + If the state is good() the previous i/o operation succeeded. + + If the state is good(), the next input operation might succeed; + otherwise, it will fail. + + Applying an input operation to a stream that is not in the good() state + is a null operation as far as the variable being read into is concerned. + + If we try to read into a variable v and the operation fails, the value + of v should be unchanged, + */ + bool good() const { return !(eof() || bad()); } + +private: + template <typename T> SvStream& ReadNumber(T& r); + template <typename T> SvStream& WriteNumber(T n); + + template<typename T> + void readNumberWithoutSwap(T& rDataDest) + { readNumberWithoutSwap_(&rDataDest, sizeof(rDataDest)); } + + SAL_DLLPRIVATE void readNumberWithoutSwap_(void * pDataDest, int nDataSize); + + template<typename T> + void writeNumberWithoutSwap(T const & rDataSrc) + { writeNumberWithoutSwap_(&rDataSrc, sizeof(rDataSrc)); } + + SAL_DLLPRIVATE void writeNumberWithoutSwap_(const void * pDataSrc, int nDataSize); +}; + +inline SvStream& operator<<( SvStream& rStr, SvStrPtr f ) +{ + (*f)(rStr); + return rStr; +} + +TOOLS_DLLPUBLIC SvStream& endl( SvStream& rStr ); +/// same as endl() but Unicode +TOOLS_DLLPUBLIC SvStream& endlu( SvStream& rStr ); +/// call endlu() if m_eStreamCharSet==RTL_TEXTECODING_UNICODE otherwise endl() +TOOLS_DLLPUBLIC SvStream& endlub( SvStream& rStr ); + +/// Attempt to read nUnits 8bit units to an OString, returned OString's +/// length is number of units successfully read +TOOLS_DLLPUBLIC OString read_uInt8s_ToOString(SvStream& rStrm, + std::size_t nUnits); + +/// Attempt to read nUnits 8bit units to an OUString +inline OUString read_uInt8s_ToOUString(SvStream& rStrm, + std::size_t nUnits, rtl_TextEncoding eEnc) +{ + return OStringToOUString(read_uInt8s_ToOString(rStrm, nUnits), eEnc); +} + +/// Attempt to read nUnits 16bit units to an OUString, returned +/// OUString's length is number of units successfully read +TOOLS_DLLPUBLIC OUString read_uInt16s_ToOUString(SvStream& rStrm, + std::size_t nUnits); + +/// Attempt to read a pascal-style length (of type prefix) prefixed sequence of +/// 16bit units to an OUString, returned OString's length is number of +/// units successfully read. +inline OUString read_uInt16_lenPrefixed_uInt16s_ToOUString(SvStream& rStrm) +{ + sal_uInt16 nUnits = 0; + rStrm.ReadUInt16( nUnits ); + return read_uInt16s_ToOUString(rStrm, nUnits); +} + +inline OUString read_uInt32_lenPrefixed_uInt16s_ToOUString(SvStream& rStrm) +{ + sal_uInt32 nUnits = 0; + rStrm.ReadUInt32( nUnits ); + return read_uInt16s_ToOUString(rStrm, nUnits); +} + +/// Attempt to write a prefixed sequence of nUnits 16bit units from an OUString, +/// returned value is number of bytes written +TOOLS_DLLPUBLIC std::size_t write_uInt16s_FromOUString(SvStream& rStrm, + std::u16string_view rStr, std::size_t nUnits); + +inline std::size_t write_uInt16s_FromOUString(SvStream& rStrm, + std::u16string_view rStr) +{ + return write_uInt16s_FromOUString(rStrm, rStr, rStr.size()); +} + +/// Attempt to write a pascal-style length (of type prefix) prefixed sequence +/// of 16bit units from an OUString, returned value is number of bytes written +/// (including byte-count of prefix) +std::size_t write_uInt32_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm, + std::u16string_view rStr); + +/// Attempt to write a pascal-style length (of type prefix) prefixed sequence +/// of 16bit units from an OUString, returned value is number of bytes written +/// (including byte-count of prefix) +UNLESS_MERGELIBS(TOOLS_DLLPUBLIC) std::size_t write_uInt16_lenPrefixed_uInt16s_FromOUString(SvStream& rStrm, + std::u16string_view rStr); + +/// Attempt to read 8bit units to an OString until a zero terminator is +/// encountered, returned OString's length is number of units *definitely* +/// successfully read, check SvStream::good() to see if null terminator was +/// successfully read +TOOLS_DLLPUBLIC OString read_zeroTerminated_uInt8s_ToOString(SvStream& rStrm); + +/// Attempt to read 8bit units assuming source encoding eEnc to an OUString +/// until a zero terminator is encountered. Check SvStream::good() to see if +/// null terminator was successfully read +TOOLS_DLLPUBLIC OUString read_zeroTerminated_uInt8s_ToOUString(SvStream& rStrm, rtl_TextEncoding eEnc); + +/// Attempt to read a pascal-style length (of type prefix) prefixed sequence of +/// 8bit units to an OString, returned OString's length is number of units +/// successfully read. +inline OString read_uInt32_lenPrefixed_uInt8s_ToOString(SvStream& rStrm) +{ + sal_uInt32 nUnits = 0; + rStrm.ReadUInt32(nUnits); + return read_uInt8s_ToOString(rStrm, nUnits); +} +inline OString read_uInt16_lenPrefixed_uInt8s_ToOString(SvStream& rStrm) +{ + sal_uInt16 nUnits = 0; + rStrm.ReadUInt16(nUnits); + return read_uInt8s_ToOString(rStrm, nUnits); +} + +inline OString read_uInt8_lenPrefixed_uInt8s_ToOString(SvStream& rStrm) +{ + sal_uInt8 nUnits = 0; + rStrm.ReadUChar(nUnits); + return read_uInt8s_ToOString(rStrm, nUnits); +} + +inline OUString read_uInt16_lenPrefixed_uInt8s_ToOUString(SvStream& rStrm, + rtl_TextEncoding eEnc) +{ + return OStringToOUString(read_uInt16_lenPrefixed_uInt8s_ToOString(rStrm), eEnc); +} + +inline OUString read_uInt8_lenPrefixed_uInt8s_ToOUString(SvStream& rStrm, + rtl_TextEncoding eEnc) +{ + return OStringToOUString(read_uInt8_lenPrefixed_uInt8s_ToOString(rStrm), eEnc); +} + +/// Attempt to write a prefixed sequence of nUnits 8bit units from an OString, +/// returned value is number of bytes written +inline std::size_t write_uInt8s_FromOString(SvStream& rStrm, std::string_view rStr, + std::size_t nUnits) +{ + return rStrm.WriteBytes(rStr.data(), nUnits); +} + +inline std::size_t write_uInt8s_FromOString(SvStream& rStrm, std::string_view rStr) +{ + return write_uInt8s_FromOString(rStrm, rStr, rStr.size()); +} + +/// Attempt to write a pascal-style length (of type prefix) prefixed +/// sequence of units from a string-type, returned value is number of bytes +/// written (including byte-count of prefix) +TOOLS_DLLPUBLIC std::size_t write_uInt16_lenPrefixed_uInt8s_FromOString(SvStream& rStrm, + std::string_view rStr); + +/// Attempt to write a pascal-style length (of type prefix) prefixed sequence +/// of 8bit units from an OUString, returned value is number of bytes written +/// (including byte-count of prefix) +inline std::size_t write_uInt16_lenPrefixed_uInt8s_FromOUString(SvStream& rStrm, + std::u16string_view rStr, + rtl_TextEncoding eEnc) +{ + return write_uInt16_lenPrefixed_uInt8s_FromOString(rStrm, OUStringToOString(rStr, eEnc)); +} + +[[nodiscard]] TOOLS_DLLPUBLIC bool checkSeek(SvStream &rSt, sal_uInt64 nOffset); + +namespace tools +{ +/// Is rUrl a file:// URL with no contents? +TOOLS_DLLPUBLIC bool isEmptyFileUrl(const OUString& rUrl); +} + +// FileStream + +class TOOLS_DLLPUBLIC SvFileStream final : public SvStream +{ +private: + void* mxFileHandle = nullptr; // on windows, it is a HANDLE, otherwise, it is a oslFileHandle +#if defined(_WIN32) + sal_uInt16 nLockCounter; +#endif + OUString aFilename; + bool bIsOpen; + + SvFileStream (const SvFileStream&) = delete; + SvFileStream & operator= (const SvFileStream&) = delete; + + bool LockFile(); + void UnlockFile(); + + virtual std::size_t GetData( void* pData, std::size_t nSize ) override; + virtual std::size_t PutData( const void* pData, std::size_t nSize ) override; + virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override; + virtual void SetSize( sal_uInt64 nSize ) override; + virtual void FlushData() override; + +public: + // Switches to Read StreamMode on failed attempt of Write opening + SvFileStream( const OUString& rFileName, StreamMode eOpenMode ); + SvFileStream(); + virtual ~SvFileStream() override; + + virtual void ResetError() override; + + void Open( const OUString& rFileName, StreamMode eOpenMode ); + void Close(); + bool IsOpen() const { return bIsOpen; } + + const OUString& GetFileName() const { return aFilename; } +}; + +// MemoryStream + +class TOOLS_DLLPUBLIC SvMemoryStream : public SvStream +{ + SvMemoryStream (const SvMemoryStream&) = delete; + SvMemoryStream & operator= (const SvMemoryStream&) = delete; + +protected: + std::size_t nSize; + std::size_t nResize; + std::size_t nPos; + std::size_t nEndOfData; + sal_uInt8* pBuf; + bool bOwnsData; + + virtual std::size_t GetData( void* pData, std::size_t nSize ) override; + virtual std::size_t PutData( const void* pData, std::size_t nSize ) override; + virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override; + virtual void SetSize( sal_uInt64 nSize ) override; + virtual void FlushData() override; + + /// AllocateMemory must update pBuf accordingly + /// - pBuf: Address of new block + void AllocateMemory( std::size_t nSize ); + + /// ReAllocateMemory must update the following variables: + /// - pBuf: Address of new block + /// - nEndOfData: Set to nNewSize-1 , if outside of block + /// Set to 0 , if new block size is 0 bytes + /// - nSize: New block size + /// - nPos: Set to 0 if position outside of block + bool ReAllocateMemory( tools::Long nDiff ); + + /// Is called when this stream allocated the buffer or the buffer is + /// resized. FreeMemory may need to NULLify handles in derived classes. + void FreeMemory(); + +public: + SvMemoryStream( void* pBuf, std::size_t nSize, StreamMode eMode); + SvMemoryStream( std::size_t nInitSize=512, std::size_t nResize=64 ); + virtual ~SvMemoryStream() override; + + virtual void ResetError() override; + + sal_uInt64 GetSize() { return TellEnd(); } + std::size_t GetEndOfData() const { return nEndOfData; } + const void* GetData() { FlushBuffer(); return pBuf; } + + // return the buffer currently in use, and allocate a new buffer internally + void* SwitchBuffer(); + // the buffer is not owned by this class + void SetBuffer( void* pBuf, std::size_t nSize, std::size_t nEOF ); + + void ObjectOwnsMemory( bool bOwn ) { bOwnsData = bOwn; } + /// Makes the stream read-only after it was (possibly) initially writable, + /// without having to copy the data or change buffers. + /// @since LibreOffice 7.5 + void MakeReadOnly(); + void SetResizeOffset( std::size_t nNewResize ) { nResize = nNewResize; } + virtual sal_uInt64 TellEnd() override { FlushBuffer(); return nEndOfData; } +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/svborder.hxx b/include/tools/svborder.hxx new file mode 100644 index 0000000000..92f779cac3 --- /dev/null +++ b/include/tools/svborder.hxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_TOOLS_SVBORDER_HXX +#define INCLUDED_TOOLS_SVBORDER_HXX + +#include <tools/toolsdllapi.h> +#include <tools/long.hxx> + +namespace tools { class Rectangle; } + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC SvBorder +{ + tools::Long nTop, nRight, nBottom, nLeft; + +public: + SvBorder() + { + nTop = nRight = nBottom = nLeft = 0; + } + SvBorder( tools::Long nLeftP, tools::Long nTopP, tools::Long nRightP, tools::Long nBottomP ) + { + nLeft = nLeftP; + nTop = nTopP; + nRight = nRightP; + nBottom = nBottomP; + } + bool operator == ( const SvBorder & rObj ) const + { + return nTop == rObj.nTop && nRight == rObj.nRight && + nBottom == rObj.nBottom && nLeft == rObj.nLeft; + } + bool operator != ( const SvBorder & rObj ) const + { return !(*this == rObj); } + SvBorder & operator += ( const SvBorder & rBorder ) + { + Left() += rBorder.Left(); + Top() += rBorder.Top(); + Right() += rBorder.Right(); + Bottom() += rBorder.Bottom(); + return *this; + } + tools::Long & Top() { return nTop; } + tools::Long & Right() { return nRight; } + tools::Long & Bottom() { return nBottom; } + tools::Long & Left() { return nLeft; } + tools::Long Top() const { return nTop; } + tools::Long Right() const { return nRight; } + tools::Long Bottom() const { return nBottom; } + tools::Long Left() const { return nLeft; } +}; + +TOOLS_DLLPUBLIC tools::Rectangle & operator += ( tools::Rectangle & rRect, const SvBorder & rBorder ); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/svlibrary.h b/include/tools/svlibrary.h new file mode 100644 index 0000000000..df3f720314 --- /dev/null +++ b/include/tools/svlibrary.h @@ -0,0 +1,15 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef SVLIBRARY +#define SVLIBRARY(Base) SAL_MODULENAME(Base "lo") +#include <osl/module.h> +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/tenccvt.hxx b/include/tools/tenccvt.hxx new file mode 100644 index 0000000000..1893c73551 --- /dev/null +++ b/include/tools/tenccvt.hxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_TENCCVT_HXX +#define INCLUDED_TOOLS_TENCCVT_HXX + +#include <rtl/textenc.h> +#include <tools/toolsdllapi.h> + +// Functions for handling Import/Export + +/// return an encoding which has more defined Characters as the given +/// encoding, but have the same definition for the defined characters +/// e.g.: windows-1252 for iso-8859-1 or windows-1254 for iso-8859-9 +TOOLS_DLLPUBLIC rtl_TextEncoding GetExtendedCompatibilityTextEncoding(rtl_TextEncoding eEncoding); + +/// return an encoding which has more defined Characters as the given +/// encoding. The encodings could be different. +/// e.g.: windows-1251 for iso-8859-5 +TOOLS_DLLPUBLIC rtl_TextEncoding GetExtendedTextEncoding(rtl_TextEncoding eEncoding); + +/// if the given encoding is an multi-byte encoding (which allows more than +/// one byte per char, e.g. UTF-8 or Shift-JIS), a one-byte encoding +/// is returned (normally windows-1252). +rtl_TextEncoding GetOneByteTextEncoding(rtl_TextEncoding eEncoding); + +TOOLS_DLLPUBLIC rtl_TextEncoding GetSOLoadTextEncoding(rtl_TextEncoding eEncoding); +TOOLS_DLLPUBLIC rtl_TextEncoding GetSOStoreTextEncoding(rtl_TextEncoding eEncoding); + +/** + * Given a Unicode character, return a legacy Microsoft Encoding which + * supports it. Returns RTL_TEXTENCODING_DONTKNOW if there is + * no encoding which could support the character + * + * Useful as a utility to categorize unicode characters into the best fit + * windows charset range for exporting to ww6 & wmf or as a hint to non \u + * unicode token aware rtf readers + */ +TOOLS_DLLPUBLIC rtl_TextEncoding getBestMSEncodingByChar(sal_Unicode c); + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/time.hxx b/include/tools/time.hxx new file mode 100644 index 0000000000..414b28f729 --- /dev/null +++ b/include/tools/time.hxx @@ -0,0 +1,177 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_TIME_HXX +#define INCLUDED_TOOLS_TIME_HXX + +#include <tools/toolsdllapi.h> +#include <com/sun/star/util/Time.hpp> + +namespace com::sun::star::util { struct DateTime; } + +/** + @WARNING: This class can serve both as wall clock time and time duration, and + the mixing of these concepts leads to problems such as there being + 25 hours or 10 minus 20 seconds being (non-negative) 10 seconds. +*/ + +namespace tools { + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC Time +{ +private: + sal_Int64 nTime; + void init( sal_uInt32 nHour, sal_uInt32 nMin, + sal_uInt32 nSec, sal_uInt64 nNanoSec); + +public: + enum TimeInitSystem + { + SYSTEM + }; + + // temporary until all uses are inspected and resolved + enum TimeInitEmpty + { + EMPTY + }; + static const sal_Int64 hourPerDay = 24; + static const sal_Int64 minutePerHour = 60; + static const sal_Int64 secondPerMinute = 60; + static const sal_Int64 nanoSecPerSec = 1000000000; + static const sal_Int64 nanoSecPerMinute = nanoSecPerSec * secondPerMinute; + static const sal_Int64 nanoSecPerHour = nanoSecPerSec * secondPerMinute * minutePerHour; + static const sal_Int64 nanoSecPerDay = nanoSecPerSec * secondPerMinute * minutePerHour * hourPerDay; + static const sal_Int64 secondPerHour = secondPerMinute * minutePerHour; + static const sal_Int64 secondPerDay = secondPerMinute * minutePerHour * hourPerDay; + static const sal_Int64 minutePerDay = minutePerHour * hourPerDay; + static const sal_Int64 nanoPerMicro = 1000; + static const sal_Int64 nanoPerMilli = 1000000; + static const sal_Int64 nanoPerCenti = 10000000; + + explicit Time( TimeInitEmpty ) + { nTime = 0; } + explicit Time( TimeInitSystem ); + explicit Time( sal_Int64 _nTime ) { Time::nTime = _nTime; } + Time( const tools::Time& rTime ); + Time( const css::util::Time& rTime ); + explicit Time( const css::util::DateTime& rDateTime ); + Time( sal_uInt32 nHour, sal_uInt32 nMin, + sal_uInt32 nSec = 0, sal_uInt64 nNanoSec = 0 ); + + void SetTime( sal_Int64 nNewTime ) { nTime = nNewTime; } + sal_Int64 GetTime() const { return nTime; } + css::util::Time GetUNOTime() const { return css::util::Time(GetNanoSec(),GetSec(),GetMin(),GetHour(),false); } + + void SetHour( sal_uInt16 nNewHour ); + void SetMin( sal_uInt16 nNewMin ); + void SetSec( sal_uInt16 nNewSec ); + void SetNanoSec( sal_uInt32 nNewNanoSec ); + sal_uInt16 GetHour() const + { sal_uInt64 nTempTime = (nTime >= 0) ? nTime : -nTime; + return static_cast<sal_uInt16>(nTempTime / SAL_CONST_UINT64(10000000000000)); } + sal_uInt16 GetMin() const + { sal_uInt64 nTempTime = (nTime >= 0) ? nTime : -nTime; + return static_cast<sal_uInt16>((nTempTime / SAL_CONST_UINT64(100000000000)) % 100); } + sal_uInt16 GetSec() const + { sal_uInt64 nTempTime = (nTime >= 0) ? nTime : -nTime; + return static_cast<sal_uInt16>((nTempTime / SAL_CONST_UINT64(1000000000)) % 100); } + sal_uInt32 GetNanoSec() const + { sal_uInt64 nTempTime = (nTime >= 0) ? nTime : -nTime; + return static_cast<sal_uInt32>( nTempTime % SAL_CONST_UINT64(1000000000)); } + + // TODO: consider removing GetMSFromTime and MakeTimeFromMS? + sal_Int32 GetMSFromTime() const; + void MakeTimeFromMS( sal_Int32 nMS ); + sal_Int64 GetNSFromTime() const; + void MakeTimeFromNS( sal_Int64 nNS ); + + /// 12 hours == 0.5 days + double GetTimeInDays() const; + + /** Get the wall clock time particles for a (date+)time value. + + Does the necessary rounding and truncating to obtain hour, minute, + second and fraction of second from a double time value (time in days, + 0.5 == 12h) such that individual values are not rounded up, i.e. + x:59:59.999 does not yield x+1:0:0.00 + + A potential date component (fTimeInDays >= 1.0) is discarded. + + @param nFractionDecimals + If > 0 fFractionOfSecond is truncated to that amount of + decimals. + Else fFractionOfSecond returns the full remainder of the + fractional second. + */ + static void GetClock( double fTimeInDays, + sal_uInt16& nHour, sal_uInt16& nMinute, sal_uInt16& nSecond, + double& fFractionOfSecond, int nFractionDecimals ); + + bool IsEqualIgnoreNanoSec( const tools::Time& rTime ) const; + + bool operator ==( const tools::Time& rTime ) const + { return (nTime == rTime.nTime); } + bool operator !=( const tools::Time& rTime ) const + { return (nTime != rTime.nTime); } + bool operator >( const tools::Time& rTime ) const + { return (nTime > rTime.nTime); } + bool operator <( const tools::Time& rTime ) const + { return (nTime < rTime.nTime); } + bool operator >=( const tools::Time& rTime ) const + { return (nTime >= rTime.nTime); } + bool operator <=( const tools::Time& rTime ) const + { return (nTime <= rTime.nTime); } + + static Time GetUTCOffset(); + + /** + * Elapsed time in milliseconds (1e-3) since some unspecified starting point + * + * Convenience function, which just calls GetMonotonicTicks() / 1000. + */ + static sal_uInt64 GetSystemTicks(); + + /** + * Elapsed time in microseconds (1e-6) since some unspecified starting point + * + * Uses the high-precision, monotonic time sources provided by the OS, if + * available. Don't try to relate it to the system time, and also it's long + * time accuracy is not the best. + * + * Currently used to measure the runtime of OpenCL shaders and to set a + * message creation timestamp to allow filtering of invalid timer messages. + * + * @return current system ticks in microseconds (1e-6s) + */ + static sal_uInt64 GetMonotonicTicks(); + + tools::Time& operator =( const tools::Time& rTime ); + Time operator -() const + { return Time( -nTime ); } + tools::Time& operator +=( const tools::Time& rTime ); + tools::Time& operator -=( const tools::Time& rTime ); + TOOLS_DLLPUBLIC friend Time operator +( const tools::Time& rTime1, const tools::Time& rTime2 ); + TOOLS_DLLPUBLIC friend Time operator -( const tools::Time& rTime1, const tools::Time& rTime2 ); +}; + +} /* namespace tools */ + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/toolsdllapi.h b/include/tools/toolsdllapi.h new file mode 100644 index 0000000000..0ee778e6f0 --- /dev/null +++ b/include/tools/toolsdllapi.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_TOOLS_TOOLSDLLAPI_H +#define INCLUDED_TOOLS_TOOLSDLLAPI_H + +#include <sal/types.h> + +#if defined(TOOLS_DLLIMPLEMENTATION) +#define TOOLS_DLLPUBLIC SAL_DLLPUBLIC_EXPORT +#else +#define TOOLS_DLLPUBLIC SAL_DLLPUBLIC_IMPORT +#endif +#define TOOLS_DLLPRIVATE SAL_DLLPRIVATE + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/urlobj.hxx b/include/tools/urlobj.hxx new file mode 100644 index 0000000000..7e7c4a2aaf --- /dev/null +++ b/include/tools/urlobj.hxx @@ -0,0 +1,1305 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_URLOBJ_HXX +#define INCLUDED_TOOLS_URLOBJ_HXX + +#include <tools/toolsdllapi.h> +#include <rtl/ustrbuf.hxx> +#include <rtl/textenc.h> +#include <sal/types.h> +#include <o3tl/typed_flags_set.hxx> + +#include <memory> +#include <string_view> + +class SvMemoryStream; + +namespace com::sun::star::util { + class XStringWidth; +} + +namespace com::sun::star::uno { template <typename > class Reference; } + +// Common URL prefixes for various schemes: +inline constexpr OUString INET_FTP_SCHEME = u"ftp://"_ustr; +inline constexpr OUString INET_HTTP_SCHEME = u"http://"_ustr; +inline constexpr OUString INET_HTTPS_SCHEME = u"https://"_ustr; +inline constexpr OUString INET_FILE_SCHEME = u"file://"_ustr; +inline constexpr OUString INET_MAILTO_SCHEME = u"mailto:"_ustr; +inline constexpr OUString INET_HID_SCHEME = u"hid:"_ustr; + +#define URL_PREFIX_PRIV_SOFFICE "private:" + +// Schemes: +enum class INetProtocol +{ + NotValid, + Ftp, + Http, + File, + Mailto, + VndSunStarWebdav, + PrivSoffice, + VndSunStarHelp, + Https, + Slot, + Macro, + Javascript, + Data, + Cid, + VndSunStarHier, + Uno, + Component, + VndSunStarPkg, + Ldap, + Db, + VndSunStarCmd, + Telnet, + VndSunStarExpand, + VndSunStarTdoc, + Generic, + Smb, + Hid, + Sftp, + Cmis, + LAST = Cmis +}; + +/** The supported notations for file system paths. + */ +enum class FSysStyle +{ + /** VOS notation (e.g., "//server/dir/file"). + */ + Vos = 0x1, + + /** Unix notation (e.g., "/dir/file"). + */ + Unix = 0x2, + + /** DOS notation (e.g., "a:\dir\file" and "\\server\dir\file"). + */ + Dos = 0x4, + + /** Detect the used notation. + + @descr For the following descriptions, please note that + whereas FSYS_DEFAULT includes all style bits, combinations of only + a few style bits are also possible, and are also described. + + @descr When used to translate a file system path to a file URL, + the subset of the following productions for which the appropriate + style bit is set are checked in order (using the conventions of + RFC 2234, RFC 2396, and RFC 2732; UCS4 stands for any UCS4 + character): + + Production T1 (VOS local; FSysStyle::Vos only): + "//." ["/" *UCS4] + becomes + "file:///" *UCS4 + + Production T2 (VOS host; FSysStyle::Vos only): + "//" [host] ["/" *UCS4] + becomes + "file://" host "/" *UCS4 + + Production T3 (UNC; FSysStyle::Dos only): + "\\" [host] ["\" *UCS4] + becomes + "file://" host "/" *UCS4 + replacing "\" by "/" within <*UCS4> + + Production T4 (Unix-like DOS; FSysStyle::Dos only): + ALPHA ":" ["/" *UCS4] + becomes + "file:///" ALPHA ":/" *UCS4 + replacing "\" by "/" within <*UCS4> + + Production T5 (DOS; FSysStyle::Dos only): + ALPHA ":" ["\" *UCS4] + becomes + "file:///" ALPHA ":/" *UCS4 + replacing "\" by "/" within <*UCS4> + + Production T6 (any): + *UCS4 + becomes + "file:///" *UCS4 + replacing the delimiter by "/" within <*UCS4>. The delimiter is + that character from the set { "/", "\" } which appears most + often in <*UCS4> (if FSysStyle::Unix is not among the style bits, "/" + is removed from the set; if FSysStyle::Dos is not among the style + bits, "\" is removed from the set). If two or more + characters appear the same number of times, the character + mentioned first in that set is chosen. If the first character + of <*UCS4> is the delimiter, that character is not copied. + + @descr When used to translate a file URL to a file system path, + the following productions are checked in order (using the + conventions of RFC 2234, RFC 2396, and RFC 2732): + + Production F1 (VOS; FSysStyle::Vos): + "file://" host "/" fpath ["#" fragment] + becomes + "//" host "/" fpath + + Production F2 (DOS; FSysStyle::Dos): + "file:///" ALPHA ":" ["/" fpath] ["#" fragment] + becomes + ALPHA ":" ["\" fpath] + replacing "/" by "\" in <fpath> + + Production F3 (Unix; FSysStyle::Unix): + "file:///" fpath ["#" fragment] + becomes + "/" fpath + */ + Detect = Vos | Unix | Dos +}; +namespace o3tl { + template<> struct typed_flags<FSysStyle> : is_typed_flags<FSysStyle, 0x07> {}; +} + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC INetURLObject +{ +public: + // Get- and Set-Methods: + + /** The way input strings that represent (parts of) URIs are interpreted + in set-methods. + + @descr UTF-32 characters in the range 0x80--0x10FFFF are replaced by + sequences of escape sequences, representing the UTF-8 coded characters. + + @descr Along with an EncodeMechanism parameter, the set-methods all + take an rtl_TextEncoding parameter, which is ignored unless the + EncodeMechanism is EncodeMechanism::WasEncoded. + */ + enum class EncodeMechanism + { + /** All escape sequences that are already present are ignored, and are + interpreted as literal sequences of three characters. + */ + All, + + /** Sequences of escape sequences, that represent characters from the + specified character set and that can be converted to UTF-32 + characters, are first decoded. If they have to be encoded, they + are converted to UTF-8 characters and are than translated into + (sequences of) escape sequences. Other escape sequences are + copied verbatim (but using upper case hex digits). + */ + WasEncoded, + + /** All escape sequences that are already present are copied verbatim + (but using upper case hex digits). + */ + NotCanonical + }; + + /** The way strings that represent (parts of) URIs are returned from get- + methods. + + @descr Along with a DecodeMechanism parameter, the get-methods all + take an rtl_TextEncoding parameter, which is ignored unless the + DecodeMechanism is DecodeMechanism::WithCharset or DecodeMechanism::Unambiguous. + */ + enum class DecodeMechanism + { + /** The (part of the) URI is returned unchanged. Since URIs are + written using a subset of US-ASCII, the returned string is + guaranteed to contain only US-ASCII characters. + */ + NONE, + + /** All sequences of escape sequences that represent UTF-8 coded + UTF-32 characters with a numerical value greater than 0x7F, are + replaced by the respective UTF-16 characters. All other escape + sequences are not decoded. + */ + ToIUri, + + /** All (sequences of) escape sequences that represent characters from + the specified character set, and that can be converted to UTF-32, + are replaced by the respective UTF-16 characters. All other + escape sequences are not decoded. + */ + WithCharset, + + /** All (sequences of) escape sequences that represent characters from + the specified character set, that can be converted to UTF-32, and + that (in the case of ASCII characters) can safely be decoded + without altering the meaning of the (part of the) URI, are + replaced by the respective UTF-16 characters. All other escape + sequences are not decoded. + */ + Unambiguous + }; + + // General Structure: + + INetURLObject(): + m_aAbsURIRef(256), m_eScheme(INetProtocol::NotValid), m_eSmartScheme(INetProtocol::Http) {} + + bool HasError() const { return m_eScheme == INetProtocol::NotValid; } + + OUString GetMainURL(DecodeMechanism eMechanism, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8) const + { return decode(m_aAbsURIRef, eMechanism, eCharset); } + + OUString GetURLNoPass(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + const; + + OUString GetURLNoMark(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + const; + + OUString + getAbbreviated(css::uno::Reference< css::util::XStringWidth > const & rStringWidth, + sal_Int32 nWidth, + DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + const; + + bool operator ==(INetURLObject const & rObject) const; + + bool operator !=(INetURLObject const & rObject) const + { return !(*this == rObject); } + + // Strict Parsing: + + inline explicit INetURLObject( + std::u16string_view rTheAbsURIRef, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + inline bool SetURL(std::u16string_view rTheAbsURIRef, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + bool ConcatData(INetProtocol eTheScheme, std::u16string_view rTheUser, + std::u16string_view rThePassword, + std::u16string_view rTheHost, sal_uInt32 nThePort, + std::u16string_view rThePath); + + // Smart Parsing: + + inline INetURLObject(std::u16string_view rTheAbsURIRef, + INetProtocol eTheSmartScheme, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8, + FSysStyle eStyle = FSysStyle::Detect); + + void SetSmartProtocol(INetProtocol eTheSmartScheme) + { m_eSmartScheme = eTheSmartScheme; } + + inline bool + SetSmartURL(std::u16string_view rTheAbsURIRef, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8, + FSysStyle eStyle = FSysStyle::Detect); + + inline INetURLObject + smartRel2Abs(OUString const & rTheRelURIRef, + bool & rWasAbsolute, + bool bIgnoreFragment = false, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8, + bool bRelativeNonURIs = false, + FSysStyle eStyle = FSysStyle::Detect) const; + + // Relative URLs: + + inline bool + GetNewAbsURL(OUString const & rTheRelURIRef, + INetURLObject * pTheAbsURIRef) + const; + + /** @descr If rTheRelURIRef cannot be converted to an absolute URL + (because of syntactic reasons), either rTheRelURIRef or an empty + string is returned: If all of the parameters eEncodeMechanism, + eDecodeMechanism and eCharset have their respective default values, + then rTheRelURIRef is returned unmodified; otherwise, an empty string + is returned. + */ + static OUString + GetAbsURL(std::u16string_view rTheBaseURIRef, + OUString const & rTheRelURIRef, + EncodeMechanism eEncodeMechanism = EncodeMechanism::WasEncoded, + DecodeMechanism eDecodeMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + static inline OUString + GetRelURL(std::u16string_view rTheBaseURIRef, + OUString const & rTheAbsURIRef, + EncodeMechanism eEncodeMechanism = EncodeMechanism::WasEncoded, + DecodeMechanism eDecodeMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8, + FSysStyle eStyle = FSysStyle::Detect); + + // External URLs: + + OUString getExternalURL() const; + + static inline bool translateToExternal(std::u16string_view rTheIntURIRef, + OUString & rTheExtURIRef, + DecodeMechanism eDecodeMechanism + = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8); + + static inline bool translateToInternal(std::u16string_view rTheExtURIRef, + OUString & rTheIntURIRef, + DecodeMechanism eDecodeMechanism + = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8); + + // Scheme: + + struct SchemeInfo; + + INetProtocol GetProtocol() const { return m_eScheme; } + + bool isSchemeEqualTo(INetProtocol scheme) const { return scheme == m_eScheme; } + + bool isSchemeEqualTo(std::u16string_view scheme) const; + + /** Check if the scheme is one of the WebDAV scheme + * we know about. + * + * @return true is one other scheme either public scheme or private scheme. + */ + bool isAnyKnownWebDAVScheme() const; + + /** Return the URL 'prefix' for a given scheme. + + @param eTheScheme One of the supported URL schemes. + + @return The 'prefix' of URLs of the given scheme. + */ + static OUString GetScheme(INetProtocol eTheScheme); + + /** Return the human-readable name for a given scheme. + + @param eTheScheme One of the supported URL schemes. + + @return The protocol name of URLs of the given scheme. + */ + static const OUString & GetSchemeName(INetProtocol eTheScheme); + + static INetProtocol CompareProtocolScheme(std::u16string_view aTheAbsURIRef); + + // User Info: + + bool HasUserData() const { return m_aUser.isPresent(); } + + OUString GetUser(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8) const + { return decode(m_aUser, eMechanism, eCharset); } + + OUString GetPass(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8) const + { return decode(m_aAuth, eMechanism, eCharset); } + + bool SetUser(std::u16string_view rTheUser) + { return setUser(rTheUser, RTL_TEXTENCODING_UTF8); } + + inline bool SetPass(std::u16string_view rThePassword); + + // Host and Port: + + bool HasPort() const { return m_aPort.isPresent(); } + + OUString GetHost(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8) const + { return decode(m_aHost, eMechanism, eCharset); } + + OUString GetHostPort(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) const; + + sal_uInt32 GetPort() const; + + bool SetHost(std::u16string_view rTheHost) + { return setHost(rTheHost, RTL_TEXTENCODING_UTF8); } + + bool SetPort(sal_uInt32 nThePort); + + // Path: + + bool HasURLPath() const { return !m_aPath.isEmpty(); } + + OUString GetURLPath(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8) const + { return decode(m_aPath, eMechanism, eCharset); } + + bool SetURLPath(std::u16string_view rThePath, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + { return setPath(rThePath, eMechanism, eCharset); } + + // Hierarchical Path: + + /** A constant to address the last segment in various methods dealing with + hierarchical paths. + + @descr It is often more efficient to address the last segment using + this constant, than to determine its ordinal value using + getSegmentCount(). + */ + enum { LAST_SEGMENT = -1 }; + + /** The number of segments in the hierarchical path. + + @descr Using RFC 2396 and RFC 2234, a hierarchical path is of the + form + + hierarchical-path = 1*("/" segment) + + segment = name *(";" param) + + name = [base ["." extension]] + + base = 1*pchar + + extension = *<any pchar except "."> + + param = *pchar + + @param bIgnoreFinalSlash If true, a final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @return The number of segments in the hierarchical path. If the path + is not hierarchical, 0 is returned. + */ + sal_Int32 getSegmentCount(bool bIgnoreFinalSlash = true) const; + + /** Remove a segment from the hierarchical path. + + @param nIndex The non-negative index of the segment, or LAST_SEGMENT + if addressing the last segment. + + @param bIgnoreFinalSlash If true, a final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @return True if the segment has successfully been removed (and the + resulting URI is still valid). If the path is not hierarchical, or + the specified segment does not exist, false is returned. If false is + returned, the object is not modified. + */ + bool removeSegment(sal_Int32 nIndex = LAST_SEGMENT, + bool bIgnoreFinalSlash = true); + + /** Insert a new segment into the hierarchical path. + A final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @param rTheName The name part of the new segment. The new segment + will contain no parameters. + + @param bAppendFinalSlash If the new segment is appended at the end of + the hierarchical path, this parameter specifies whether to add a final + slash after it or not. + + @param nIndex The non-negative index of the segment before which + to insert the new segment. LAST_SEGMENT or an nIndex that equals + getSegmentCount() inserts the new segment at the end of the + hierarchical path. + + @param eMechanism See the general discussion for set-methods. + + @param eCharset See the general discussion for set-methods. + + @return True if the segment has successfully been inserted (and the + resulting URI is still valid). If the path is not hierarchical, or + the specified place to insert the new segment does not exist, false is + returned. If false is returned, the object is not modified. + */ + bool insertName(std::u16string_view rTheName, + bool bAppendFinalSlash = false, + sal_Int32 nIndex = LAST_SEGMENT, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + /** Get the name of a segment of the hierarchical path. + + @param nIndex The non-negative index of the segment, or LAST_SEGMENT + if addressing the last segment. + + @param bIgnoreFinalSlash If true, a final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @param eMechanism See the general discussion for get-methods. + + @param eCharset See the general discussion for get-methods. + + @return The name part of the specified segment. If the path is not + hierarchical, or the specified segment does not exits, an empty string + is returned. + */ + OUString getName(sal_Int32 nIndex = LAST_SEGMENT, + bool bIgnoreFinalSlash = true, + DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + const; + + /** Set the name of the last segment (preserving any parameters and any query or + fragment part). + + @param rTheName The new name. + + @param eMechanism See the general discussion for get-methods. + + @param eCharset See the general discussion for get-methods. + + @return True if the name has successfully been modified (and the + resulting URI is still valid). If the path is not hierarchical, or + a last segment does not exist, false is returned. If false is + returned, the object is not modified. + */ + bool setName(std::u16string_view rTheName, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + /** Get the base of the name of a segment. + + @param nIndex The non-negative index of the segment, or LAST_SEGMENT + if addressing the last segment. + + @param bIgnoreFinalSlash If true, a final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @param eMechanism See the general discussion for get-methods. + + @param eCharset See the general discussion for get-methods. + + @return The base part of the specified segment. If the path is + not hierarchical, or the specified segment does not exits, an empty + string is returned. + */ + OUString getBase(sal_Int32 nIndex = LAST_SEGMENT, + bool bIgnoreFinalSlash = true, + DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + const; + + /** Set the base of the name of a segment (preserving the extension). + A final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @param rTheBase The new base. + + @param nIndex The non-negative index of the segment, or LAST_SEGMENT + if addressing the last segment. + + @param eMechanism See the general discussion for set-methods. + + @param eCharset See the general discussion for set-methods. + + @return True if the base has successfully been modified (and the + resulting URI is still valid). If the path is not hierarchical, or + the specified segment does not exist, false is returned. If false is + returned, the object is not modified. + */ + bool setBase(std::u16string_view rTheBase, + sal_Int32 nIndex = LAST_SEGMENT, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + /** Determine whether the name of the last segment has an extension. + + @return True if the name of the specified segment has an extension. + If the path is not hierarchical, or the specified segment does not + exist, false is returned. + */ + bool hasExtension() const; + + /** Get the extension of the name of a segment. + + @param nIndex The non-negative index of the segment, or LAST_SEGMENT + if addressing the last segment. + + @param bIgnoreFinalSlash If true, a final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @param eMechanism See the general discussion for get-methods. + + @param eCharset See the general discussion for get-methods. + + @return The extension part of the specified segment. If the path is + not hierarchical, or the specified segment does not exits, an empty + string is returned. + */ + OUString getExtension(sal_Int32 nIndex = LAST_SEGMENT, + bool bIgnoreFinalSlash = true, + DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + const; + + /** Set the extension of the name of a segment (replacing an already + existing extension). + + @param rTheExtension The new extension. + + @param nIndex The non-negative index of the segment, or LAST_SEGMENT + if addressing the last segment. + + @param bIgnoreFinalSlash If true, a final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @param eCharset See the general discussion for set-methods. + + @return True if the extension has successfully been modified (and the + resulting URI is still valid). If the path is not hierarchical, or + the specified segment does not exist, false is returned. If false is + returned, the object is not modified. + */ + bool setExtension(std::u16string_view rTheExtension, + sal_Int32 nIndex = LAST_SEGMENT, + bool bIgnoreFinalSlash = true, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + /** Remove the extension of the name of a segment. + + @param nIndex The non-negative index of the segment, or LAST_SEGMENT + if addressing the last segment. + + @param bIgnoreFinalSlash If true, a final slash at the end of the + hierarchical path does not denote an empty segment, but is ignored. + + @return True if the extension has successfully been removed (and the + resulting URI is still valid), or if the name did not have an + extension. If the path is not hierarchical, or the specified segment + does not exist, false is returned. If false is returned, the object + is not modified. + */ + bool removeExtension(sal_Int32 nIndex = LAST_SEGMENT, + bool bIgnoreFinalSlash = true); + + /** Determine whether the hierarchical path ends in a final slash. + + @return True if the hierarchical path ends in a final slash. If the + path is not hierarchical, false is returned. + */ + bool hasFinalSlash() const; + + /** Make the hierarchical path end in a final slash (if it does not + already do so). + + @return True if a final slash has successfully been appended (and the + resulting URI is still valid), or if the hierarchical path already + ended in a final slash. If the path is not hierarchical, false is + returned. If false is returned, the object is not modified. + */ + bool setFinalSlash(); + + /** Remove a final slash from the hierarchical path. + + @return True if a final slash has successfully been removed (and the + resulting URI is still valid), or if the hierarchical path already did + not end in a final slash. If the path is not hierarchical, false is + returned. If false is returned, the object is not modified. + */ + bool removeFinalSlash(); + + // Query: + + bool HasParam() const { return m_aQuery.isPresent(); } + + OUString GetParam(rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8) const + { return decode(m_aQuery, DecodeMechanism::NONE, eCharset); } + + inline bool SetParam(std::u16string_view rTheQuery, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + // Fragment: + + bool HasMark() const { return m_aFragment.isPresent(); } + + OUString GetMark(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8) const + { return decode(m_aFragment, eMechanism, eCharset); } + + inline bool SetMark(std::u16string_view rTheFragment, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + // File URLs: + + /** Return the file system path represented by a file URL (ignoring any + fragment part). + + @param eStyle The notation of the returned file system path. + + @param pDelimiter Upon successful return, this parameter can return + the character that is the 'main' delimiter within the returned file + system path (e.g., "/" for Unix, "\" for DOS). This is + especially useful for routines that later try to shorten the returned + file system path at a 'good' position, e.g. to fit it into some + limited display space. + + @return The file system path represented by this file URL. If this + file URL does not represent a file system path according to the + specified notation, or if this is not a file URL at all, an empty + string is returned. + */ + OUString getFSysPath(FSysStyle eStyle, sal_Unicode * pDelimiter = nullptr) + const; + + // Data URLs: + std::unique_ptr<SvMemoryStream> getData() const; + + // Coding: + + enum Part + { + PART_USER_PASSWORD = 0x00001, + PART_FPATH = 0x00008, + PART_AUTHORITY = 0x00010, + PART_REL_SEGMENT_EXTRA = 0x00020, + PART_URIC = 0x00040, + PART_HTTP_PATH = 0x00080, + PART_MESSAGE_ID_PATH = 0x00100, + PART_MAILTO = 0x00200, + PART_PATH_BEFORE_QUERY = 0x00400, + PART_PCHAR = 0x00800, + PART_VISIBLE = 0x01000, + PART_VISIBLE_NONSPECIAL = 0x02000, + PART_UNO_PARAM_VALUE = 0x04000, + PART_UNAMBIGUOUS = 0x08000, + PART_URIC_NO_SLASH = 0x10000, + PART_HTTP_QUERY = 0x20000, //TODO! unused? + }; + + enum class EscapeType + { + NONE, + Octet, + Utf32 + }; + + /** Encode some text as part of a URI. + + @param rText Some text (for its interpretation, see the general + discussion for set-methods). + + @param ePart The part says which characters are 'forbidden' and must + be encoded (replaced by escape sequences). Characters outside the US- + ASCII range are always 'forbidden.' + + @param eMechanism See the general discussion for set-methods. + + @param eCharset See the general discussion for set-methods. + + @return The text, encoded according to the given mechanism and + charset ('forbidden' characters replaced by escape sequences). + */ + static OUString encode( std::u16string_view rText, Part ePart, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8); + + + /** Decode some text. + + @param rText Some (encoded) text. + + @param eMechanism See the general discussion for get-methods. + + @param eCharset See the general discussion for get-methods. + + @return The text, decoded according to the given mechanism and + charset (escape sequences replaced by 'raw' characters). + */ + static inline OUString decode(std::u16string_view rText, + DecodeMechanism eMechanism, + rtl_TextEncoding eCharset + = RTL_TEXTENCODING_UTF8); + + static void appendUCS4Escape(OUStringBuffer & rTheText, sal_uInt32 nUCS4); + + static void appendUCS4(OUStringBuffer & rTheText, sal_uInt32 nUCS4, + EscapeType eEscapeType, Part ePart, + rtl_TextEncoding eCharset, bool bKeepVisibleEscapes); + + static sal_uInt32 getUTF32(sal_Unicode const *& rBegin, + sal_Unicode const * pEnd, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset, + EscapeType & rEscapeType); + + // Specialized helpers: + + static sal_uInt32 scanDomain(sal_Unicode const *& rBegin, + sal_Unicode const * pEnd, + bool bEager = true); + + // OBSOLETE Hierarchical Path: + + OUString GetPartBeforeLastName() const; + + /** Get the last segment in the path. + + @param eMechanism See the general discussion for get-methods. + + @param eCharset See the general discussion for get-methods. + + @return For a hierarchical URL, the last segment (everything after + the last unencoded '/'). Note that this last segment may be empty. If + the URL is not hierarchical, an empty string is returned. + */ + OUString GetLastName(DecodeMechanism eMechanism = DecodeMechanism::ToIUri, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8) + const; + + /** Get the 'extension' of the last segment in the path. + + @return For a hierarchical URL, everything after the first unencoded + '.' in the last segment of the path. Note that this 'extension' may + be empty. If the URL is not hierarchical, or if the last segment does + not contain an unencoded '.', an empty string is returned. + */ + OUString GetFileExtension() const; + + bool Append(std::u16string_view rTheSegment, + EncodeMechanism eMechanism = EncodeMechanism::WasEncoded, + rtl_TextEncoding eCharset = RTL_TEXTENCODING_UTF8); + + void CutLastName(); + + // OBSOLETE File URLs: + + OUString PathToFileName() const; + + OUString GetFull() const; + + OUString GetPath() const; + + void SetBase(std::u16string_view rTheBase); + + OUString GetBase() const; + + void SetExtension(std::u16string_view rTheExtension); + + OUString CutExtension(); + + static bool IsCaseSensitive() { return true; } + + void changeScheme(INetProtocol eTargetScheme); + + // INetProtocol::Macro, INetProtocol::Uno, INetProtocol::Slot, + // vnd.sun.star.script, etc. All the types of URLs which shouldn't + // be accepted from an outside controlled source + bool IsExoticProtocol() const; + +private: + // General Structure: + + class SAL_DLLPRIVATE SubString + { + sal_Int32 m_nBegin; + sal_Int32 m_nLength; + + public: + explicit SubString(sal_Int32 nTheBegin = -1, + sal_Int32 nTheLength = 0): + m_nBegin(nTheBegin), m_nLength(nTheLength) {} + + bool isPresent() const { return m_nBegin != -1; } + + bool isEmpty() const { return m_nLength == 0; } + + sal_Int32 getBegin() const { return m_nBegin; } + + sal_Int32 getLength() const { return m_nLength; } + + sal_Int32 getEnd() const { return m_nBegin + m_nLength; } + + sal_Int32 clear(); + + sal_Int32 set(OUStringBuffer & rString, + std::u16string_view rSubString, + sal_Int32 nTheBegin); + + sal_Int32 set(OUString & rString, + std::u16string_view rSubString); + + sal_Int32 set(OUStringBuffer & rString, + std::u16string_view rSubString); + + inline void operator +=(sal_Int32 nDelta); + + int compare(SubString const & rOther, + OUStringBuffer const & rThisString, + OUStringBuffer const & rOtherString) const; + }; + + OUStringBuffer m_aAbsURIRef; + SubString m_aScheme; + SubString m_aUser; + SubString m_aAuth; + SubString m_aHost; + SubString m_aPort; + SubString m_aPath; + SubString m_aQuery; + SubString m_aFragment; + INetProtocol m_eScheme; + INetProtocol m_eSmartScheme; + + TOOLS_DLLPRIVATE void setInvalid(); + + bool setAbsURIRef( + std::u16string_view rTheAbsURIRef, + EncodeMechanism eMechanism, rtl_TextEncoding eCharset, bool bSmart, + FSysStyle eStyle); + + // Relative URLs: + + bool convertRelToAbs( + OUString const & rTheRelURIRef, + INetURLObject & rTheAbsURIRef, bool & rWasAbsolute, + EncodeMechanism eMechanism, rtl_TextEncoding eCharset, + bool bIgnoreFragment, bool bSmart, bool bRelativeNonURIs, + FSysStyle eStyle) const; + + bool convertAbsToRel( + OUString const & rTheAbsURIRef, + OUString & rTheRelURIRef, EncodeMechanism eEncodeMechanism, + DecodeMechanism eDecodeMechanism, rtl_TextEncoding eCharset, + FSysStyle eStyle) const; + + // External URLs: + + static bool convertIntToExt( + std::u16string_view rTheIntURIRef, + OUString & rTheExtURIRef, DecodeMechanism eDecodeMechanism, + rtl_TextEncoding eCharset); + + static bool convertExtToInt( + std::u16string_view rTheExtURIRef, + OUString & rTheIntURIRef, DecodeMechanism eDecodeMechanism, + rtl_TextEncoding eCharset); + + // Scheme: + + struct PrefixInfo; + + TOOLS_DLLPRIVATE static inline SchemeInfo const & getSchemeInfo( + INetProtocol eTheScheme); + + TOOLS_DLLPRIVATE inline SchemeInfo const & getSchemeInfo() const; + + TOOLS_DLLPRIVATE static PrefixInfo const * getPrefix( + sal_Unicode const *& rBegin, sal_Unicode const * pEnd); + + // Authority: + + TOOLS_DLLPRIVATE sal_Int32 getAuthorityBegin() const; + + TOOLS_DLLPRIVATE SubString getAuthority() const; + + // User Info: + + bool setUser( + std::u16string_view rTheUser, + rtl_TextEncoding eCharset); + + bool clearPassword(); + + bool setPassword( + std::u16string_view rThePassword, + rtl_TextEncoding eCharset); + + // Host and Port: + + TOOLS_DLLPRIVATE static bool parseHost( + sal_Unicode const *& rBegin, sal_Unicode const * pEnd, + OUStringBuffer* pCanonic); + + TOOLS_DLLPRIVATE static bool parseHostOrNetBiosName( + sal_Unicode const * pBegin, sal_Unicode const * pEnd, + EncodeMechanism eMechanism, rtl_TextEncoding eCharset, + bool bNetBiosName, OUStringBuffer* pCanonic); + + bool setHost( + std::u16string_view rTheHost, + rtl_TextEncoding eCharset); + + // Path: + + TOOLS_DLLPRIVATE static bool parsePath( + INetProtocol eScheme, sal_Unicode const ** pBegin, + sal_Unicode const * pEnd, EncodeMechanism eMechanism, + rtl_TextEncoding eCharset, bool bSkippedInitialSlash, + sal_uInt32 nSegmentDelimiter, sal_uInt32 nAltSegmentDelimiter, + sal_uInt32 nQueryDelimiter, sal_uInt32 nFragmentDelimiter, + OUStringBuffer &rSynPath); + + bool setPath( + std::u16string_view rThePath, + EncodeMechanism eMechanism, rtl_TextEncoding eCharset); + + // Hierarchical Path: + + TOOLS_DLLPRIVATE bool checkHierarchical() const; + + TOOLS_DLLPRIVATE SubString getSegment( + sal_Int32 nIndex, bool bIgnoreFinalSlash) const; + + // Query: + + void clearQuery(); + + bool setQuery( + std::u16string_view rTheQuery, + EncodeMechanism eMechanism, rtl_TextEncoding eCharset); + + // Fragment: + + bool clearFragment(); + + bool setFragment( + std::u16string_view rTheMark, + EncodeMechanism eMechanism, rtl_TextEncoding eCharset); + + // FILE URLs: + + TOOLS_DLLPRIVATE bool hasDosVolume(FSysStyle eStyle) const; + + // Coding: + + TOOLS_DLLPRIVATE static inline void appendEscape( + OUStringBuffer & rTheText, sal_uInt32 nOctet); + + static void encodeText( + OUStringBuffer& rOutputBuffer, + sal_Unicode const * pBegin, sal_Unicode const * pEnd, + Part ePart, EncodeMechanism eMechanism, rtl_TextEncoding eCharset, + bool bKeepVisibleEscapes); + + static inline void encodeText( + OUStringBuffer& rOutputBuffer, + std::u16string_view rTheText, Part ePart, + EncodeMechanism eMechanism, rtl_TextEncoding eCharset, + bool bKeepVisibleEscapes); + + static OUString decode( + sal_Unicode const * pBegin, sal_Unicode const * pEnd, + DecodeMechanism, rtl_TextEncoding eCharset); + + inline OUString decode( + SubString const & rSubString, + DecodeMechanism eMechanism, rtl_TextEncoding eCharset) const; + + // Specialized helpers: + + TOOLS_DLLPRIVATE static bool scanIPv6reference( + sal_Unicode const *& rBegin, sal_Unicode const * pEnd); +}; + +// static +inline void INetURLObject::encodeText( OUStringBuffer& rOutputBuffer, + std::u16string_view rTheText, + Part ePart, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset, + bool bKeepVisibleEscapes) +{ + encodeText(rOutputBuffer, + rTheText.data(), + rTheText.data() + rTheText.size(), ePart, + eMechanism, eCharset, bKeepVisibleEscapes); +} + +inline OUString INetURLObject::decode(SubString const & rSubString, + DecodeMechanism eMechanism, + rtl_TextEncoding eCharset) const +{ + return rSubString.isPresent() ? + decode(m_aAbsURIRef.getStr() + rSubString.getBegin(), + m_aAbsURIRef.getStr() + rSubString.getEnd(), + eMechanism, eCharset) : + OUString(); +} + +inline INetURLObject::INetURLObject(std::u16string_view rTheAbsURIRef, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset): + m_aAbsURIRef(rTheAbsURIRef.size() * 2), m_eScheme(INetProtocol::NotValid), m_eSmartScheme(INetProtocol::Http) +{ + setAbsURIRef(rTheAbsURIRef, eMechanism, eCharset, false, + FSysStyle(0)); +} + +inline bool INetURLObject::SetURL(std::u16string_view rTheAbsURIRef, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset) +{ + return setAbsURIRef(rTheAbsURIRef, eMechanism, eCharset, false, + FSysStyle(0)); +} + +inline INetURLObject::INetURLObject(std::u16string_view rTheAbsURIRef, + INetProtocol eTheSmartScheme, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset, + FSysStyle eStyle): + m_eScheme(INetProtocol::NotValid), m_eSmartScheme(eTheSmartScheme) +{ + setAbsURIRef(rTheAbsURIRef, eMechanism, eCharset, true, eStyle); +} + +inline bool INetURLObject::SetSmartURL(std::u16string_view rTheAbsURIRef, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset, + FSysStyle eStyle) +{ + return setAbsURIRef(rTheAbsURIRef, eMechanism, eCharset, true, + eStyle); +} + +inline INetURLObject +INetURLObject::smartRel2Abs(OUString const & rTheRelURIRef, + bool & rWasAbsolute, + bool bIgnoreFragment, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset, + bool bRelativeNonURIs, + FSysStyle eStyle) const +{ + INetURLObject aTheAbsURIRef; + convertRelToAbs(rTheRelURIRef, aTheAbsURIRef, rWasAbsolute, + eMechanism, eCharset, bIgnoreFragment, true, + bRelativeNonURIs, eStyle); + return aTheAbsURIRef; +} + +inline bool INetURLObject::GetNewAbsURL(OUString const & rTheRelURIRef, + INetURLObject * pTheAbsURIRef) + const +{ + INetURLObject aTheAbsURIRef; + bool bWasAbsolute; + if (!convertRelToAbs(rTheRelURIRef, aTheAbsURIRef, bWasAbsolute, + EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, false/*bIgnoreFragment*/, false, false, + FSysStyle::Detect)) + return false; + if (pTheAbsURIRef) + *pTheAbsURIRef = aTheAbsURIRef; + return true; +} + +// static +inline OUString INetURLObject::GetRelURL(std::u16string_view rTheBaseURIRef, + OUString const & rTheAbsURIRef, + EncodeMechanism eEncodeMechanism, + DecodeMechanism eDecodeMechanism, + rtl_TextEncoding eCharset, + FSysStyle eStyle) +{ + OUString aTheRelURIRef; + INetURLObject(rTheBaseURIRef, eEncodeMechanism, eCharset). + convertAbsToRel(rTheAbsURIRef, aTheRelURIRef, eEncodeMechanism, + eDecodeMechanism, eCharset, eStyle); + return aTheRelURIRef; +} + +// static +inline bool INetURLObject::translateToExternal(std::u16string_view + rTheIntURIRef, + OUString & rTheExtURIRef, + DecodeMechanism + eDecodeMechanism, + rtl_TextEncoding eCharset) +{ + return convertIntToExt(rTheIntURIRef, rTheExtURIRef, + eDecodeMechanism, eCharset); +} + +// static +inline bool INetURLObject::translateToInternal(std::u16string_view + rTheExtURIRef, + OUString & rTheIntURIRef, + DecodeMechanism + eDecodeMechanism, + rtl_TextEncoding eCharset) +{ + return convertExtToInt(rTheExtURIRef, rTheIntURIRef, + eDecodeMechanism, eCharset); +} + +inline bool INetURLObject::SetPass(std::u16string_view rThePassword) +{ + return rThePassword.empty() ? + clearPassword() : + setPassword(rThePassword, RTL_TEXTENCODING_UTF8); +} + +inline bool INetURLObject::SetParam(std::u16string_view rTheQuery, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset) +{ + if (rTheQuery.empty()) + { + clearQuery(); + return false; + } + return setQuery(rTheQuery, eMechanism, eCharset); +} + +inline bool INetURLObject::SetMark(std::u16string_view rTheFragment, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset) +{ + return rTheFragment.empty() ? + clearFragment() : + setFragment(rTheFragment, eMechanism, eCharset); +} + +// static +inline OUString INetURLObject::encode(std::u16string_view rText, Part ePart, + EncodeMechanism eMechanism, + rtl_TextEncoding eCharset) +{ + OUStringBuffer aBuf; + encodeText(aBuf, rText, ePart, eMechanism, eCharset, false); + return aBuf.makeStringAndClear(); +} + +// static +inline OUString INetURLObject::decode(std::u16string_view rText, + DecodeMechanism eMechanism, + rtl_TextEncoding eCharset) +{ + return decode(rText.data(), rText.data() + rText.size(), + eMechanism, eCharset); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/vcompat.hxx b/include/tools/vcompat.hxx new file mode 100644 index 0000000000..39cd0cd0bd --- /dev/null +++ b/include/tools/vcompat.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_VCOMPAT_HXX +#define INCLUDED_TOOLS_VCOMPAT_HXX + +#include <tools/toolsdllapi.h> + +inline sal_uInt32 COMPAT_FORMAT(char char1, char char2, char char3, char char4) +{ + return static_cast<sal_uInt32>(char1) | (static_cast<sal_uInt32>(char2) << 8) + | (static_cast<sal_uInt32>(char3) << 16) | (static_cast<sal_uInt32>(char4) << 24); +}; + +class SvStream; + +class TOOLS_DLLPUBLIC VersionCompatRead +{ + SvStream& mrRStm; + sal_uInt32 mnCompatPos; + sal_uInt32 mnTotalSize; + sal_uInt16 mnVersion; + + VersionCompatRead(const VersionCompatRead&) = delete; + VersionCompatRead& operator=(const VersionCompatRead&) = delete; + +public: + VersionCompatRead(SvStream& rStm); + ~VersionCompatRead(); + + sal_uInt16 GetVersion() const { return mnVersion; } +}; + +class TOOLS_DLLPUBLIC VersionCompatWrite +{ + SvStream& mrWStm; + sal_uInt32 mnCompatPos; + sal_uInt32 mnTotalSize; + + VersionCompatWrite(const VersionCompatWrite&) = delete; + VersionCompatWrite& operator=(const VersionCompatWrite&) = delete; + +public: + VersionCompatWrite(SvStream& rStm, sal_uInt16 nVersion = 1); + ~VersionCompatWrite(); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/weakbase.h b/include/tools/weakbase.h new file mode 100644 index 0000000000..f5a79e635b --- /dev/null +++ b/include/tools/weakbase.h @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_WEAKBASE_H +#define INCLUDED_TOOLS_WEAKBASE_H + +#include <sal/types.h> +#include <rtl/ref.hxx> +#include <tools/toolsdllapi.h> + +/** the template classes in this header are helper to implement weak references + to implementation objects that are not refcounted. + + THIS IS NOT THREADSAFE + + Use this only to have 'safe' pointers to implementation objects that you + don't own but that you reference with a pointer. + + Example: + + class ImplClass : public tools::WeakBase< ImplClass > + { + ~ImplClass() { clearWeek(); } // not needed but safer, see method description + ... + }; + + class UserClass + { + tools::WeakReference< ImplClass > mxWeakRef; + + UserClass( ImplClass* pObject ) : mxWeakRef( pObject ) {} + + DoSomething() + { + if( mxWeakRef.is() ) + mxWeakRef->DoSomethingMore(); + } + }; +*/ +namespace tools +{ +class WeakBase; + +/** private connection helper, do not use directly */ +struct WeakConnection +{ + sal_Int32 mnRefCount; + WeakBase* mpReference; + + WeakConnection() : mnRefCount( 0 ), mpReference( nullptr ) {}; + WeakConnection( WeakBase* pReference ) : mnRefCount( 0 ), mpReference( pReference ) {}; + void acquire() { mnRefCount++; } + void release() { mnRefCount--; if( mnRefCount == 0 ) delete this; } +}; + +/** template implementation to hold a weak reference to an instance of type reference_type */ +template <class reference_type> +class SAL_WARN_UNUSED WeakReference +{ +public: + /** constructs an empty reference */ + inline WeakReference(); + + /** constructs a reference with a pointer to a class derived from WeakBase */ + inline WeakReference( reference_type* pReference ); + + /** constructs a reference from another reference */ + inline WeakReference( const WeakReference< reference_type >& rWeakRef ); + + /** move a reference from another reference */ + inline WeakReference( WeakReference< reference_type >&& rWeakRef ); + + /** returns true if the reference object is not null and still alive */ + inline bool is() const; + + /** returns true if the reference object is not null and still alive */ + operator bool() const { return is(); } + + /** returns the pointer to the reference object or null */ + inline reference_type * get() const; + + /** sets this reference to the given object or null */ + inline void reset( reference_type* pReference ); + + /** resets this reference to null */ + inline void reset(); + + /** returns the pointer to the reference object or null */ + inline reference_type * operator->() const; + + /** returns a ref to the reference object */ + inline reference_type& operator*() const; + + /** returns true if this instance references pReferenceObject */ + inline bool operator== (const reference_type * pReferenceObject) const; + + /** returns true if this instance and the given weakref reference the same object */ + inline bool operator== (const WeakReference<reference_type> & handle) const; + + /** only needed for using this class with stl containers */ + inline bool operator!= (const WeakReference<reference_type> & handle) const; + + /** only needed for using this class with stl containers */ + inline bool operator< (const WeakReference<reference_type> & handle) const; + + /** only needed for using this class with stl containers */ + inline bool operator> (const WeakReference<reference_type> & handle) const; + + /** the assignment operator */ + inline WeakReference<reference_type>& operator= (const WeakReference<reference_type> & handle); + + /** the move assignment operator */ + inline WeakReference<reference_type>& operator= (WeakReference<reference_type> && handle); + +private: + rtl::Reference<WeakConnection> mpWeakConnection; +}; + +/** derive your implementation classes from this class if you want them to support weak references */ +class TOOLS_DLLPUBLIC WeakBase +{ + template<typename T> friend class WeakReference; + +public: + WeakBase() {} + virtual ~WeakBase(); + /** clears the reference pointer in all living weak references for this instance. + Further created weak references will also be invalid. + You should call this method in the d'tor of your derived classes for an early + invalidate of all living weak references while your object is already inside + it d'tor. + */ + inline void clearWeak(); + +private: + inline WeakConnection* getWeakConnection(); + rtl::Reference<WeakConnection> mpWeakConnection; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/weakbase.hxx b/include/tools/weakbase.hxx new file mode 100644 index 0000000000..ca6bdc37e6 --- /dev/null +++ b/include/tools/weakbase.hxx @@ -0,0 +1,162 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_TOOLS_WEAKBASE_HXX +#define INCLUDED_TOOLS_WEAKBASE_HXX + +#include <tools/weakbase.h> + +/// see weakbase.h for documentation + +namespace tools +{ + +template< class reference_type > +inline WeakReference< reference_type >::WeakReference() +{ + mpWeakConnection = new WeakConnection; +} + +template< class reference_type > +inline WeakReference< reference_type >::WeakReference( reference_type* pReference ) +{ + reset( pReference ); +} + +template< class reference_type > +inline WeakReference< reference_type >::WeakReference( const WeakReference< reference_type >& rWeakRef ) +{ + mpWeakConnection = rWeakRef.mpWeakConnection; +} + +template< class reference_type > +inline WeakReference< reference_type >::WeakReference( WeakReference< reference_type >&& rWeakRef ) +{ + mpWeakConnection = std::move(rWeakRef.mpWeakConnection); + rWeakRef.reset(); +} + +template< class reference_type > +inline bool WeakReference< reference_type >::is() const +{ + return mpWeakConnection->mpReference != nullptr; +} + +template< class reference_type > +inline reference_type * WeakReference< reference_type >::get() const +{ + auto pWeakBase = mpWeakConnection->mpReference; + if (!pWeakBase) + return nullptr; + assert(dynamic_cast<reference_type *>(pWeakBase)); + return static_cast<reference_type *>(pWeakBase); +} + +template< class reference_type > +inline void WeakReference< reference_type >::reset( reference_type* pReference ) +{ + if( pReference ) + mpWeakConnection = pReference->getWeakConnection(); + else + reset(); +} + +template< class reference_type > +inline void WeakReference< reference_type >::reset() +{ + mpWeakConnection = new WeakConnection; +} + +template< class reference_type > +inline reference_type * WeakReference< reference_type >::operator->() const +{ + return get(); +} + +template< class reference_type > +inline reference_type& WeakReference< reference_type >::operator*() const +{ + return *get(); +} + +template< class reference_type > +inline bool WeakReference< reference_type >::operator==(const reference_type * pReferenceObject) const +{ + return mpWeakConnection->mpReference == pReferenceObject; +} + +template< class reference_type > +inline bool WeakReference< reference_type >::operator==(const WeakReference<reference_type> & handle) const +{ + return mpWeakConnection == handle.mpWeakConnection; +} + +template< class reference_type > +inline bool WeakReference< reference_type >::operator!=(const WeakReference<reference_type> & handle) const +{ + return mpWeakConnection != handle.mpWeakConnection; +} + +template< class reference_type > +inline bool WeakReference< reference_type >::operator<(const WeakReference<reference_type> & handle) const +{ + return mpWeakConnection->mpReference < handle.mpWeakConnection->mpReference; +} + +template< class reference_type > +inline bool WeakReference< reference_type >::operator>(const WeakReference<reference_type> & handle) const +{ + return mpWeakConnection->mpReference > handle.mpWeakConnection->mpReference; +} + +template< class reference_type > +inline WeakReference<reference_type>& WeakReference<reference_type>::operator= ( + const WeakReference<reference_type>& rReference) +{ + if (&rReference != this) + mpWeakConnection = rReference.mpWeakConnection; + return *this; +} + +template< class reference_type > +inline WeakReference<reference_type>& WeakReference<reference_type>::operator= ( + WeakReference<reference_type>&& rReference) +{ + mpWeakConnection = std::move(rReference.mpWeakConnection); + return *this; +} + +inline void WeakBase::clearWeak() +{ + if( mpWeakConnection.is() ) + mpWeakConnection->mpReference = nullptr; +} + +inline WeakConnection* WeakBase::getWeakConnection() +{ + if( !mpWeakConnection.is() ) + mpWeakConnection = new WeakConnection( this ); + return mpWeakConnection.get(); +} + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/wldcrd.hxx b/include/tools/wldcrd.hxx new file mode 100644 index 0000000000..5c18ad20fc --- /dev/null +++ b/include/tools/wldcrd.hxx @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_TOOLS_WLDCRD_HXX +#define INCLUDED_TOOLS_WLDCRD_HXX + +#include <sal/config.h> + +#include <string_view> + +#include <tools/toolsdllapi.h> +#include <rtl/ustring.hxx> + +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC WildCard +{ +private: + OUString aWildString; + char cSepSymbol; + + static bool ImpMatch( std::u16string_view aWild, std::u16string_view aStr ); + +public: + WildCard() + : aWildString('*') + , cSepSymbol('\0') + { + } + + WildCard(std::u16string_view rWildCard, const char cSeparator = '\0') + : aWildString(rWildCard) + , cSepSymbol(cSeparator) + { + } + + const OUString & getGlob() const + { + return aWildString; + } + + void setGlob(std::u16string_view rString) + { + aWildString = rString; + } + + bool Matches( std::u16string_view rStr ) const; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/tools/zcodec.hxx b/include/tools/zcodec.hxx new file mode 100644 index 0000000000..a86dbec70b --- /dev/null +++ b/include/tools/zcodec.hxx @@ -0,0 +1,96 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_TOOLS_ZCODEC_HXX +#define INCLUDED_TOOLS_ZCODEC_HXX + +#include <tools/toolsdllapi.h> +#include <tools/long.hxx> +#include <memory> +#include <rtl/string.hxx> + +#define ZCODEC_NO_COMPRESSION 0 +#define ZCODEC_DEFAULT_COMPRESSION 6 + +class SvStream; + +// The overall client call protocol is one of: +// * BeginCompression, Compress, EndCompression +// * BeginCompression, SetCompressionMetadata, Compress, EndCompression (for gz files) +// * BeginCompression, Decompress, EndCompression +// * BeginCompression, Write*, EndCompression +// * BeginCompression, Read*, EndCompression +// * BeginCompression, ReadAsynchron*, EndCompression +class SAL_WARN_UNUSED TOOLS_DLLPUBLIC ZCodec +{ + enum State { STATE_INIT, STATE_DECOMPRESS, STATE_COMPRESS }; + State meState; + bool mbStatus; + bool mbFinish; + std::unique_ptr<sal_uInt8[]> mpInBuf; + size_t mnInBufSize; + size_t mnInToRead; + SvStream* mpOStm; + std::unique_ptr<sal_uInt8[]> mpOutBuf; + size_t mnOutBufSize; + sal_uInt32 mnUncompressedSize; + sal_uInt32 mnInBufCRC32; + sal_uInt32 mnLastModifiedTime; + OString msFilename; + + int mnCompressLevel; + bool mbGzLib; + void* mpsC_Stream; + + void InitCompress(); + void InitDecompress(SvStream & inStream); + void ImplWriteBack(); + +public: + ZCodec( size_t nInBufSize = 32768, size_t nOutBufSize = 32768 ); + ~ZCodec(); + /** + * @brief Checks whether a stream is Z compressed + * + * @param rIStm the stream to check + */ + static bool IsZCompressed( SvStream& rIStm ); + + void BeginCompression( int nCompressLevel = ZCODEC_DEFAULT_COMPRESSION, bool gzLib = false ); + tools::Long EndCompression(); + + /** + * @brief Set metadata for gzlib compression + * + * @param sFilename the uncompressed file filename + * @param nLastModifiedTime the files last modified time in unix format + */ + void SetCompressionMetadata( const OString& sFilename, + sal_uInt32 nLastModifiedTime, sal_uInt32 nInBufCRC32 ); + void Compress( SvStream& rIStm, SvStream& rOStm ); + tools::Long Decompress( SvStream& rIStm, SvStream& rOStm ); + bool AttemptDecompression( SvStream& rIStm, SvStream& rOStm ); + + void Write( SvStream& rOStm, const sal_uInt8* pData, sal_uInt32 nSize ); + tools::Long Read( SvStream& rIStm, sal_uInt8* pData, sal_uInt32 nSize ); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |