File indexing completed on 2024-04-14 15:52:54

0001 /*
0002     This file is part of the Okteta Gui library, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2003, 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #ifndef OKTETA_COORD_HPP
0010 #define OKTETA_COORD_HPP
0011 
0012 // lib
0013 #include "lineposition.hpp"
0014 #include "line.hpp"
0015 // Okteta core
0016 #include <Okteta/Address>
0017 #include <Okteta/Size>
0018 
0019 namespace Okteta {
0020 
0021 /**
0022  * a class which represents a coord in a 2-dim. system
0023  *
0024  * It consists of a line number and a position in the line.
0025  * The coord starts at (0,0). Line numbers increase downwards, positions to the right.
0026  * With any of both at a negative number the coord is invalid.
0027  * The index at coord(0,0) is 0.
0028  *
0029  * @author Friedrich W. H. Kossebau
0030  */
0031 class Coord
0032 {
0033 public:
0034     /** constructs a section by width
0035      * @param index starting index
0036      * @param lineWidth width of the section
0037      */
0038     static Coord fromIndex(Address index, LinePositionSize lineWidth);
0039 
0040 public:
0041     /** creates a coord with 0,0 */
0042     Coord() = default;
0043     constexpr Coord(LinePosition pos, Line line);
0044     Coord(const Coord& other) = default;
0045     Coord& operator=(const Coord& other) = default;
0046 
0047     ~Coord() = default;
0048 
0049 public: // logic
0050     constexpr bool operator==(const Coord& other) const;
0051     constexpr bool operator!=(const Coord& other) const;
0052     constexpr bool operator<(const Coord& other) const;
0053     constexpr bool operator<=(const Coord& other) const;
0054     constexpr bool operator>(const Coord& other) const;
0055     constexpr bool operator>=(const Coord& other) const;
0056 
0057     /** tests if the coord is prior in the same line than the given coord.
0058      * If at least one of both is invalid the result is undefined.
0059      * @return true if the pos is left to the pos of other and both are in the same line, otherwise false.
0060      */
0061     constexpr bool isPriorInLineThan(const Coord& other) const;
0062     /** tests if the coord is later in the same line than the given coord.
0063      * If at least one of both is invalid the result is undefined.
0064      * @return true if the pos is right to the pos of other and both are in the same line, otherwise false
0065      */
0066     constexpr bool isLaterInLineThan(const Coord& other) const;
0067     /** @return true if the line is below lines, otherwise false */
0068     constexpr bool isBelow(Line line) const;
0069     /** @return true if the line is above lines, otherwise false */
0070     constexpr bool isAbove(Line line) const;
0071     /** @return true if the coord is at (0,0) */
0072     constexpr bool isAtStart() const;
0073     /** @return true if the pos is greater than 0, otherwise false */
0074     constexpr bool isBehindLineStart() const;
0075     /** @return true if the pos is smaller than maxPos, otherwise false */
0076     constexpr bool isBeforeLineEnd(LinePosition maxPos) const;
0077 
0078     /** calculates the index the coord is at with a given line width
0079      * If the coord is invalid the result is undefined.
0080      * @param lineWidth given width of line
0081      * @return index the coord is at
0082      */
0083     constexpr Address indexByLineWidth(LinePositionSize lineWidth) const;
0084 
0085 public:
0086     /** set the coord by calculating it for an index with a given line width
0087      * @param index index in the buffer
0088      * @param lineWidth given line width
0089      */
0090     void setByIndexNWidth(Address index, LinePositionSize lineWidth);
0091     /** sets both position and line */
0092     void set(LinePosition pos, Line line);
0093     /** sets the position */
0094     void setPos(LinePosition pos);
0095     /** sets the line */
0096     void setLine(Line line);
0097 
0098     /** moves the coord one position to the left. If the coord is invalid the result is undefined. */
0099     void goLeft();
0100     /** moves the coord a given number of positions to the left.
0101      * If the coord is invalid the result is undefined or the position smaller than the given number
0102      * the behaviour is undefined.
0103      * @param positions number of positions
0104      */
0105     void goLeft(LinePositionSize positions);
0106     /** moves the coord one position to the left, or if the position is already at the line start
0107      * to the given position in the previous line. If the coord is invalid the result is undefined.
0108      * @param maxPos maximal allowed position
0109      */
0110     void goCLeft(LinePosition maxPos);
0111     /** moves the coord one position to the right. If the coord is invalid the result is undefined. */
0112     void goRight();
0113     /** moves the coord a given number of positions to the right. If the coord is invalid the result is undefined.
0114      * @param positions number of positions
0115      */
0116     void goRight(LinePositionSize positions);
0117     /** moves the coord one position to the right, or if the position has already reached or passed maxPos
0118      * to the first position in the next line. If the coord is invalid the result is undefined.
0119      * @param maxPos maximal allowed position
0120      */
0121     void goCRight(LinePosition maxPos);
0122     /** sets coord to (0,0) */
0123     void gotoStart();
0124     void gotoEndOfPreviousLine(LinePosition lastPos);
0125     /** sets the coord to the start of the next line.
0126      * If the coord is invalid the behaviour is undefined.
0127      */
0128     void gotoStartOfNextLine();
0129     /** sets the position to the start of the line or
0130      * if the line is the same as that of the given coord to the position of it.
0131      * If one or more of the coords is invalid the behaviour is undefined.
0132      * @param other a possible line start coord
0133      */
0134     void goLineStart(const Coord& other);
0135     /** sets the position to the given pos or
0136      * if the line is the same as that of the given coord to the position of that.
0137      * If one or more of the coords is invalid the behaviour is undefined.
0138      * @param lastPos last position in normal line
0139      * @param other a possible line end coord
0140      */
0141     void goLineEnd(LinePosition lastPos, const Coord& other);
0142     /** moves the coord 1 lines upwards. There is no check whether the first line is overstepped. */
0143     void goUp();
0144     /** moves the coord lines lines downwards. */
0145     void goDown();
0146     /** moves the coord lines lines upwards. There is no check whether the first line is overstepped.
0147      * @param lines number of lines
0148      */
0149     void goUp(LineSize lines);
0150     /** moves the coord lines lines downwards.
0151      * @param lines number of lines
0152      */
0153     void goDown(LineSize lines);
0154 
0155 public: // state value access
0156     /** @return the pos in the line */
0157     constexpr LinePosition pos() const;
0158     /** @return the line number */
0159     constexpr Line line() const;
0160     /** @return true if the coord is valid */
0161     constexpr bool isValid() const;
0162 
0163 private: // member variables
0164     /** Position in mLine */
0165     LinePosition mPos = 0;
0166     /** mLine */
0167     Line mLine = 0;
0168 };
0169 
0170 inline constexpr Coord::Coord(LinePosition pos, Line line)
0171     : mPos(pos)
0172     , mLine(line)
0173 {}
0174 
0175 inline Coord Coord::fromIndex(Address index, LinePositionSize lineWidth)
0176 {
0177     const Line line = index / lineWidth;
0178     const LinePosition pos  = index - line * lineWidth;
0179     return Coord(pos, line);
0180 }
0181 
0182 inline constexpr bool Coord::operator==(const Coord& other) const { return mPos == other.mPos && mLine == other.mLine; }
0183 inline constexpr bool Coord::operator!=(const Coord& other) const { return !(*this == other); }
0184 
0185 inline constexpr bool Coord::operator<(const Coord& other) const
0186 { return mLine < other.mLine || (mLine == other.mLine && mPos < other.mPos); }
0187 inline constexpr bool Coord::operator<=(const Coord& other) const
0188 { return mLine < other.mLine || (mLine == other.mLine && mPos <= other.mPos); }
0189 inline constexpr bool Coord::operator>(const Coord& other) const
0190 { return mLine > other.mLine || (mLine == other.mLine && mPos > other.mPos); }
0191 inline constexpr bool Coord::operator>=(const Coord& other) const
0192 { return mLine > other.mLine || (mLine == other.mLine && mPos >= other.mPos); }
0193 
0194 inline constexpr LinePosition Coord::pos() const { return mPos; }
0195 inline constexpr Line Coord::line()        const { return mLine; }
0196 inline constexpr bool Coord::isValid()      const { return mLine >= 0 && mPos >= 0; }
0197 
0198 inline void Coord::setByIndexNWidth(Address index, LinePositionSize lineWidth)
0199 {
0200     mLine = index / lineWidth;
0201     mPos  = index - mLine * lineWidth;
0202 }
0203 
0204 inline void Coord::set(LinePosition pos, Line line)
0205 {
0206     mPos  = pos;
0207     mLine = line;
0208 }
0209 inline void Coord::setPos(LinePosition pos)  { mPos  = pos; }
0210 inline void Coord::setLine(Line line) { mLine = line; }
0211 
0212 inline void Coord::goCRight(LinePosition maxPos)
0213 {
0214     if (isBeforeLineEnd(maxPos)) {
0215         goRight();
0216     } else {
0217         gotoStartOfNextLine();
0218     }
0219 }
0220 inline void Coord::goCLeft(LinePosition maxPos)
0221 {
0222     if (isBehindLineStart()) {
0223         goLeft();
0224     } else {
0225         gotoEndOfPreviousLine(maxPos);
0226     }
0227 }
0228 
0229 inline void Coord::goRight() { ++mPos; }
0230 inline void Coord::goLeft()  { --mPos; }
0231 inline void Coord::goRight(LinePositionSize positions) { mPos += positions; }
0232 inline void Coord::goLeft(LinePositionSize positions)  { mPos -= positions; }
0233 
0234 inline void Coord::gotoStart() { mPos = mLine = 0; }
0235 
0236 inline void Coord::gotoEndOfPreviousLine(LinePosition lastPos)
0237 {
0238     --mLine;
0239     mPos = lastPos;
0240 }
0241 
0242 inline void Coord::gotoStartOfNextLine()
0243 {
0244     ++mLine;
0245     mPos = 0;
0246 }
0247 
0248 inline void Coord::goLineStart(const Coord& other)
0249 {
0250     mPos = (mLine == other.mLine) ? other.mPos : 0;
0251 }
0252 
0253 inline void Coord::goLineEnd(LinePosition lastPos, const Coord& other)
0254 {
0255     mPos = (mLine == other.mLine) ? other.mPos : lastPos;
0256 }
0257 
0258 inline void Coord::goUp()           { --mLine; }
0259 inline void Coord::goDown()         { ++mLine; }
0260 inline void Coord::goUp(LineSize lines)    { mLine -= lines; }
0261 inline void Coord::goDown(LineSize lines)  { mLine += lines; }
0262 
0263 inline constexpr Address Coord::indexByLineWidth(LinePositionSize lineWidth) const
0264 {
0265     return mLine * lineWidth + mPos;
0266 }
0267 
0268 inline constexpr bool Coord::isPriorInLineThan(const Coord& other) const
0269 {
0270     return mLine == other.mLine && mPos < other.mPos;
0271 }
0272 
0273 inline constexpr bool Coord::isLaterInLineThan(const Coord& other) const
0274 {
0275     return mLine == other.mLine && mPos > other.mPos;
0276 }
0277 
0278 inline constexpr bool Coord::isBelow(Line line) const { return mLine > line; }
0279 inline constexpr bool Coord::isAbove(Line line) const { return mLine < line; }
0280 
0281 inline constexpr bool Coord::isBehindLineStart()           const { return mPos > 0; }
0282 inline constexpr bool Coord::isBeforeLineEnd(LinePosition maxPos) const { return mPos < maxPos; }
0283 
0284 inline constexpr bool Coord::isAtStart()                   const { return mPos == 0 && mLine == 0; }
0285 
0286 inline Coord operator+(const Coord& other, LinePosition pos)
0287 {
0288     return Coord(other.pos() + pos, other.line());
0289 }
0290 
0291 }
0292 
0293 #endif