127 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// This file is part of Desktop App Toolkit,
 | 
						|
// a set of libraries for developing nice desktop applications.
 | 
						|
//
 | 
						|
// For license and copyright information please follow this link:
 | 
						|
// https://github.com/desktop-app/legal/blob/master/LEGAL
 | 
						|
//
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include "ui/text/text.h"
 | 
						|
 | 
						|
namespace Ui::Text {
 | 
						|
 | 
						|
class Parser {
 | 
						|
public:
 | 
						|
	Parser(
 | 
						|
		not_null<String*> string,
 | 
						|
		const TextWithEntities &textWithEntities,
 | 
						|
		const TextParseOptions &options,
 | 
						|
		const std::any &context);
 | 
						|
 | 
						|
private:
 | 
						|
	struct ReadyToken {
 | 
						|
	};
 | 
						|
 | 
						|
	class StartedEntity {
 | 
						|
	public:
 | 
						|
		enum class Type {
 | 
						|
			Flags,
 | 
						|
			Link,
 | 
						|
			IndexedLink,
 | 
						|
			Spoiler,
 | 
						|
			CustomEmoji,
 | 
						|
		};
 | 
						|
 | 
						|
		explicit StartedEntity(TextBlockFlags flags);
 | 
						|
		explicit StartedEntity(uint16 index, Type type);
 | 
						|
 | 
						|
		[[nodiscard]] Type type() const;
 | 
						|
		[[nodiscard]] std::optional<TextBlockFlags> flags() const;
 | 
						|
		[[nodiscard]] std::optional<uint16> lnkIndex() const;
 | 
						|
		[[nodiscard]] std::optional<uint16> spoilerIndex() const;
 | 
						|
 | 
						|
	private:
 | 
						|
		const int _value = 0;
 | 
						|
		const Type _type;
 | 
						|
 | 
						|
	};
 | 
						|
 | 
						|
	Parser(
 | 
						|
		not_null<String*> string,
 | 
						|
		TextWithEntities &&source,
 | 
						|
		const TextParseOptions &options,
 | 
						|
		const std::any &context,
 | 
						|
		ReadyToken);
 | 
						|
 | 
						|
	void trimSourceRange();
 | 
						|
	void blockCreated();
 | 
						|
	void createBlock(int32 skipBack = 0);
 | 
						|
	void createNewlineBlock();
 | 
						|
 | 
						|
	// Returns true if at least one entity was parsed in the current position.
 | 
						|
	bool checkEntities();
 | 
						|
	void parseCurrentChar();
 | 
						|
	void parseEmojiFromCurrent();
 | 
						|
	void finalize(const TextParseOptions &options);
 | 
						|
 | 
						|
	void finishEntities();
 | 
						|
	void skipPassedEntities();
 | 
						|
	void skipBadEntities();
 | 
						|
 | 
						|
	bool isInvalidEntity(const EntityInText &entity) const;
 | 
						|
	bool isLinkEntity(const EntityInText &entity) const;
 | 
						|
 | 
						|
	bool processCustomIndex(uint16 index);
 | 
						|
 | 
						|
	void parse(const TextParseOptions &options);
 | 
						|
	void computeLinkText(
 | 
						|
		const QString &linkData,
 | 
						|
		QString *outLinkText,
 | 
						|
		EntityLinkShown *outShown);
 | 
						|
 | 
						|
	const not_null<String*> _t;
 | 
						|
	const TextWithEntities _source;
 | 
						|
	const std::any &_context;
 | 
						|
	const QChar * const _start = nullptr;
 | 
						|
	const QChar *_end = nullptr; // mutable, because we trim by decrementing.
 | 
						|
	const QChar *_ptr = nullptr;
 | 
						|
	const EntitiesInText::const_iterator _entitiesEnd;
 | 
						|
	EntitiesInText::const_iterator _waitingEntity;
 | 
						|
	QString _customEmojiData;
 | 
						|
	const bool _multiline = false;
 | 
						|
 | 
						|
	const QFixed _stopAfterWidth; // summary width of all added words
 | 
						|
	const bool _checkTilde = false; // do we need a special text block for tilde symbol
 | 
						|
 | 
						|
	std::vector<uint16> _linksIndexes;
 | 
						|
 | 
						|
	std::vector<EntityLinkData> _links;
 | 
						|
	std::vector<EntityLinkData> _spoilers;
 | 
						|
	std::vector<EntityLinkData> _monos;
 | 
						|
	base::flat_map<
 | 
						|
		const QChar*,
 | 
						|
		std::vector<StartedEntity>> _startedEntities;
 | 
						|
 | 
						|
	uint16 _maxLnkIndex = 0;
 | 
						|
	uint16 _maxShiftedLnkIndex = 0;
 | 
						|
 | 
						|
	// current state
 | 
						|
	int32 _flags = 0;
 | 
						|
	uint16 _lnkIndex = 0;
 | 
						|
	uint16 _spoilerIndex = 0;
 | 
						|
	uint16 _monoIndex = 0;
 | 
						|
	EmojiPtr _emoji = nullptr; // current emoji, if current word is an emoji, or zero
 | 
						|
	int32 _blockStart = 0; // offset in result, from which current parsed block is started
 | 
						|
	int32 _diacs = 0; // diac chars skipped without good char
 | 
						|
	QFixed _sumWidth;
 | 
						|
	bool _sumFinished = false;
 | 
						|
	bool _newlineAwaited = false;
 | 
						|
 | 
						|
	// current char data
 | 
						|
	QChar _ch; // current char (low surrogate, if current char is surrogate pair)
 | 
						|
	int32 _emojiLookback = 0; // how far behind the current ptr to look for current emoji
 | 
						|
	bool _allowDiacritic = false; // did we add last char to the current block
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
} // namespace Ui::Text
 |