text_block_parser.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #pragma once
  8. #include "ui/text/text.h"
  9. #include "ui/text/text_block.h"
  10. namespace Ui::Text {
  11. struct QuoteDetails;
  12. class BlockParser {
  13. public:
  14. BlockParser(
  15. not_null<String*> string,
  16. const TextWithEntities &textWithEntities,
  17. const TextParseOptions &options,
  18. const MarkedContext &context);
  19. private:
  20. struct ReadyToken {
  21. };
  22. class StartedEntity {
  23. public:
  24. enum class Type {
  25. Flags,
  26. Link,
  27. IndexedLink,
  28. CustomEmoji,
  29. Colorized,
  30. };
  31. explicit StartedEntity(TextBlockFlags flags);
  32. explicit StartedEntity(uint16 index, Type type);
  33. [[nodiscard]] Type type() const;
  34. [[nodiscard]] std::optional<TextBlockFlags> flags() const;
  35. [[nodiscard]] std::optional<uint16> linkIndex() const;
  36. [[nodiscard]] std::optional<uint16> colorIndex() const;
  37. private:
  38. const int _value = 0;
  39. const Type _type;
  40. };
  41. BlockParser(
  42. not_null<String*> string,
  43. TextWithEntities &&source,
  44. const TextParseOptions &options,
  45. const MarkedContext &context,
  46. ReadyToken);
  47. void trimSourceRange();
  48. void createBlock(int skipBack = 0);
  49. void createNewlineBlock(bool fromOriginalText);
  50. void ensureAtNewline(QuoteDetails quote);
  51. // Returns true if at least one entity was parsed in the current position.
  52. bool checkEntities();
  53. void parseCurrentChar();
  54. void parseEmojiFromCurrent();
  55. void finalize(const TextParseOptions &options);
  56. void finishEntities();
  57. void skipPassedEntities();
  58. void skipBadEntities();
  59. bool isInvalidEntity(const EntityInText &entity) const;
  60. bool isLinkEntity(const EntityInText &entity) const;
  61. bool processCustomIndex(uint16 index);
  62. void parse(const TextParseOptions &options);
  63. void computeLinkText(
  64. const QString &linkData,
  65. QString *outLinkText,
  66. EntityLinkShown *outShown);
  67. const not_null<String*> _t;
  68. QString &_tText;
  69. std::vector<Block> &_tBlocks;
  70. const TextWithEntities _source;
  71. const MarkedContext &_context;
  72. const QChar * const _start = nullptr;
  73. const QChar *_end = nullptr; // mutable, because we trim by decrementing.
  74. const QChar *_ptr = nullptr;
  75. const EntitiesInText::const_iterator _entitiesEnd;
  76. EntitiesInText::const_iterator _waitingEntity;
  77. QString _customEmojiData;
  78. const bool _multiline = false;
  79. const bool _checkTilde = false; // do we need a special text block for tilde symbol
  80. std::vector<uint16> _linksIndexes;
  81. std::vector<EntityLinkData> _links;
  82. std::vector<EntityLinkData> _monos;
  83. base::flat_map<
  84. const QChar*,
  85. std::vector<StartedEntity>> _startedEntities;
  86. uint16 _maxLinkIndex = 0;
  87. uint16 _maxShiftedLinkIndex = 0;
  88. // current state
  89. TextBlockFlags _flags;
  90. uint16 _linkIndex = 0;
  91. uint16 _colorIndex = 0;
  92. uint16 _monoIndex = 0;
  93. uint16 _quoteIndex = 0;
  94. int _quoteStartPosition = 0;
  95. EmojiPtr _emoji = nullptr; // current emoji, if current word is an emoji, or zero
  96. int _blockStart = 0; // offset in result, from which current parsed block is started
  97. int _diacritics = 0; // diacritic chars skipped without good char
  98. bool _newlineAwaited = false;
  99. // current char data
  100. QChar _ch; // current char (low surrogate, if current char is surrogate pair)
  101. int _emojiLookback = 0; // how far behind the current ptr to look for current emoji
  102. bool _allowDiacritic = false; // did we add last char to the current block
  103. };
  104. } // namespace Ui::Text