<commit_before>/*
 * (c) Copyright Ascensio System SIA 2010-2022
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 <NAME>-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

"use strict";

(function(window)
{
	/**
	 * Данный класс рассчитывает текстовые настройки шрифта для выделенного текста
	 * @constructor
	 */
	function CFontCalculator()
	{
		this.Bold     = null;
		this.Italic   = null;
		this.FontSize = null;
		this.FontName = null;

		// Для случая, когда в выделение попали только элементы со слотом AscWord.fontslot_Unknown
		// (например, только знак конца параграфа)
		this.BoldUnknown     = null;
		this.ItalicUnkown    = null;
		this.FontSizeUnknown = null;
		this.FontNameUnknown = null;
	}
	CFontCalculator.prototype.Calculate = function(oDocContent, oTextPr)
	{
		this.Reset();

		if (oDocContent.IsTextSelectionUse())
			this.HandleSelectionCase(oDocContent);
		else
			this.HandleCursorCase(oDocContent);

		this.CheckResult();

		oTextPr.Bold       = this.Bold;
		oTextPr.Italic     = this.Italic;
		oTextPr.FontSize   = this.FontSize;
		oTextPr.FontFamily = {Name : this.FontName, Index : -1};
	};
	//------------------------------------------------------------------------------------------------------------------
	CFontCalculator.prototype.Reset = function()
	{
		this.Bold     = null;
		this.Italic   = null;
		this.FontSize = null;
		this.FontName = null;

		this.BoldUnknown     = null;
		this.ItalicUnkown    = null;
		this.FontSizeUnknown = null;
		this.FontNameUnknown = null;
	};
	CFontCalculator.prototype.HandleSelectionCase = function(oDocContent)
	{
		let oThis = this;
		oDocContent.CheckSelectedRunContent(function(oRun, nStartPos, nEndPos)
		{
			if (oThis.IsStop())
				return true;

			if (oRun.IsEmpty())
				return false;

			let nFontSlot = oRun.GetFontSlotInRange(nStartPos, nEndPos);
			if (AscWord.fontslot_None === nFontSlot)
				return false;

			// TODO: Пока оставим эту проверку здесь. Проблема в том, что настройки в последнем ране не совпадают
			//       с настройками конца параграфа (если это исправится, тогда здесь можно просто оставить
			//       простое получение компилированных настроек рана)
			let oTextPr;
			if (oRun.IsParaEndRun() && oRun.GetParagraph())
				oTextPr = oRun.GetParagraph().GetParaEndCompiledPr();
			else
				oTextPr = oRun.Get_CompiledPr(false);

			let oParagraph = oRun.GetParagraph();
			if (oParagraph)
				oTextPr.ReplaceThemeFonts(oParagraph.GetTheme().themeElements.fontScheme);

			nFontSlot = oThis.CheckUnknownFontSlot(nFontSlot, oTextPr);

			if (nFontSlot & AscWord.fontslot_CS)
			{
				oThis.CheckBold(oTextPr.BoldCS);
				oThis.CheckItalic(oTextPr.ItalicCS);
				oThis.CheckFontSize(oTextPr.FontSizeCS);
				oThis.CheckFontName(oTextPr.RFonts.CS.Name);
			}

			if (nFontSlot !== AscWord.fontslot_CS && nFontSlot !== AscWord.fontslot_None)
			{
				oThis.CheckBold(oTextPr.Bold);
				oThis.CheckItalic(oTextPr.Italic);
				oThis.CheckFontSize(oTextPr.FontSize);
			}

			if (nFontSlot & AscWord.fontslot_ASCII)
				oThis.CheckFontName(oTextPr.RFonts.Ascii.Name);

			if (nFontSlot & AscWord.fontslot_HAnsi)
				oThis.CheckFontName(oTextPr.RFonts.HAnsi.Name);

			if (nFontSlot & AscWord.fontslot_EastAsia)
				oThis.CheckFontName(oTextPr.RFonts.EastAsia.Name);

			return false;
		});
	};
	CFontCalculator.prototype.HandleCursorCase = function(oDocContent)
	{
		let oParagraph = oDocContent.GetCurrentParagraph();
		if (!oParagraph)
			return;

		let oParaContentPos = oParagraph.Get_ParaContentPos(false, false);
		if (!oParaContentPos)
			return;

		let oRun = oParagraph.GetClassByPos(oParaContentPos);
		if (!oRun || !(oRun instanceof AscWord.ParaRun))
			return;

		let oTextPr   = oRun.Get_CompiledPr(false);
		let nInRunPos = oParaContentPos.Get(oParaContentPos.GetDepth());
		let nFontSlot = this.CheckUnknownFontSlot(oRun.GetFontSlotByPosition(nInRunPos), oTextPr);

		oTextPr.ReplaceThemeFonts(oParagraph.GetTheme().themeElements.fontScheme);

		if (nFontSlot & AscWord.fontslot_ASCII)
			this.FontName = oTextPr.RFonts.Ascii.Name;
		else if (nFontSlot & AscWord.fontslot_HAnsi)
			this.FontName = oTextPr.RFonts.HAnsi.Name;
		else if (nFontSlot & AscWord.fontslot_EastAsia)
			this.FontName = oTextPr.RFonts.EastAsia.Name;
<commit_msg>[de] Fix font calculator when cursor is placed in empty run<commit_after>/*
 * (c) Copyright Ascensio System SIA 2010-2022
 *
 * This program is a free software product. You can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License (AGPL)
 * version 3 as published by the Free Software Foundation. In accordance with
 * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
 * that Ascensio System SIA expressly excludes the warranty of non-infringement
 * of any third-party rights.
 *
 * This program is distributed WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR  PURPOSE. For
 * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
 *
 * You can contact Ascensio System SIA at 20A-12 <NAME>-Upisha
 * street, Riga, Latvia, EU, LV-1050.
 *
 * The  interactive user interfaces in modified source and object code versions
 * of the Program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU AGPL version 3.
 *
 * Pursuant to Section 7(b) of the License you must retain the original Product
 * logo when distributing the program. Pursuant to Section 7(e) we decline to
 * grant you any rights under trademark law for use of our trademarks.
 *
 * All the Product's GUI elements, including illustrations and icon sets, as
 * well as technical writing content are licensed under the terms of the
 * Creative Commons Attribution-ShareAlike 4.0 International. See the License
 * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
 *
 */

"use strict";

(function(window)
{
	/**
	 * Данный класс рассчитывает текстовые настройки шрифта для выделенного текста
	 * @constructor
	 */
	function CFontCalculator()
	{
		this.Bold     = null;
		this.Italic   = null;
		this.FontSize = null;
		this.FontName = null;

		// Для случая, когда в выделение попали только элементы со слотом AscWord.fontslot_Unknown
		// (например, только знак конца параграфа)
		this.BoldUnknown     = null;
		this.ItalicUnkown    = null;
		this.FontSizeUnknown = null;
		this.FontNameUnknown = null;
	}
	CFontCalculator.prototype.Calculate = function(oDocContent, oTextPr)
	{
		this.Reset();

		if (oDocContent.IsTextSelectionUse())
			this.HandleSelectionCase(oDocContent);
		else
			this.HandleCursorCase(oDocContent);

		this.CheckResult();

		oTextPr.Bold       = this.Bold;
		oTextPr.Italic     = this.Italic;
		oTextPr.FontSize   = this.FontSize;
		oTextPr.FontFamily = {Name : this.FontName, Index : -1};
	};
	//------------------------------------------------------------------------------------------------------------------
	CFontCalculator.prototype.Reset = function()
	{
		this.Bold     = null;
		this.Italic   = null;
		this.FontSize = null;
		this.FontName = null;

		this.BoldUnknown     = null;
		this.ItalicUnkown    = null;
		this.FontSizeUnknown = null;
		this.FontNameUnknown = null;
	};
	CFontCalculator.prototype.HandleSelectionCase = function(oDocContent)
	{
		let oThis = this;
		oDocContent.CheckSelectedRunContent(function(oRun, nStartPos, nEndPos)
		{
			if (oThis.IsStop())
				return true;

			if (oRun.IsEmpty())
				return false;

			let nFontSlot = oRun.GetFontSlotInRange(nStartPos, nEndPos);
			if (AscWord.fontslot_None === nFontSlot)
				return false;

			// TODO: Пока оставим эту проверку здесь. Проблема в том, что настройки в последнем ране не совпадают
			//       с настройками конца параграфа (если это исправится, тогда здесь можно просто оставить
			//       простое получение компилированных настроек рана)
			let oTextPr;
			if (oRun.IsParaEndRun() && oRun.GetParagraph())
				oTextPr = oRun.GetParagraph().GetParaEndCompiledPr();
			else
				oTextPr = oRun.Get_CompiledPr(false);

			let oParagraph = oRun.GetParagraph();
			if (oParagraph)
				oTextPr.ReplaceThemeFonts(oParagraph.GetTheme().themeElements.fontScheme);

			nFontSlot = oThis.CheckUnknownFontSlot(nFontSlot, oTextPr);

			if (nFontSlot & AscWord.fontslot_CS)
			{
				oThis.CheckBold(oTextPr.BoldCS);
				oThis.CheckItalic(oTextPr.ItalicCS);
				oThis.CheckFontSize(oTextPr.FontSizeCS);
				oThis.CheckFontName(oTextPr.RFonts.CS.Name);
			}

			if (nFontSlot !== AscWord.fontslot_CS && nFontSlot !== AscWord.fontslot_None)
			{
				oThis.CheckBold(oTextPr.Bold);
				oThis.CheckItalic(oTextPr.Italic);
				oThis.CheckFontSize(oTextPr.FontSize);
			}

			if (nFontSlot & AscWord.fontslot_ASCII)
				oThis.CheckFontName(oTextPr.RFonts.Ascii.Name);

			if (nFontSlot & AscWord.fontslot_HAnsi)
				oThis.CheckFontName(oTextPr.RFonts.HAnsi.Name);

			if (nFontSlot & AscWord.fontslot_EastAsia)
				oThis.CheckFontName(oTextPr.RFonts.EastAsia.Name);

			return false;
		});
	};
	CFontCalculator.prototype.HandleCursorCase = function(oDocContent)
	{
		let oParagraph = oDocContent.GetCurrentParagraph();
		if (!oParagraph)
			return;

		let oParaContentPos = oParagraph.Get_ParaContentPos(false, false);
		if (!oParaContentPos)
			return;

		let oRun = oParagraph.GetClassByPos(oParaContentPos);
		if (!oRun || !(oRun instanceof AscWord.ParaRun))
			return;

		let oTextPr   = oRun.Get_CompiledPr(false);
		let nInRunPos = oParaContentPos.Get(oParaContentPos.GetDepth());
		let nFontSlot = this.CheckUnknownFontSlot(oRun.GetFontSlotByPosition(nInRunPos), oTextPr);

		oTextPr.ReplaceThemeFonts(oParagraph.GetTheme().themeElements.fontScheme);

		if (AscWord.fontslot_None === nFontSlot)
			nFontSlot = AscWord.fontslot_ASCII;

		if (nFontSlot & AscWord.fontslot_ASCII)
			this.FontName = oTextPr.RFonts.Ascii.Name;
		else if (nFontSlot & AscWord.fontslot_HAnsi)
			this.FontName = oTextPr.RFonts.HAnsi.Name;
		else if (nFontSlot & AscWord.fontslot_EastAsia)
			this.FontName = oTextPr.RFonts.EastAsia.Name;

{'fraction_non_alphanumeric': 0.11401737909242517, 'fraction_numerical': 0.005441938032124989, 'mean_word_length': 3.598062953995157, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4929136', 'n_tokens_mistral': 4282, 'n_tokens_neox': 3874, 'n_words': 935}