Made monospace text clickable.
This commit is contained in:
		
							parent
							
								
									b81b9371e6
								
							
						
					
					
						commit
						4e4e54dcc5
					
				
					 1 changed files with 67 additions and 16 deletions
				
			
		|  | @ -30,6 +30,10 @@ constexpr auto kStringLinkIndexShift = uint16(0x8000); | ||||||
| constexpr auto kMaxDiacAfterSymbol = 2; | constexpr auto kMaxDiacAfterSymbol = 2; | ||||||
| constexpr auto kSelectedSpoilerOpacity = 0.5; | constexpr auto kSelectedSpoilerOpacity = 0.5; | ||||||
| 
 | 
 | ||||||
|  | inline bool IsMono(int32 flags) { | ||||||
|  | 	return (flags & TextBlockFPre) || (flags & TextBlockFCode); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| Qt::LayoutDirection StringDirection( | Qt::LayoutDirection StringDirection( | ||||||
| 		const QString &str, | 		const QString &str, | ||||||
| 		int from, | 		int from, | ||||||
|  | @ -239,11 +243,13 @@ private: | ||||||
| 
 | 
 | ||||||
| 	std::vector<EntityLinkData> _links; | 	std::vector<EntityLinkData> _links; | ||||||
| 	std::vector<EntityLinkData> _spoilers; | 	std::vector<EntityLinkData> _spoilers; | ||||||
|  | 	std::vector<EntityLinkData> _monos; | ||||||
| 	base::flat_map< | 	base::flat_map< | ||||||
| 		const QChar*, | 		const QChar*, | ||||||
| 		std::vector<StartedEntity>> _startedEntities; | 		std::vector<StartedEntity>> _startedEntities; | ||||||
| 
 | 
 | ||||||
| 	uint16 _maxLnkIndex = 0; | 	uint16 _maxLnkIndex = 0; | ||||||
|  | 	uint16 _maxShiftedLnkIndex = 0; | ||||||
| 	uint16 _maxSpoilerIndex = 0; | 	uint16 _maxSpoilerIndex = 0; | ||||||
| 
 | 
 | ||||||
| 	// current state
 | 	// current state
 | ||||||
|  | @ -343,6 +349,11 @@ void Parser::createBlock(int32 skipBack) { | ||||||
| 	if (_lnkIndex < kStringLinkIndexShift && _lnkIndex > _maxLnkIndex) { | 	if (_lnkIndex < kStringLinkIndexShift && _lnkIndex > _maxLnkIndex) { | ||||||
| 		_maxLnkIndex = _lnkIndex; | 		_maxLnkIndex = _lnkIndex; | ||||||
| 	} | 	} | ||||||
|  | 	if (_lnkIndex > kStringLinkIndexShift) { | ||||||
|  | 		_maxShiftedLnkIndex = std::max( | ||||||
|  | 			uint16(_lnkIndex - kStringLinkIndexShift), | ||||||
|  | 			_maxShiftedLnkIndex); | ||||||
|  | 	} | ||||||
| 	if (_spoilerIndex > _maxSpoilerIndex) { | 	if (_spoilerIndex > _maxSpoilerIndex) { | ||||||
| 		_maxSpoilerIndex = _spoilerIndex; | 		_maxSpoilerIndex = _spoilerIndex; | ||||||
| 	} | 	} | ||||||
|  | @ -459,14 +470,24 @@ bool Parser::checkEntities() { | ||||||
| 		flags = TextBlockFPlainLink; | 		flags = TextBlockFPlainLink; | ||||||
| 	} else if (entityType == EntityType::StrikeOut) { | 	} else if (entityType == EntityType::StrikeOut) { | ||||||
| 		flags = TextBlockFStrikeOut; | 		flags = TextBlockFStrikeOut; | ||||||
| 	} else if (entityType == EntityType::Code) { // #TODO entities
 | 	} else if ((entityType == EntityType::Code) // #TODO entities
 | ||||||
|  | 		|| (entityType == EntityType::Pre)) { | ||||||
|  | 		if (entityType == EntityType::Code) { | ||||||
| 			flags = TextBlockFCode; | 			flags = TextBlockFCode; | ||||||
| 	} else if (entityType == EntityType::Pre) { | 		} else { | ||||||
| 			flags = TextBlockFPre; | 			flags = TextBlockFPre; | ||||||
| 			createBlock(); | 			createBlock(); | ||||||
| 		if (!_t->_blocks.empty() && _t->_blocks.back()->type() != TextBlockTNewline) { | 			if (!_t->_blocks.empty() | ||||||
|  | 				&& _t->_blocks.back()->type() != TextBlockTNewline) { | ||||||
| 				createNewlineBlock(); | 				createNewlineBlock(); | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
|  | 		const auto end = _waitingEntity->offset() + entityLength; | ||||||
|  | 		_monos.push_back({ | ||||||
|  | 			.text = QString(entityBegin, entityLength), | ||||||
|  | 			.data = QString(QChar(end)), | ||||||
|  | 			.type = entityType, | ||||||
|  | 		}); | ||||||
| 	} else if (entityType == EntityType::Url | 	} else if (entityType == EntityType::Url | ||||||
| 		|| entityType == EntityType::Email | 		|| entityType == EntityType::Email | ||||||
| 		|| entityType == EntityType::Mention | 		|| entityType == EntityType::Mention | ||||||
|  | @ -706,8 +727,13 @@ void Parser::trimSourceRange() { | ||||||
| // }
 | // }
 | ||||||
| 
 | 
 | ||||||
| void Parser::finalize(const TextParseOptions &options) { | void Parser::finalize(const TextParseOptions &options) { | ||||||
| 	_t->_links.resize(_maxLnkIndex); | 	_t->_links.resize(_maxLnkIndex + _maxShiftedLnkIndex); | ||||||
| 	_t->_spoilers.resize(_maxSpoilerIndex); | 	_t->_spoilers.resize(_maxSpoilerIndex); | ||||||
|  | 	auto monoLnk = uint16(1); | ||||||
|  | 	struct { | ||||||
|  | 		uint16 mono = 0; | ||||||
|  | 		uint16 lnk = 0; | ||||||
|  | 	} lastHandlerIndex; | ||||||
| 	for (auto &block : _t->_blocks) { | 	for (auto &block : _t->_blocks) { | ||||||
| 		const auto spoilerIndex = block->spoilerIndex(); | 		const auto spoilerIndex = block->spoilerIndex(); | ||||||
| 		if (spoilerIndex) { | 		if (spoilerIndex) { | ||||||
|  | @ -719,22 +745,46 @@ void Parser::finalize(const TextParseOptions &options) { | ||||||
| 		} | 		} | ||||||
| 		const auto shiftedIndex = block->lnkIndex(); | 		const auto shiftedIndex = block->lnkIndex(); | ||||||
| 		if (shiftedIndex <= kStringLinkIndexShift) { | 		if (shiftedIndex <= kStringLinkIndexShift) { | ||||||
|  | 			if (IsMono(block->flags())) { | ||||||
|  | 				const auto entityEnd = int( | ||||||
|  | 					_monos[monoLnk - 1].data.constData()->unicode()); | ||||||
|  | 				if (block->from() >= entityEnd) { | ||||||
|  | 					monoLnk++; | ||||||
|  | 				} | ||||||
|  | 				const auto monoIndex = _maxLnkIndex | ||||||
|  | 					+ _maxShiftedLnkIndex | ||||||
|  | 					+ monoLnk; | ||||||
|  | 				block->setLnkIndex(monoIndex); | ||||||
|  | 
 | ||||||
|  | 				if (lastHandlerIndex.mono == monoIndex) { | ||||||
|  | 					continue; // Optimization.
 | ||||||
|  | 				} | ||||||
|  | 				const auto handler = Integration::Instance().createLinkHandler( | ||||||
|  | 					_monos[monoLnk - 1], | ||||||
|  | 					_context); | ||||||
|  | 				_t->_links.resize(monoIndex); | ||||||
|  | 				if (handler) { | ||||||
|  | 					_t->setLink(monoIndex, handler); | ||||||
|  | 				} | ||||||
|  | 				lastHandlerIndex.mono = monoIndex; | ||||||
|  | 			} | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 		const auto realIndex = (shiftedIndex - kStringLinkIndexShift); | 		const auto realIndex = (shiftedIndex - kStringLinkIndexShift); | ||||||
| 		const auto index = _maxLnkIndex + realIndex; | 		const auto index = _maxLnkIndex + realIndex; | ||||||
| 		block->setLnkIndex(index); | 		block->setLnkIndex(index); | ||||||
| 		if (_t->_links.size() >= index) { | 		if (lastHandlerIndex.lnk == index) { | ||||||
| 			continue; | 			continue; // Optimization.
 | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		_t->_links.resize(index); | 		// _t->_links.resize(index);
 | ||||||
| 		const auto handler = Integration::Instance().createLinkHandler( | 		const auto handler = Integration::Instance().createLinkHandler( | ||||||
| 			_links[realIndex - 1], | 			_links[realIndex - 1], | ||||||
| 			_context); | 			_context); | ||||||
| 		if (handler) { | 		if (handler) { | ||||||
| 			_t->setLink(index, handler); | 			_t->setLink(index, handler); | ||||||
| 		} | 		} | ||||||
|  | 		lastHandlerIndex.lnk = index; | ||||||
| 	} | 	} | ||||||
| 	_t->_links.squeeze(); | 	_t->_links.squeeze(); | ||||||
| 	_t->_spoilers.squeeze(); | 	_t->_spoilers.squeeze(); | ||||||
|  | @ -1953,7 +2003,7 @@ private: | ||||||
| 			return f; | 			return f; | ||||||
| 		} | 		} | ||||||
| 		auto result = f; | 		auto result = f; | ||||||
| 		if ((flags & TextBlockFPre) || (flags & TextBlockFCode)) { | 		if (IsMono(flags)) { | ||||||
| 			result = result->monospace(); | 			result = result->monospace(); | ||||||
| 		} else { | 		} else { | ||||||
| 			if (flags & TextBlockFBold) { | 			if (flags & TextBlockFBold) { | ||||||
|  | @ -2592,12 +2642,13 @@ private: | ||||||
| 			} else { | 			} else { | ||||||
| 				_background = {}; | 				_background = {}; | ||||||
| 			} | 			} | ||||||
| 			if (block->lnkIndex() || (block->flags() & TextBlockFPlainLink)) { | 			if (IsMono(block->flags())) { | ||||||
| 				_currentPen = &_textPalette->linkFg->p; |  | ||||||
| 				_currentPenSelected = &_textPalette->selectLinkFg->p; |  | ||||||
| 			} else if ((block->flags() & TextBlockFCode) || (block->flags() & TextBlockFPre)) { |  | ||||||
| 				_currentPen = &_textPalette->monoFg->p; | 				_currentPen = &_textPalette->monoFg->p; | ||||||
| 				_currentPenSelected = &_textPalette->selectMonoFg->p; | 				_currentPenSelected = &_textPalette->selectMonoFg->p; | ||||||
|  | 			} else if (block->lnkIndex() | ||||||
|  | 				|| (block->flags() & TextBlockFPlainLink)) { | ||||||
|  | 				_currentPen = &_textPalette->linkFg->p; | ||||||
|  | 				_currentPenSelected = &_textPalette->selectLinkFg->p; | ||||||
| 			} else { | 			} else { | ||||||
| 				_currentPen = &_originalPen; | 				_currentPen = &_originalPen; | ||||||
| 				_currentPenSelected = &_originalPenSelected; | 				_currentPenSelected = &_originalPenSelected; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 23rd
						23rd