"use strict"; /** * User: Ilja.Kirillov * Date: 03.12.13 * Time: 18:28 */ var reviewtype_Common = 0x00; var reviewtype_Remove = 0x01; var reviewtype_Add = 0x02; /** * * @param Paragraph * @param bMathRun * @constructor * @extends {CParagraphContentWithContentBase} */ function ParaRun(Paragraph, bMathRun) { ParaRun.superclass.constructor.call(this); this.Id = g_oIdCounter.Get_NewId(); // Id данного элемента this.Type = para_Run; // тип данного элемента this.Paragraph = Paragraph; // Ссылка на параграф this.Pr = new CTextPr(); // Текстовые настройки данного run this.Content = []; // Содержимое данного run this.State = new CParaRunState(); // Положение курсора и селекта в данного run this.Selection = this.State.Selection; this.CompiledPr = new CTextPr(); // Скомпилированные настройки this.RecalcInfo = new CParaRunRecalcInfo(); // Флаги для пересчета (там же флаг пересчета стиля) this.TextAscent = 0; // текстовый ascent + linegap this.TextAscent = 0; // текстовый ascent + linegap this.TextDescent = 0; // текстовый descent this.TextHeight = 0; // высота текста this.TextAscent2 = 0; // текстовый ascent this.Ascent = 0; // общий ascent this.Descent = 0; // общий descent this.YOffset = 0; // смещение по Y this.CollPrChangeMine = false; this.CollPrChangeOther = false; this.CollaborativeMarks = new CRunCollaborativeMarks(); this.m_oContentChanges = new CContentChanges(); // список изменений(добавление/удаление элементов) this.NearPosArray = []; this.SearchMarks = []; this.SpellingMarks = []; this.ReviewType = reviewtype_Common; this.ReviewInfo = new CReviewInfo(); if (editor && !editor.isPresentationEditor && editor.WordControl && editor.WordControl.m_oLogicDocument && true === editor.WordControl.m_oLogicDocument.Is_TrackRevisions()) this.ReviewType = reviewtype_Add; if(bMathRun) { this.Type = para_Math_Run; // запомним позицию для Recalculate_CurPos, когда Run пустой this.pos = new CMathPosition(); this.ParaMath = null; this.Parent = null; this.ArgSize = 0; this.size = new CMathSize(); this.MathPrp = new CMPrp(); this.bEqArray = false; } this.StartState = null; // Добавляем данный класс в таблицу Id (обязательно в конце конструктора) g_oTableId.Add( this, this.Id ); if(this.Paragraph && !this.Paragraph.bFromDocument) { this.Save_StartState(); } } Asc.extendClass(ParaRun, CParagraphContentWithContentBase); ParaRun.prototype.Get_Type = function() { return this.Type; }; //----------------------------------------------------------------------------------- // Функции для работы с Id //----------------------------------------------------------------------------------- ParaRun.prototype.Set_Id = function(newId) { g_oTableId.Reset_Id( this, newId, this.Id ); this.Id = newId; }; ParaRun.prototype.Get_Id = function() { return this.Id; }; ParaRun.prototype.Get_Paragraph = function() { return this.Paragraph; }; ParaRun.prototype.Set_Paragraph = function(Paragraph) { this.Paragraph = Paragraph; }; ParaRun.prototype.Set_ParaMath = function(ParaMath, Parent) { this.ParaMath = ParaMath; this.Parent = Parent; for(var i = 0; i < this.Content.length; i++) { this.Content[i].relate(this); } }; ParaRun.prototype.Save_StartState = function() { this.StartState = new CParaRunStartState(this); }; //----------------------------------------------------------------------------------- // Функции для работы с содержимым данного рана //----------------------------------------------------------------------------------- ParaRun.prototype.Copy = function(Selected) { var bMath = this.Type == para_Math_Run ? true : false; var NewRun = new ParaRun(this.Paragraph, bMath); NewRun.Set_Pr( this.Pr.Copy() ); if (this.Paragraph && this.Paragraph.LogicDocument && true === this.Paragraph.LogicDocument.Is_TrackRevisions()) NewRun.Set_ReviewType(reviewtype_Add); if(true === bMath) NewRun.MathPrp = this.MathPrp.Copy(); var StartPos = 0; var EndPos = this.Content.length; if (true === Selected && true === this.State.Selection.Use) { StartPos = this.State.Selection.StartPos; EndPos = this.State.Selection.EndPos; if (StartPos > EndPos) { StartPos = this.State.Selection.EndPos; EndPos = this.State.Selection.StartPos; } } else if (true === Selected && true !== this.State.Selection.Use) EndPos = -1; for ( var CurPos = StartPos; CurPos < EndPos; CurPos++ ) { var Item = this.Content[CurPos]; // TODO: Как только перенесем para_End в сам параграф (как и нумерацию) убрать здесь if ( para_End !== Item.Type ) NewRun.Add_ToContent( CurPos - StartPos, Item.Copy(), false ); } return NewRun; }; ParaRun.prototype.Copy2 = function() { var NewRun = new ParaRun(this.Paragraph); NewRun.Set_Pr( this.Pr.Copy() ); var StartPos = 0; var EndPos = this.Content.length; for ( var CurPos = StartPos; CurPos < EndPos; CurPos++ ) { var Item = this.Content[CurPos]; NewRun.Add_ToContent( CurPos - StartPos, Item.Copy(), false ); } return NewRun; }; ParaRun.prototype.CopyContent = function(Selected) { return [this.Copy(Selected)]; }; ParaRun.prototype.Get_AllDrawingObjects = function(DrawingObjs) { var Count = this.Content.length; for ( var Index = 0; Index < Count; Index++ ) { var Item = this.Content[Index]; if ( para_Drawing === Item.Type ) DrawingObjs.push(Item); } }; ParaRun.prototype.Clear_ContentChanges = function() { this.m_oContentChanges.Clear(); }; ParaRun.prototype.Add_ContentChanges = function(Changes) { this.m_oContentChanges.Add( Changes ); }; ParaRun.prototype.Refresh_ContentChanges = function() { this.m_oContentChanges.Refresh(); }; ParaRun.prototype.Get_Text = function(Text) { if ( null === Text.Text ) return; var ContentLen = this.Content.length; for ( var CurPos = 0; CurPos < ContentLen; CurPos++ ) { var Item = this.Content[CurPos]; var ItemType = Item.Type; var bBreak = false; switch ( ItemType ) { case para_Drawing: case para_End: case para_PageNum: { Text.Text = null; bBreak = true; break; } case para_Text : Text.Text += String.fromCharCode(Item.Value); break; case para_Space: case para_Tab : Text.Text += " "; break; } if ( true === bBreak ) break; } }; // Проверяем пустой ли ран ParaRun.prototype.Is_Empty = function(Props) { var SkipAnchor = (undefined !== Props ? Props.SkipAnchor : false); var SkipEnd = (undefined !== Props ? Props.SkipEnd : false); var SkipPlcHldr= (undefined !== Props ? Props.SkipPlcHldr: false); var SkipNewLine= (undefined !== Props ? Props.SkipNewLine: false); var Count = this.Content.length; if (true !== SkipAnchor && true !== SkipEnd && true !== SkipPlcHldr && true !== SkipNewLine) { if ( Count > 0 ) return false; else return true; } else { for ( var CurPos = 0; CurPos < this.Content.length; CurPos++ ) { var Item = this.Content[CurPos]; var ItemType = Item.Type; if ((true !== SkipAnchor || para_Drawing !== ItemType || false !== Item.Is_Inline()) && (true !== SkipEnd || para_End !== ItemType) && (true !== SkipPlcHldr || true !== Item.IsPlaceholder()) && (true !== SkipNewLine || para_NewLine !== ItemType)) return false; } return true; } }; ParaRun.prototype.Is_CheckingNearestPos = function() { if (this.NearPosArray.length > 0) return true; return false; }; // Начинается ли данный ран с новой строки ParaRun.prototype.Is_StartFromNewLine = function() { if (this.protected_GetLinesCount() < 2 || 0 !== this.protected_GetRangeStartPos(1, 0)) return false; return true; }; // Добавляем элемент в текущую позицию ParaRun.prototype.Add = function(Item, bMath) { if (this.Paragraph && this.Paragraph.LogicDocument && true === this.Paragraph.LogicDocument.CheckLanguageOnTextAdd && editor) { var nRequiredLanguage = editor.asc_getKeyboardLanguage(); var nCurrentLanguage = this.Get_CompiledPr(false).Lang.Val; if (-1 !== nRequiredLanguage && nRequiredLanguage !== nCurrentLanguage) { var NewLang = new CLang(); NewLang.Val = nRequiredLanguage; if (this.Is_Empty()) this.Set_Lang(NewLang); else { var Parent = this.Get_Parent(); var RunPos = this.private_GetPosInParent(); if (null !== Parent && -1 !== RunPos) { // Если мы стоим в начале рана, тогда добавим новый ран в начало, если мы стоим в конце рана, тогда // добавим новый ран после текущего, а если мы в середине рана, тогда надо разбивать текущий ран. var NewRun = new ParaRun(this.Paragraph, bMath); NewRun.Set_Pr(this.Pr.Copy()); NewRun.Set_Lang(NewLang); NewRun.Cursor_MoveToStartPos(); NewRun.Add(Item, bMath); var CurPos = this.State.ContentPos; if (0 === CurPos) Parent.Add_ToContent(RunPos, NewRun); else if (this.Content.length === CurPos) Parent.Add_ToContent(RunPos + 1, NewRun); else { // Нужно разделить данный ран в текущей позиции var RightRun = this.Split2(CurPos); Parent.Add_ToContent(RunPos + 1, NewRun); Parent.Add_ToContent(RunPos + 2, RightRun); } NewRun.Make_ThisElementCurrent(); return; } } } } var TrackRevisions = false; if (this.Paragraph && this.Paragraph.LogicDocument) TrackRevisions = this.Paragraph.LogicDocument.Is_TrackRevisions(); var ReviewType = this.Get_ReviewType(); if ((true === TrackRevisions && reviewtype_Add !== ReviewType) || (false === TrackRevisions && reviewtype_Common !== ReviewType)) { var DstReviewType = true === TrackRevisions ? reviewtype_Add : reviewtype_Common; // Если мы стоим в конце рана, тогда проверяем следующий элемент родительского класса, аналогично если мы стоим // в начале рана, проверяем предыдущий элемент родительского класса. var Parent = this.Get_Parent(); if (null === Parent) return; // Ищем данный элемент в родительском классе var RunPos = this.private_GetPosInParent(Parent); if (-1 === RunPos) return; var CurPos = this.State.ContentPos; if (0 === CurPos && RunPos > 0) { var PrevElement = Parent.Content[RunPos - 1]; if (para_Run === PrevElement.Type && DstReviewType === PrevElement.Get_ReviewType() && true === this.Pr.Is_Equal(PrevElement.Pr)) { PrevElement.State.ContentPos = PrevElement.Content.length; PrevElement.Add_ToContent(PrevElement.Content.length, Item, true); PrevElement.Make_ThisElementCurrent(); return; } } if (this.Content.length === CurPos && (RunPos < Parent.Content.length - 2 || (RunPos < Parent.Content.length - 1 && !(Parent instanceof Paragraph)))) { var NextElement = Parent.Content[RunPos + 1]; if (para_Run === NextElement.Type && DstReviewType === NextElement.Get_ReviewType() && true === this.Pr.Is_Equal(NextElement.Pr)) { NextElement.State.ContentPos = 0; NextElement.Add_ToContent(0, Item, true); NextElement.Make_ThisElementCurrent(); return; } } // Если мы дошли до сюда, значит нам надо создать новый ран var NewRun = new ParaRun(this.Paragraph, bMath); NewRun.Set_Pr(this.Pr.Copy()); NewRun.Set_ReviewType(DstReviewType); NewRun.Add_ToContent(0, Item, true); if (0 === CurPos) Parent.Add_ToContent(RunPos, NewRun); else if (this.Content.length === CurPos) Parent.Add_ToContent(RunPos + 1, NewRun); else { // Нужно разделить данный ран в текущей позиции var RightRun = this.Split2(CurPos); Parent.Add_ToContent(RunPos + 1, NewRun); Parent.Add_ToContent(RunPos + 2, RightRun); } NewRun.Make_ThisElementCurrent(); } else this.Add_ToContent(this.State.ContentPos, Item, true); }; ParaRun.prototype.Remove = function(Direction, bOnAddText) { var TrackRevisions = null; if (this.Paragraph && this.Paragraph.LogicDocument) TrackRevisions = this.Paragraph.LogicDocument.Is_TrackRevisions(); var Selection = this.State.Selection; var ReviewType = this.Get_ReviewType(); if (true === TrackRevisions && reviewtype_Add !== ReviewType) { if (reviewtype_Remove === ReviewType) { // Тут мы ничего не делаем, просто перешагиваем через удаленный текст if (true !== Selection.Use) { var CurPos = this.State.ContentPos; // Просто перешагиваем через элемент if (Direction < 0) { // Пропускаем все Flow-объекты while (CurPos > 0 && para_Drawing === this.Content[CurPos - 1].Type && false === this.Content[CurPos - 1].Is_Inline()) CurPos--; if (CurPos <= 0) return false; this.State.ContentPos--; } else { if (CurPos >= this.Content.length || para_End === this.Content[CurPos].Type) return false; this.State.ContentPos++; } this.Make_ThisElementCurrent(); } else { // Ничего не делаем } } else { if (true === Selection.Use) { // Мы должны данный ран разбить в начальной и конечной точках выделения и центральный ран пометить как // удаленный. var StartPos = Selection.StartPos; var EndPos = Selection.EndPos; if (StartPos > EndPos) { StartPos = Selection.EndPos; EndPos = Selection.StartPos; } var Parent = this.Get_Parent(); var RunPos = this.private_GetPosInParent(Parent); if (-1 !== RunPos) { var DeletedRun = null; if (StartPos <= 0 && EndPos >= this.Content.length) DeletedRun = this; else if (StartPos <= 0) { this.Split2(EndPos, Parent, RunPos); DeletedRun = this; } else if (EndPos >= this.Content.length) { DeletedRun = this.Split2(StartPos, Parent, RunPos); } else { this.Split2(EndPos, Parent, RunPos); DeletedRun = this.Split2(StartPos, Parent, RunPos); } DeletedRun.Set_ReviewType(reviewtype_Remove); } } else { var Parent = this.Get_Parent(); var RunPos = this.private_GetPosInParent(Parent); var CurPos = this.State.ContentPos; if (Direction < 0) { // Пропускаем все Flow-объекты while (CurPos > 0 && para_Drawing === this.Content[CurPos - 1].Type && false === this.Content[CurPos - 1].Is_Inline()) CurPos--; if (CurPos <= 0) return false; // Проверяем, возможно предыдущий элемент - инлайн картинка, тогда мы его не удаляем, а выделяем как картинку if (para_Drawing == this.Content[CurPos - 1].Type && true === this.Content[CurPos - 1].Is_Inline()) { return this.Paragraph.Parent.Select_DrawingObject(this.Content[CurPos - 1].Get_Id()); } if (1 === CurPos && 1 === this.Content.length) { this.Set_ReviewType(reviewtype_Remove); this.State.ContentPos = CurPos - 1; this.Make_ThisElementCurrent(); return true; } else if (1 === CurPos && Parent && RunPos > 0) { var PrevElement = Parent.Content[RunPos - 1]; if (para_Run === PrevElement.Type && reviewtype_Remove === PrevElement.Get_ReviewType() && true === this.Pr.Is_Equal(PrevElement.Pr)) { var Item = this.Content[CurPos - 1]; this.Remove_FromContent(CurPos - 1, 1, true); PrevElement.Add_ToContent(PrevElement.Content.length, Item); PrevElement.State.ContentPos = PrevElement.Content.length - 1; PrevElement.Make_ThisElementCurrent(); return true; } } else if (CurPos === this.Content.length && Parent && RunPos < Parent.Content.length - 1) { var NextElement = Parent.Content[RunPos + 1]; if (para_Run === NextElement.Type && reviewtype_Remove === NextElement.Get_ReviewType() && true === this.Pr.Is_Equal(NextElement.Pr)) { var Item = this.Content[CurPos - 1]; this.Remove_FromContent(CurPos - 1, 1, true); NextElement.Add_ToContent(0, Item); this.State.ContentPos = CurPos - 1; this.Make_ThisElementCurrent(); return true; } } // Если мы дошли до сюда, значит данный элемент нужно выделять в отдельный ран var RRun = this.Split2(CurPos, Parent, RunPos); var CRun = this.Split2(CurPos - 1, Parent, RunPos); CRun.Set_ReviewType(reviewtype_Remove); this.State.ContentPos = CurPos - 1; this.Make_ThisElementCurrent(); } else { if (CurPos >= this.Content.length || para_End === this.Content[CurPos].Type) return false; // Проверяем, возможно следующий элемент - инлайн картинка, тогда мы его не удаляем, а выделяем как картинку if (para_Drawing == this.Content[CurPos].Type && true === this.Content[CurPos].Is_Inline()) { return this.Paragraph.Parent.Select_DrawingObject(this.Content[CurPos].Get_Id()); } if (CurPos === this.Content.length - 1 && 0 === CurPos) { this.Set_ReviewType(reviewtype_Remove); this.State.ContentPos = 1; this.Make_ThisElementCurrent(); return true; } else if (0 === CurPos && Parent && RunPos > 0) { var PrevElement = Parent.Content[RunPos - 1]; if (para_Run === PrevElement.Type && reviewtype_Remove === PrevElement.Get_ReviewType() && true === this.Pr.Is_Equal(PrevElement.Pr)) { var Item = this.Content[CurPos]; this.Remove_FromContent(CurPos, 1, true); PrevElement.Add_ToContent(PrevElement.Content.length, Item); this.State.ContentPos = CurPos; this.Make_ThisElementCurrent(); return true; } } else if (CurPos === this.Content.length - 1 && Parent && RunPos < Parent.Content.length - 1) { var NextElement = Parent.Content[RunPos + 1]; if (para_Run === NextElement.Type && reviewtype_Remove === NextElement.Get_ReviewType() && true === this.Pr.Is_Equal(NextElement.Pr)) { var Item = this.Content[CurPos]; this.Remove_FromContent(CurPos, 1, true); NextElement.Add_ToContent(0, Item); NextElement.State.ContentPos = 1; NextElement.Make_ThisElementCurrent(); return true; } } // Если мы дошли до сюда, значит данный элемент нужно выделять в отдельный ран var RRun = this.Split2(CurPos + 1, Parent, RunPos); var CRun = this.Split2(CurPos, Parent, RunPos); CRun.Set_ReviewType(reviewtype_Remove); RRun.State.ContentPos = 0; RRun.Make_ThisElementCurrent(); } } } } else { if (true === Selection.Use) { var StartPos = Selection.StartPos; var EndPos = Selection.EndPos; if (StartPos > EndPos) { var Temp = StartPos; StartPos = EndPos; EndPos = Temp; } // Если в выделение попадает ParaEnd, тогда удаляем все кроме этого элемента if (true === this.Selection_CheckParaEnd()) { for (var CurPos = EndPos - 1; CurPos >= StartPos; CurPos--) { if (para_End !== this.Content[CurPos].Type) this.Remove_FromContent(CurPos, 1, true); } } else { this.Remove_FromContent(StartPos, EndPos - StartPos, true); } this.Selection_Remove(); this.State.ContentPos = StartPos; } else { var CurPos = this.State.ContentPos; if (Direction < 0) { // Пропускаем все Flow-объекты while (CurPos > 0 && para_Drawing === this.Content[CurPos - 1].Type && false === this.Content[CurPos - 1].Is_Inline()) CurPos--; if (CurPos <= 0) return false; // Проверяем, возможно предыдущий элемент - инлайн картинка, тогда мы его не удаляем, а выделяем как картинку if (para_Drawing == this.Content[CurPos - 1].Type && true === this.Content[CurPos - 1].Is_Inline()) { return this.Paragraph.Parent.Select_DrawingObject(this.Content[CurPos - 1].Get_Id()); } this.Remove_FromContent(CurPos - 1, 1, true); this.State.ContentPos = CurPos - 1; } else { if (CurPos >= this.Content.length || para_End === this.Content[CurPos].Type) return false; // Проверяем, возможно следующий элемент - инлайн картинка, тогда мы его не удаляем, а выделяем как картинку if (para_Drawing == this.Content[CurPos].Type && true === this.Content[CurPos].Is_Inline()) { return this.Paragraph.Parent.Select_DrawingObject(this.Content[CurPos].Get_Id()); } this.Remove_FromContent(CurPos, 1, true); this.State.ContentPos = CurPos; } } } return true; }; ParaRun.prototype.Remove_ParaEnd = function() { var Pos = -1; var ContentLen = this.Content.length; for ( var CurPos = 0; CurPos < ContentLen; CurPos++ ) { if ( para_End === this.Content[CurPos].Type ) { Pos = CurPos; break; } } if ( -1 === Pos ) return false; this.Remove_FromContent( Pos, ContentLen - Pos, true ); return true; }; /** * Обновляем позиции селекта, курсора и переносов строк при добавлении элемента в контент данного рана. * @param Pos */ ParaRun.prototype.private_UpdatePositionsOnAdd = function(Pos) { // Обновляем текущую позицию if (this.State.ContentPos >= Pos) this.State.ContentPos++; // Обновляем начало и конец селекта if (true === this.State.Selection.Use) { if (this.State.Selection.StartPos >= Pos) this.State.Selection.StartPos++; if (this.State.Selection.EndPos >= Pos) this.State.Selection.EndPos++; } // Также передвинем всем метки переносов страниц и строк var LinesCount = this.protected_GetLinesCount(); for (var CurLine = 0; CurLine < LinesCount; CurLine++) { var RangesCount = this.protected_GetRangesCount(CurLine); for (var CurRange = 0; CurRange < RangesCount; CurRange++) { var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); if (StartPos > Pos) StartPos++; if (EndPos > Pos) EndPos++; this.protected_FillRange(CurLine, CurRange, StartPos, EndPos); } // Особый случай, когда мы добавляем элемент в самый последний ран if (Pos === this.Content.length - 1 && LinesCount - 1 === CurLine) { this.protected_FillRangeEndPos(CurLine, RangesCount - 1, this.protected_GetRangeEndPos(CurLine, RangesCount - 1) + 1); } } }; /** * Обновляем позиции селекта, курсора и переносов строк при удалении элементов из контента данного рана. * @param Pos * @param Count */ ParaRun.prototype.private_UpdatePositionsOnRemove = function(Pos, Count) { // Обновим текущую позицию if (this.State.ContentPos > Pos + Count) this.State.ContentPos -= Count; else if (this.State.ContentPos > Pos) this.State.ContentPos = Pos; // Обновим начало и конец селекта if (true === this.State.Selection.Use) { if (this.State.Selection.StartPos <= this.State.Selection.EndPos) { if (this.State.Selection.StartPos > Pos + Count) this.State.Selection.StartPos -= Count; else if (this.State.Selection.StartPos > Pos) this.State.Selection.StartPos = Pos; if (this.State.Selection.EndPos >= Pos + Count) this.State.Selection.EndPos -= Count; else if (this.State.Selection.EndPos > Pos) this.State.Selection.EndPos = Math.max(0, Pos - 1); } else { if (this.State.Selection.StartPos >= Pos + Count) this.State.Selection.StartPos -= Count; else if (this.State.Selection.StartPos > Pos) this.State.Selection.StartPos = Math.max(0, Pos - 1); if (this.State.Selection.EndPos > Pos + Count) this.State.Selection.EndPos -= Count; else if (this.State.Selection.EndPos > Pos) this.State.Selection.EndPos = Pos; } } // Также передвинем всем метки переносов страниц и строк var LinesCount = this.protected_GetLinesCount(); for (var CurLine = 0; CurLine < LinesCount; CurLine++) { var RangesCount = this.protected_GetRangesCount(CurLine); for (var CurRange = 0; CurRange < RangesCount; CurRange++) { var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); if (StartPos > Pos + Count) StartPos -= Count; else if (StartPos > Pos) StartPos = Math.max(0, Pos); if (EndPos >= Pos + Count) EndPos -= Count; else if (EndPos >= Pos) EndPos = Math.max(0, Pos); this.protected_FillRange(CurLine, CurRange, StartPos, EndPos); } } }; // Добавляем элемент в позицию с сохранием в историю ParaRun.prototype.Add_ToContent = function(Pos, Item, UpdatePosition) { History.Add( this, { Type : historyitem_ParaRun_AddItem, Pos : Pos, EndPos : Pos, Items : [ Item ] } ); this.Content.splice( Pos, 0, Item ); if (true === UpdatePosition) this.private_UpdatePositionsOnAdd(Pos); // Обновляем позиции в NearestPos var NearPosLen = this.NearPosArray.length; for ( var Index = 0; Index < NearPosLen; Index++ ) { var RunNearPos = this.NearPosArray[Index]; var ContentPos = RunNearPos.NearPos.ContentPos; var Depth = RunNearPos.Depth; if ( ContentPos.Data[Depth] >= Pos ) ContentPos.Data[Depth]++; } // Обновляем позиции в поиске var SearchMarksCount = this.SearchMarks.length; for ( var Index = 0; Index < SearchMarksCount; Index++ ) { var Mark = this.SearchMarks[Index]; var ContentPos = ( true === Mark.Start ? Mark.SearchResult.StartPos : Mark.SearchResult.EndPos ); var Depth = Mark.Depth; if ( ContentPos.Data[Depth] >= Pos ) ContentPos.Data[Depth]++; } // Обновляем позиции для орфографии var SpellingMarksCount = this.SpellingMarks.length; for ( var Index = 0; Index < SpellingMarksCount; Index++ ) { var Mark = this.SpellingMarks[Index]; var ContentPos = ( true === Mark.Start ? Mark.Element.StartPos : Mark.Element.EndPos ); var Depth = Mark.Depth; if ( ContentPos.Data[Depth] >= Pos ) ContentPos.Data[Depth]++; } this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(true); // Обновляем позиции меток совместного редактирования this.CollaborativeMarks.Update_OnAdd( Pos ); // Отмечаем, что надо перемерить элементы в данном ране this.RecalcInfo.Measure = true; }; ParaRun.prototype.Remove_FromContent = function(Pos, Count, UpdatePosition) { // Получим массив удаляемых элементов var DeletedItems = this.Content.slice( Pos, Pos + Count ); History.Add( this, { Type : historyitem_Paragraph_RemoveItem, Pos : Pos, EndPos : Pos + Count - 1, Items : DeletedItems } ); this.Content.splice( Pos, Count ); if (true === UpdatePosition) this.private_UpdatePositionsOnRemove(Pos, Count); // Обновляем позиции в NearestPos var NearPosLen = this.NearPosArray.length; for ( var Index = 0; Index < NearPosLen; Index++ ) { var RunNearPos = this.NearPosArray[Index]; var ContentPos = RunNearPos.NearPos.ContentPos; var Depth = RunNearPos.Depth; if ( ContentPos.Data[Depth] > Pos + Count ) ContentPos.Data[Depth] -= Count; else if ( ContentPos.Data[Depth] > Pos ) ContentPos.Data[Depth] = Math.max( 0 , Pos ); } // Обновляем позиции в поиске var SearchMarksCount = this.SearchMarks.length; for ( var Index = 0; Index < SearchMarksCount; Index++ ) { var Mark = this.SearchMarks[Index]; var ContentPos = ( true === Mark.Start ? Mark.SearchResult.StartPos : Mark.SearchResult.EndPos ); var Depth = Mark.Depth; if ( ContentPos.Data[Depth] > Pos + Count ) ContentPos.Data[Depth] -= Count; else if ( ContentPos.Data[Depth] > Pos ) ContentPos.Data[Depth] = Math.max( 0 , Pos ); } // Обновляем позиции для орфографии var SpellingMarksCount = this.SpellingMarks.length; for ( var Index = 0; Index < SpellingMarksCount; Index++ ) { var Mark = this.SpellingMarks[Index]; var ContentPos = ( true === Mark.Start ? Mark.Element.StartPos : Mark.Element.EndPos ); var Depth = Mark.Depth; if ( ContentPos.Data[Depth] > Pos + Count ) ContentPos.Data[Depth] -= Count; else if ( ContentPos.Data[Depth] > Pos ) ContentPos.Data[Depth] = Math.max( 0 , Pos ); } this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(true); // Обновляем позиции меток совместного редактирования this.CollaborativeMarks.Update_OnRemove( Pos, Count ); // Отмечаем, что надо перемерить элементы в данном ране this.RecalcInfo.Measure = true; }; ParaRun.prototype.Concat_ToContent = function(NewItems) { var StartPos = this.Content.length; this.Content = this.Content.concat( NewItems ); History.Add( this, { Type : historyitem_ParaRun_AddItem, Pos : StartPos, EndPos : this.Content.length - 1, Items : NewItems, Color : false } ); this.private_UpdateTrackRevisionOnChangeContent(true); // Отмечаем, что надо перемерить элементы в данном ране this.RecalcInfo.Measure = true; }; // Определим строку и отрезок текущей позиции ParaRun.prototype.Get_CurrentParaPos = function() { var Pos = this.State.ContentPos; if (-1 === this.StartLine) return new CParaPos(-1, -1, -1, -1); var CurLine = 0; var CurRange = 0; var LinesCount = this.protected_GetLinesCount(); for (; CurLine < LinesCount; CurLine++) { var RangesCount = this.protected_GetRangesCount(CurLine); for (CurRange = 0; CurRange < RangesCount; CurRange++) { var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); if ( Pos < EndPos && Pos >= StartPos ) return new CParaPos((CurLine === 0 ? CurRange + this.StartRange : CurRange), CurLine + this.StartLine, 0, 0); } } // Значит курсор стоит в самом конце, поэтому посылаем последний отрезок if(this.Type == para_Math_Run && LinesCount > 1) { var Line = LinesCount - 1, Range = this.protected_GetRangesCount(LinesCount - 1) - 1; StartPos = this.protected_GetRangeStartPos(Line, Range); EndPos = this.protected_GetRangeEndPos(Line, Range); // учтем, что в одной строке в формуле может быть только один Range while(StartPos == EndPos && Line > 0 && this.Content.length !== 0) // == this.Content.length, т.к. последний Range { Line--; StartPos = this.protected_GetRangeStartPos(Line, Range); EndPos = this.protected_GetRangeEndPos(Line, Range); } return new CParaPos((this.protected_GetRangesCount(Line) - 1), Line + this.StartLine, 0, 0 ); } return new CParaPos((LinesCount <= 1 ? this.protected_GetRangesCount(0) - 1 + this.StartRange : this.protected_GetRangesCount(LinesCount - 1) - 1), LinesCount - 1 + this.StartLine, 0, 0 ); }; ParaRun.prototype.Get_ParaPosByContentPos = function(ContentPos, Depth) { if (this.StartRange < 0 || this.StartLine < 0) return new CParaPos(0, 0, 0, 0); var Pos = ContentPos.Get(Depth); var CurLine = 0; var CurRange = 0; var LinesCount = this.protected_GetLinesCount(); for (; CurLine < LinesCount; CurLine++) { var RangesCount = this.protected_GetRangesCount(CurLine); for (CurRange = 0; CurRange < RangesCount; CurRange++) { var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var bUpdateMathRun = Pos == EndPos && StartPos == EndPos && EndPos == this.Content.length && this.Type == para_Math_Run; // для para_Run позиция может быть после последнего элемента (пример: Run, за ним идет мат объект) if (Pos < EndPos && Pos >= StartPos || bUpdateMathRun) return new CParaPos((CurLine === 0 ? CurRange + this.StartRange : CurRange), CurLine + this.StartLine, 0, 0); } } return new CParaPos((LinesCount === 1 ? this.protected_GetRangesCount(0) - 1 + this.StartRange : this.protected_GetRangesCount(0) - 1), LinesCount - 1 + this.StartLine, 0, 0); }; ParaRun.prototype.Recalculate_CurPos = function(X, Y, CurrentRun, _CurRange, _CurLine, CurPage, UpdateCurPos, UpdateTarget, ReturnTarget) { var Para = this.Paragraph; var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var Pos = StartPos; var _EndPos = ( true === CurrentRun ? Math.min( EndPos, this.State.ContentPos ) : EndPos ); if(this.Type == para_Math_Run) { var Lng = this.Content.length; Pos = _EndPos; var LocParaMath = this.ParaMath.GetLinePosition(_CurLine, _CurRange); X = LocParaMath.x; Y = LocParaMath.y; var MATH_Y = Y; var loc; if(Lng == 0) { X += this.pos.x; Y += this.pos.y; } else if(Pos < EndPos) { loc = this.Content[Pos].GetLocationOfLetter(); X += loc.x; Y += loc.y; } else if(!(StartPos == EndPos)) // исключаем этот случай StartPos == EndPos && EndPos == Pos, это возможно когда конец Run находится в начале строки, при этом ни одна из букв этого Run не входит в эту строку { var Letter = this.Content[Pos - 1]; loc = Letter.GetLocationOfLetter(); X += loc.x + Letter.Get_WidthVisible(); Y += loc.y; } } else { for ( ; Pos < _EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; switch( ItemType ) { case para_Text: case para_Space: case para_Sym: case para_PageNum: case para_Tab: case para_End: case para_NewLine: case para_Math_Text: case para_Math_BreakOperator: case para_Math_Placeholder: case para_Math_Ampersand: { X += Item.Get_WidthVisible(); break; } case para_Drawing: { if ( drawing_Inline != Item.DrawingType ) break; X += Item.Get_WidthVisible(); break; } } } } if ( true === CurrentRun && Pos === this.State.ContentPos ) { if ( true === UpdateCurPos ) { // Обновляем позицию курсора в параграфе Para.CurPos.X = X; Para.CurPos.Y = Y; Para.CurPos.PagesPos = CurPage; if ( true === UpdateTarget ) { var CurTextPr = this.Get_CompiledPr(false); g_oTextMeasurer.SetTextPr( CurTextPr, this.Paragraph.Get_Theme() ); g_oTextMeasurer.SetFontSlot( fontslot_ASCII, CurTextPr.Get_FontKoef() ); var Height = g_oTextMeasurer.GetHeight(); var Descender = Math.abs( g_oTextMeasurer.GetDescender() ); var Ascender = Height - Descender; Para.DrawingDocument.SetTargetSize( Height ); var RGBA; if(CurTextPr.TextFill) { CurTextPr.TextFill.check(Para.Get_Theme(), Para.Get_ColorMap()); var oColor = CurTextPr.TextFill.getRGBAColor(); Para.DrawingDocument.SetTargetColor( oColor.R, oColor.G, oColor.B ); } else if(CurTextPr.Unifill) { CurTextPr.Unifill.check(Para.Get_Theme(), Para.Get_ColorMap()); RGBA = CurTextPr.Unifill.getRGBAColor(); Para.DrawingDocument.SetTargetColor( RGBA.R, RGBA.G, RGBA.B ); } else { if ( true === CurTextPr.Color.Auto ) { // Выясним какая заливка у нашего текста var Pr = Para.Get_CompiledPr(); var BgColor = undefined; if ( undefined !== Pr.ParaPr.Shd && shd_Nil !== Pr.ParaPr.Shd.Value ) { if(Pr.ParaPr.Shd.Unifill) { Pr.ParaPr.Shd.Unifill.check(this.Paragraph.Get_Theme(), this.Paragraph.Get_ColorMap()); var RGBA = Pr.ParaPr.Shd.Unifill.getRGBAColor(); BgColor = new CDocumentColor(RGBA.R, RGBA.G, RGBA.B, false); } else { BgColor = Pr.ParaPr.Shd.Color; } } else { // Нам надо выяснить заливку у родительского класса (возможно мы находимся в ячейке таблицы с забивкой) BgColor = Para.Parent.Get_TextBackGroundColor(); if ( undefined !== CurTextPr.Shd && shd_Nil !== CurTextPr.Shd.Value ) BgColor = CurTextPr.Shd.Get_Color( this.Paragraph ); } // Определим автоцвет относительно заливки var AutoColor = ( undefined != BgColor && false === BgColor.Check_BlackAutoColor() ? new CDocumentColor( 255, 255, 255, false ) : new CDocumentColor( 0, 0, 0, false ) ); Para.DrawingDocument.SetTargetColor( AutoColor.r, AutoColor.g, AutoColor.b ); } else Para.DrawingDocument.SetTargetColor( CurTextPr.Color.r, CurTextPr.Color.g, CurTextPr.Color.b ); } var TargetY = Y - Ascender - CurTextPr.Position; switch( CurTextPr.VertAlign ) { case vertalign_SubScript: { TargetY -= CurTextPr.FontSize * g_dKoef_pt_to_mm * vertalign_Koef_Sub; break; } case vertalign_SuperScript: { TargetY -= CurTextPr.FontSize * g_dKoef_pt_to_mm * vertalign_Koef_Super; break; } } var Page_Abs = Para.Get_StartPage_Absolute() + CurPage; Para.DrawingDocument.UpdateTarget( X, TargetY, Page_Abs ); // TODO: Тут делаем, чтобы курсор не выходил за границы буквицы. На самом деле, надо делать, чтобы // курсор не выходил за границы строки, но для этого надо делать обрезку по строкам, а без нее // такой вариант будет смотреться плохо. if ( undefined != Para.Get_FramePr() ) { var __Y0 = TargetY, __Y1 = TargetY + Height; var ___Y0 = Para.Pages[CurPage].Y + Para.Lines[CurLine].Top; var ___Y1 = Para.Pages[CurPage].Y + Para.Lines[CurLine].Bottom; __Y0 = Math.max( __Y0, ___Y0 ); __Y1 = Math.min( __Y1, ___Y1 ); Para.DrawingDocument.SetTargetSize( __Y1 - __Y0 ); Para.DrawingDocument.UpdateTarget( X, __Y0, Page_Abs ); } if (para_Math_Run === this.Type && null !== this.Parent && true !== this.Parent.bRoot && this.Parent.bMath_OneLine) { var oBounds = this.Parent.Get_Bounds(); var __Y0 = TargetY, __Y1 = TargetY + Height; //var ___Y0 = oBounds.Y - 0.2 * oBounds.H; //var ___Y1 = oBounds.Y + 1.4 * oBounds.H; // пока так // TO DO : переделать var YY = this.Parent.pos.y - this.Parent.size.ascent, XX = this.Parent.pos.x; var ___Y0 = MATH_Y + YY - 0.2 * oBounds.H; var ___Y1 = MATH_Y + YY + 1.4 * oBounds.H; __Y0 = Math.max( __Y0, ___Y0 ); __Y1 = Math.min( __Y1, ___Y1 ); Para.DrawingDocument.SetTargetSize( __Y1 - __Y0 ); Para.DrawingDocument.UpdateTarget( X, __Y0, Page_Abs ); } } } if ( true === ReturnTarget ) { var CurTextPr = this.Get_CompiledPr(false); g_oTextMeasurer.SetTextPr( CurTextPr, this.Paragraph.Get_Theme() ); g_oTextMeasurer.SetFontSlot( fontslot_ASCII, CurTextPr.Get_FontKoef() ); var Height = g_oTextMeasurer.GetHeight(); var Descender = Math.abs( g_oTextMeasurer.GetDescender() ); var Ascender = Height - Descender; var TargetY = Y - Ascender - CurTextPr.Position; switch( CurTextPr.VertAlign ) { case vertalign_SubScript: { TargetY -= CurTextPr.FontSize * g_dKoef_pt_to_mm * vertalign_Koef_Sub; break; } case vertalign_SuperScript: { TargetY -= CurTextPr.FontSize * g_dKoef_pt_to_mm * vertalign_Koef_Super; break; } } return { X : X, Y : TargetY, Height : Height, PageNum : CurPage + Para.Get_StartPage_Absolute(), Internal : { Line : CurLine, Page : CurPage, Range : CurRange } }; } else return { X : X, Y : Y, PageNum : CurPage + Para.Get_StartPage_Absolute(), Internal : { Line : CurLine, Page : CurPage, Range : CurRange } }; } return { X : X, Y: Y, PageNum : CurPage + Para.Get_StartPage_Absolute(), Internal : { Line : CurLine, Page : CurPage, Range : CurRange } }; }; // Проверяем, произошло ли простейшее изменение (набор или удаление текста) ParaRun.prototype.Is_SimpleChanges = function(Changes) { var ParaPos = null; var Count = Changes.length; for (var Index = 0; Index < Count; Index++) { var Data = Changes[Index].Data; if (undefined === Data.Items || 1 !== Data.Items.length) return false; var Type = Data.Type; var Item = Data.Items[0]; if (undefined === Item) return false; if (historyitem_ParaRun_AddItem !== Type && historyitem_ParaRun_RemoveItem !== Type) return false; // Добавление/удаление картинок может изменить размер строки. Добавление/удаление переноса строки/страницы/колонки // нельзя обсчитывать функцией Recalculate_Fast. // TODO: Но на самом деле стоило бы сделать нормальную проверку на высоту строки в функции Recalculate_Fast var ItemType = Item.Type; if (para_Drawing === ItemType || para_NewLine === ItemType) return false; // Проверяем, что все изменения произошли в одном и том же отрезке var CurParaPos = this.Get_SimpleChanges_ParaPos([Changes[Index]]); if (null === CurParaPos) return false; if (null === ParaPos) ParaPos = CurParaPos; else if (ParaPos.Line !== CurParaPos.Line || ParaPos.Range !== CurParaPos.Range) return false; } return true; }; /* Проверяем произошло ли простое изменение параграфа, сейчас главное, чтобы это было не добавление или удаление картинки. На вход приходит либо массив изменений, либо одно изменение (можно не в массиве). */ ParaRun.prototype.Is_ParagraphSimpleChanges = function(_Changes) { var Changes = _Changes; if (!_Changes.length) Changes = [_Changes]; var ChangesCount = Changes.length; for (var ChangesIndex = 0; ChangesIndex < ChangesCount; ChangesIndex++) { var Data = Changes[ChangesIndex].Data; var ChangeType = Data.Type; if (historyitem_ParaRun_AddItem === ChangeType || historyitem_ParaRun_RemoveItem === ChangeType) { for (var ItemIndex = 0, ItemsCount = Data.Items.length; ItemIndex < ItemsCount; ItemIndex++) { var Item = Data.Items[ItemIndex]; if (para_Drawing === Item.Type) return false; } } } return true; }; // Возвращаем строку и отрезок, в котором произошли простейшие изменения ParaRun.prototype.Get_SimpleChanges_ParaPos = function(Changes) { var Change = Changes[0].Data; var Type = Changes[0].Data.Type; var Pos = Change.Pos; var CurLine = 0; var CurRange = 0; var LinesCount = this.protected_GetLinesCount(); for (; CurLine < LinesCount; CurLine++) { var RangesCount = this.protected_GetRangesCount(CurLine); for (CurRange = 0; CurRange < RangesCount; CurRange++) { var RangeStartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var RangeEndPos = this.protected_GetRangeEndPos(CurLine, CurRange); if ( ( historyitem_ParaRun_AddItem === Type && Pos < RangeEndPos && Pos >= RangeStartPos ) || ( historyitem_ParaRun_RemoveItem === Type && Pos < RangeEndPos && Pos >= RangeStartPos ) || ( historyitem_ParaRun_RemoveItem === Type && Pos >= RangeEndPos && CurLine === LinesCount - 1 && CurRange === RangesCount - 1 ) ) { // Если отрезок остается пустым, тогда надо все заново пересчитывать if ( RangeStartPos === RangeEndPos ) return null; return new CParaPos( ( CurLine === 0 ? CurRange + this.StartRange : CurRange ), CurLine + this.StartLine, 0, 0 ); } } } // Если отрезок остается пустым, тогда надо все заново пересчитывать if (this.protected_GetRangeStartPos(0, 0) === this.protected_GetRangeEndPos(0, 0)) return null; return new CParaPos( this.StartRange, this.StartLine, 0, 0 ); }; ParaRun.prototype.Split = function (ContentPos, Depth) { var CurPos = ContentPos.Get(Depth); return this.Split2( CurPos ); }; ParaRun.prototype.Split2 = function(CurPos, Parent, ParentPos) { History.Add(this, {Type : historyitem_ParaRun_OnStartSplit, Pos : CurPos}); CollaborativeEditing.OnStart_SplitRun(this, CurPos); // Если задается Parent и ParentPos, тогда ран автоматически добавляется в родительский класс var UpdateParent = (undefined !== Parent && undefined !== ParentPos && this === Parent.Content[ParentPos] ? true : false); var UpdateSelection = (true === UpdateParent && true === Parent.Is_SelectionUse() && true === this.Is_SelectionUse() ? true : false); // Создаем новый ран var bMathRun = this.Type == para_Math_Run; var NewRun = new ParaRun(this.Paragraph, bMathRun); // Копируем настройки NewRun.Set_Pr(this.Pr.Copy(true)); NewRun.Set_ReviewType(this.ReviewType); NewRun.CollPrChangeMine = this.CollPrChangeMine; NewRun.CollPrChangeOther = this.CollPrChangeOther; if(bMathRun) NewRun.Set_MathPr(this.MathPrp.Copy()); // TODO: Как только избавимся от para_End переделать тут // Проверим, если наш ран содержит para_End, тогда мы должны para_End переметить в правый ран var CheckEndPos = -1; var CheckEndPos2 = Math.min( CurPos, this.Content.length ); for ( var Pos = 0; Pos < CheckEndPos2; Pos++ ) { if ( para_End === this.Content[Pos].Type ) { CheckEndPos = Pos; break; } } if ( -1 !== CheckEndPos ) CurPos = CheckEndPos; var ParentOldSelectionStartPos, ParentOldSelectionEndPos, OldSelectionStartPos, OldSelectionEndPos; if (true === UpdateSelection) { ParentOldSelectionStartPos = Parent.Selection.StartPos; ParentOldSelectionEndPos = Parent.Selection.EndPos; OldSelectionStartPos = this.Selection.StartPos; OldSelectionEndPos = this.Selection.EndPos; } if (true === UpdateParent) { Parent.Add_ToContent(ParentPos + 1, NewRun); // Обновим массив NearPosArray for (var Index = 0, Count = this.NearPosArray.length; Index < Count; Index++) { var RunNearPos = this.NearPosArray[Index]; var ContentPos = RunNearPos.NearPos.ContentPos; var Depth = RunNearPos.Depth; var Pos = ContentPos.Get(Depth); if (Pos >= CurPos) { ContentPos.Update2(Pos - CurPos, Depth); ContentPos.Update2(ParentPos + 1, Depth - 1); this.NearPosArray.splice(Index, 1); Count--; Index--; NewRun.NearPosArray.push(RunNearPos); if (this.Paragraph) { for (var ParaIndex = 0, ParaCount = this.Paragraph.NearPosArray.length; ParaIndex < ParaCount; ParaIndex++) { var ParaNearPos = this.Paragraph.NearPosArray[ParaIndex]; if (ParaNearPos.Classes[ParaNearPos.Classes.length - 1] === this) ParaNearPos.Classes[ParaNearPos.Classes.length - 1] = NewRun; } } } } } // Разделяем содержимое по ранам NewRun.Concat_ToContent( this.Content.slice(CurPos) ); this.Remove_FromContent( CurPos, this.Content.length - CurPos, true ); // Если были точки орфографии, тогда переместим их в новый ран var SpellingMarksCount = this.SpellingMarks.length; for ( var Index = 0; Index < SpellingMarksCount; Index++ ) { var Mark = this.SpellingMarks[Index]; var MarkPos = ( true === Mark.Start ? Mark.Element.StartPos.Get(Mark.Depth) : Mark.Element.EndPos.Get(Mark.Depth) ); if ( MarkPos >= CurPos ) { var MarkElement = Mark.Element; if ( true === Mark.Start ) { MarkElement.StartPos.Data[Mark.Depth] -= CurPos; } else { MarkElement.EndPos.Data[Mark.Depth] -= CurPos; } NewRun.SpellingMarks.push( Mark ); this.SpellingMarks.splice( Index, 1 ); SpellingMarksCount--; Index--; } } if (true === UpdateSelection) { if (ParentOldSelectionStartPos <= ParentPos && ParentPos <= ParentOldSelectionEndPos) Parent.Selection.EndPos = ParentOldSelectionEndPos + 1; else if (ParentOldSelectionEndPos <= ParentPos && ParentPos <= ParentOldSelectionStartPos) Parent.Selection.StartPos = ParentOldSelectionStartPos + 1; if (OldSelectionStartPos <= CurPos && CurPos <= OldSelectionEndPos) { this.Selection.EndPos = this.Content.length; NewRun.Selection.Use = true; NewRun.Selection.StartPos = 0; NewRun.Selection.EndPos = OldSelectionEndPos - CurPos; } else if (OldSelectionEndPos <= CurPos && CurPos <= OldSelectionStartPos) { this.Selection.StartPos = this.Content.length; NewRun.Selection.Use = true; NewRun.Selection.EndPos = 0; NewRun.Selection.StartPos = OldSelectionStartPos - CurPos; } } History.Add(this, {Type : historyitem_ParaRun_OnEndSplit, NewRun : NewRun}); CollaborativeEditing.OnEnd_SplitRun(NewRun); return NewRun; }; ParaRun.prototype.Check_NearestPos = function(ParaNearPos, Depth) { var RunNearPos = new CParagraphElementNearPos(); RunNearPos.NearPos = ParaNearPos.NearPos; RunNearPos.Depth = Depth; this.NearPosArray.push( RunNearPos ); ParaNearPos.Classes.push( this ); }; ParaRun.prototype.Get_DrawingObjectRun = function(Id) { var ContentLen = this.Content.length; for ( var CurPos = 0; CurPos < ContentLen; CurPos++ ) { var Element = this.Content[CurPos]; if ( para_Drawing === Element.Type && Id === Element.Get_Id() ) return this; } return null; }; ParaRun.prototype.Get_DrawingObjectContentPos = function(Id, ContentPos, Depth) { var ContentLen = this.Content.length; for ( var CurPos = 0; CurPos < ContentLen; CurPos++ ) { var Element = this.Content[CurPos]; if ( para_Drawing === Element.Type && Id === Element.Get_Id() ) { ContentPos.Update( CurPos, Depth ); return true; } } return false; }; ParaRun.prototype.Get_DrawingObjectSimplePos = function(Id) { var ContentLen = this.Content.length; for (var CurPos = 0; CurPos < ContentLen; CurPos++) { var Element = this.Content[CurPos]; if (para_Drawing === Element.Type && Id === Element.Get_Id()) return CurPos; } return -1; }; ParaRun.prototype.Remove_DrawingObject = function(Id) { var ContentLen = this.Content.length; for ( var CurPos = 0; CurPos < ContentLen; CurPos++ ) { var Element = this.Content[CurPos]; if ( para_Drawing === Element.Type && Id === Element.Get_Id() ) { var TrackRevisions = null; if (this.Paragraph && this.Paragraph.LogicDocument) TrackRevisions = this.Paragraph.LogicDocument.Is_TrackRevisions(); if (true === TrackRevisions) { var ReviewType = this.Get_ReviewType(); if (reviewtype_Common === ReviewType) { // Разбиваем ран на две части var StartPos = CurPos; var EndPos = CurPos + 1; var Parent = this.Get_Parent(); var RunPos = this.private_GetPosInParent(Parent); if (-1 !== RunPos && Parent) { var DeletedRun = null; if (StartPos <= 0 && EndPos >= this.Content.length) DeletedRun = this; else if (StartPos <= 0) { this.Split2(EndPos, Parent, RunPos); DeletedRun = this; } else if (EndPos >= this.Content.length) { DeletedRun = this.Split2(StartPos, Parent, RunPos); } else { this.Split2(EndPos, Parent, RunPos); DeletedRun = this.Split2(StartPos, Parent, RunPos); } DeletedRun.Set_ReviewType(reviewtype_Remove); } } else if (reviewtype_Add === ReviewType) { this.Remove_FromContent(CurPos, 1, true); } else if (reviewtype_Remove === ReviewType) { // Ничего не делаем } } else { this.Remove_FromContent(CurPos, 1, true); } return; } } }; ParaRun.prototype.Get_Layout = function(DrawingLayout, UseContentPos, ContentPos, Depth) { var CurLine = DrawingLayout.Line - this.StartLine; var CurRange = ( 0 === CurLine ? DrawingLayout.Range - this.StartRange : DrawingLayout.Range ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var CurContentPos = ( true === UseContentPos ? ContentPos.Get(Depth) : -1 ); var CurPos = StartPos; for ( ; CurPos < EndPos; CurPos++ ) { if ( CurContentPos === CurPos ) break; var Item = this.Content[CurPos]; var ItemType = Item.Type; var WidthVisible = Item.Get_WidthVisible(); switch ( ItemType ) { case para_Text: case para_Space: case para_PageNum: { DrawingLayout.LastW = WidthVisible; break; } case para_Drawing: { if ( true === Item.Is_Inline() || true === DrawingLayout.Paragraph.Parent.Is_DrawingShape() ) { DrawingLayout.LastW = WidthVisible; } break; } } DrawingLayout.X += WidthVisible; } if (CurContentPos === CurPos) DrawingLayout.Layout = true; }; ParaRun.prototype.Get_NextRunElements = function(RunElements, UseContentPos, Depth) { var StartPos = ( true === UseContentPos ? RunElements.ContentPos.Get(Depth) : 0 ); var ContentLen = this.Content.length; for ( var CurPos = StartPos; CurPos < ContentLen; CurPos++ ) { var Item = this.Content[CurPos]; var ItemType = Item.Type; if ( para_Text === ItemType || para_Space === ItemType || para_Tab === ItemType) { RunElements.Elements.push( Item ); RunElements.Count--; if ( RunElements.Count <= 0 ) return; } } }; ParaRun.prototype.Get_PrevRunElements = function(RunElements, UseContentPos, Depth) { var StartPos = ( true === UseContentPos ? RunElements.ContentPos.Get(Depth) - 1 : this.Content.length - 1 ); var ContentLen = this.Content.length; for ( var CurPos = StartPos; CurPos >= 0; CurPos-- ) { var Item = this.Content[CurPos]; var ItemType = Item.Type; if ( para_Text === ItemType || para_Space === ItemType || para_Tab === ItemType ) { RunElements.Elements.push( Item ); RunElements.Count--; if ( RunElements.Count <= 0 ) return; } } }; ParaRun.prototype.Collect_DocumentStatistics = function(ParaStats) { var Count = this.Content.length; for ( var Index = 0; Index < Count; Index++ ) { var Item = this.Content[Index]; var ItemType = Item.Type; var bSymbol = false; var bSpace = false; var bNewWord = false; if ((para_Text === ItemType && false === Item.Is_NBSP()) || (para_PageNum === ItemType)) { if ( false === ParaStats.Word ) bNewWord = true; bSymbol = true; bSpace = false; ParaStats.Word = true; ParaStats.EmptyParagraph = false; } else if ((para_Text === ItemType && true === Item.Is_NBSP()) || para_Space === ItemType || para_Tab === ItemType) { bSymbol = true; bSpace = true; ParaStats.Word = false; } if ( true === bSymbol ) ParaStats.Stats.Add_Symbol( bSpace ); if ( true === bNewWord ) ParaStats.Stats.Add_Word(); } }; ParaRun.prototype.Create_FontMap = function(Map, ArgSize) { // для Math_Para_Pun argSize учитывается, когда мержатся текстовые настройки в Internal_Compile_Pr() if ( undefined !== this.Paragraph && null !== this.Paragraph ) { var TextPr; var FontSize, FontSizeCS; if(this.Type === para_Math_Run) { TextPr = this.Get_CompiledPr(false); FontSize = TextPr.FontSize; FontSizeCS = TextPr.FontSizeCS; if(null !== this.Parent && undefined !== this.Parent && null !== this.Parent.ParaMath && undefined !== this.Parent.ParaMath) { TextPr.FontSize *= MatGetKoeffArgSize(TextPr.FontSize, ArgSize.value); TextPr.FontSizeCS *= MatGetKoeffArgSize(TextPr.FontSizeCS, ArgSize.value); } } else TextPr = this.Get_CompiledPr(false); TextPr.Document_CreateFontMap(Map, this.Paragraph.Get_Theme().themeElements.fontScheme); var Count = this.Content.length; for (var Index = 0; Index < Count; Index++) { var Item = this.Content[Index]; if ( para_Drawing === Item.Type ) Item.documentCreateFontMap( Map ); } if(this.Type === para_Math_Run) { TextPr.FontSize = FontSize; TextPr.FontSizeCS = FontSizeCS; } } }; ParaRun.prototype.Get_AllFontNames = function(AllFonts) { this.Pr.Document_Get_AllFontNames( AllFonts ); var Count = this.Content.length; for (var Index = 0; Index < Count; Index++) { var Item = this.Content[Index]; if ( para_Drawing === Item.Type ) Item.documentGetAllFontNames( AllFonts ); } }; ParaRun.prototype.Get_SelectedText = function(bAll, bClearText) { var StartPos = 0; var EndPos = 0; if ( true === bAll ) { StartPos = 0; EndPos = this.Content.length; } else if ( true === this.Selection.Use ) { StartPos = this.State.Selection.StartPos; EndPos = this.State.Selection.EndPos; if ( StartPos > EndPos ) { var Temp = EndPos; EndPos = StartPos; StartPos = Temp; } } var Str = ""; for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; switch ( ItemType ) { case para_Drawing: //case para_End: case para_Numbering: case para_PresentationNumbering: case para_PageNum: { if ( true === bClearText ) return null; break; } case para_Text : Str += String.fromCharCode(Item.Value); break; case para_Space: case para_Tab : Str += " "; break; } } return Str; }; ParaRun.prototype.Get_SelectionDirection = function() { if (true !== this.Selection.Use) return 0; if (this.Selection.StartPos <= this.Selection.EndPos) return 1; return -1; }; ParaRun.prototype.Can_AddDropCap = function() { var Count = this.Content.length; for ( var Pos = 0; Pos < Count; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; switch ( ItemType ) { case para_Text: return true; case para_Space: case para_Tab: case para_PageNum: return false; } } return null; }; ParaRun.prototype.Get_TextForDropCap = function(DropCapText, UseContentPos, ContentPos, Depth) { var EndPos = ( true === UseContentPos ? ContentPos.Get(Depth) : this.Content.length ); for ( var Pos = 0; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; if ( true === DropCapText.Check ) { if ( para_Space === ItemType || para_Tab === ItemType || para_PageNum === ItemType || para_Drawing === ItemType ) { DropCapText.Mixed = true; return; } } else { if ( para_Text === ItemType ) { DropCapText.Runs.push(this); DropCapText.Text.push(Item); this.Remove_FromContent( Pos, 1, true ); Pos--; EndPos--; if ( true === DropCapText.Mixed ) return; } } } }; ParaRun.prototype.Get_StartTabsCount = function(TabsCounter) { var ContentLen = this.Content.length; for ( var Pos = 0; Pos < ContentLen; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; if ( para_Tab === ItemType ) { TabsCounter.Count++; TabsCounter.Pos.push( Pos ); } else if ( para_Text === ItemType || para_Space === ItemType || (para_Drawing === ItemType && true === Item.Is_Inline() ) || para_PageNum === ItemType || para_Math === ItemType ) return false; } return true; }; ParaRun.prototype.Remove_StartTabs = function(TabsCounter) { var ContentLen = this.Content.length; for ( var Pos = 0; Pos < ContentLen; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; if ( para_Tab === ItemType ) { this.Remove_FromContent( Pos, 1, true ); TabsCounter.Count--; Pos--; ContentLen--; } else if ( para_Text === ItemType || para_Space === ItemType || (para_Drawing === ItemType && true === Item.Is_Inline() ) || para_PageNum === ItemType || para_Math === ItemType ) return false; } return true; }; //----------------------------------------------------------------------------------- // Функции пересчета //----------------------------------------------------------------------------------- // Пересчитываем размеры всех элементов ParaRun.prototype.Recalculate_MeasureContent = function() { if ( false === this.RecalcInfo.Measure ) return; var Pr = this.Get_CompiledPr(false); var Theme = this.Paragraph.Get_Theme(); g_oTextMeasurer.SetTextPr(Pr, Theme); g_oTextMeasurer.SetFontSlot(fontslot_ASCII); // Запрашиваем текущие метрики шрифта, под TextAscent мы будем понимать ascent + linegap(которые записаны в шрифте) this.TextHeight = g_oTextMeasurer.GetHeight(); this.TextDescent = Math.abs( g_oTextMeasurer.GetDescender() ); this.TextAscent = this.TextHeight - this.TextDescent; this.TextAscent2 = g_oTextMeasurer.GetAscender(); this.YOffset = Pr.Position; var ContentLength = this.Content.length; var InfoMathText; if(para_Math_Run == this.Type) { var InfoTextPr = { TextPr: Pr, ArgSize: this.Parent.Compiled_ArgSz.value, bNormalText: this.IsNormalText(), bEqArray: this.Parent.IsEqArray() }; InfoMathText = new CMathInfoTextPr(InfoTextPr); } for ( var Pos = 0; Pos < ContentLength; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; if (para_Drawing === ItemType) { Item.Parent = this.Paragraph; Item.DocumentContent = this.Paragraph.Parent; Item.DrawingDocument = this.Paragraph.Parent.DrawingDocument; } // TODO: Как только избавимся от para_End переделать здесь if ( para_End === ItemType ) { var EndTextPr = this.Paragraph.Get_CompiledPr2(false).TextPr.Copy(); EndTextPr.Merge(this.Paragraph.TextPr.Value); g_oTextMeasurer.SetTextPr( EndTextPr, this.Paragraph.Get_Theme()); Item.Measure( g_oTextMeasurer, EndTextPr ); continue; } Item.Measure( g_oTextMeasurer, Pr, InfoMathText ); if (para_Drawing === Item.Type) { // После автофигур надо заново выставлять настройки g_oTextMeasurer.SetTextPr(Pr, Theme); g_oTextMeasurer.SetFontSlot(fontslot_ASCII); } } this.RecalcInfo.Recalc = true; this.RecalcInfo.Measure = false; }; ParaRun.prototype.Recalculate_Measure2 = function(Metrics) { var TAscent = Metrics.Ascent; var TDescent = Metrics.Descent; var Count = this.Content.length; for ( var Index = 0; Index < Count; Index++ ) { var Item = this.Content[Index]; var ItemType = Item.Type; if ( para_Text === ItemType ) { var Temp = g_oTextMeasurer.Measure2(String.fromCharCode(Item.Value)); if ( null === TAscent || TAscent < Temp.Ascent ) TAscent = Temp.Ascent; if ( null === TDescent || TDescent > Temp.Ascent - Temp.Height ) TDescent = Temp.Ascent - Temp.Height; } } Metrics.Ascent = TAscent; Metrics.Descent = TDescent; }; ParaRun.prototype.Recalculate_Range = function(PRS, ParaPr, Depth) { if ( this.Paragraph !== PRS.Paragraph ) { this.Paragraph = PRS.Paragraph; this.RecalcInfo.TextPr = true; this.RecalcInfo.Measure = true; this.protected_UpdateSpellChecking(); } // Сначала измеряем элементы (можно вызывать каждый раз, внутри разруливается, чтобы измерялось 1 раз) this.Recalculate_MeasureContent(); var CurLine = PRS.Line - this.StartLine; var CurRange = ( 0 === CurLine ? PRS.Range - this.StartRange : PRS.Range ); // Если мы рассчитываем первый отрезок в первой строке, тогда нам нужно обновить информацию о нумерации if ( 0 === CurRange && 0 === CurLine ) { var PrevRecalcInfo = PRS.RunRecalcInfoLast; // Либо до этого ничего не было (изначально первая строка и первый отрезок), либо мы заново пересчитываем // первую строку и первый отрезок (из-за обтекания, например). if ( null === PrevRecalcInfo ) this.RecalcInfo.NumberingAdd = true; else this.RecalcInfo.NumberingAdd = PrevRecalcInfo.NumberingAdd; this.RecalcInfo.NumberingUse = false; this.RecalcInfo.NumberingItem = null; } // Сохраняем ссылку на информацию пересчета данного рана PRS.RunRecalcInfoLast = this.RecalcInfo; // Добавляем информацию о новом отрезке var RangeStartPos = this.protected_AddRange(CurLine, CurRange); var RangeEndPos = 0; var Para = PRS.Paragraph; var MoveToLBP = PRS.MoveToLBP; var NewRange = PRS.NewRange; var ForceNewPage = PRS.ForceNewPage; var NewPage = PRS.NewPage; var BreakPageLine = PRS.BreakPageLine; var End = PRS.End; var Word = PRS.Word; var StartWord = PRS.StartWord; var FirstItemOnLine = PRS.FirstItemOnLine; var EmptyLine = PRS.EmptyLine; var RangesCount = PRS.RangesCount; var SpaceLen = PRS.SpaceLen; var WordLen = PRS.WordLen; var X = PRS.X; var XEnd = PRS.XEnd; var ParaLine = PRS.Line; var ParaRange = PRS.Range; var bMathWordLarge = PRS.bMathWordLarge; var OperGapRight = PRS.OperGapRight; var OperGapLeft = PRS.OperGapLeft; var bInsideOper = PRS.bInsideOper; var bContainCompareOper = PRS.bContainCompareOper; var bEndRunToContent = PRS.bEndRunToContent; var bNoOneBreakOperator = PRS.bNoOneBreakOperator; var BreakBox = PRS.BreakBox; var Pos = RangeStartPos; var ContentLen = this.Content.length; var XRange = PRS.XRange; var oSectionPr = undefined; if (false === StartWord && true === FirstItemOnLine && XEnd - X < 0.001 && RangesCount > 0) { NewRange = true; RangeEndPos = Pos; } else { for (; Pos < ContentLen; Pos++) { var Item = this.Content[Pos]; var ItemType = Item.Type; // Проверяем, не нужно ли добавить нумерацию к данному элементу if (true === this.RecalcInfo.NumberingAdd && true === Item.Can_AddNumbering()) X = this.private_RecalculateNumbering(PRS, Item, ParaPr, X); switch (ItemType) { case para_Sym: case para_Text: { // Отмечаем, что началось слово StartWord = true; // При проверке, убирается ли слово, мы должны учитывать ширину предшествующих пробелов. var LetterLen = Item.Width / TEXTWIDTH_DIVIDER;//var LetterLen = Item.Get_Width(); if (true !== Word) { // Слово только началось. Делаем следующее: // 1) Если до него на строке ничего не было и данная строка не // имеет разрывов, тогда не надо проверять убирается ли слово в строке. // 2) В противном случае, проверяем убирается ли слово в промежутке. // Если слово только началось, и до него на строке ничего не было, и в строке нет разрывов, тогда не надо проверять убирается ли оно на строке. if (true !== FirstItemOnLine || false === Para.Internal_Check_Ranges(ParaLine, ParaRange)) { if (X + SpaceLen + LetterLen > XEnd) { NewRange = true; RangeEndPos = Pos; } } if (true !== NewRange) { // Отмечаем начало нового слова PRS.Set_LineBreakPos(Pos); // Если текущий символ с переносом, например, дефис, тогда на нем заканчивается слово if (Item.Flags & PARATEXT_FLAGS_SPACEAFTER)//if ( true === Item.Is_SpaceAfter() ) { // Добавляем длину пробелов до слова и ширину самого слова. X += SpaceLen + LetterLen; Word = false; FirstItemOnLine = false; EmptyLine = false; SpaceLen = 0; WordLen = 0; } else { Word = true; WordLen = LetterLen; } } } else { if(X + SpaceLen + WordLen + LetterLen > XEnd) { if(true === FirstItemOnLine) { // Слово оказалось единственным элементом в промежутке, и, все равно, // не умещается целиком. Делаем следующее: // // // 1) Если у нас строка без вырезов, тогда ставим перенос строки на // текущей позиции. // 2) Если у нас строка с вырезом, и данный вырез не последний, тогда // ставим перенос внутри строки в начале слова. // 3) Если у нас строка с вырезом и вырез последний, тогда ставим перенос // строки в начале слова. if (false === Para.Internal_Check_Ranges(ParaLine, ParaRange)) { // Слово не убирается в отрезке. Переносим слово в следующий отрезок MoveToLBP = true; NewRange = true; } else { EmptyLine = false; X += WordLen; // Слово не убирается в отрезке, но, поскольку, слово 1 на строке и отрезок тоже 1, // делим слово в данном месте NewRange = true; RangeEndPos = Pos; } } else { // Слово не убирается в отрезке. Переносим слово в следующий отрезок MoveToLBP = true; NewRange = true; } } if (true !== NewRange) { // Мы убираемся в пределах данной строки. Прибавляем ширину буквы к ширине слова WordLen += LetterLen; // Если текущий символ с переносом, например, дефис, тогда на нем заканчивается слово if (Item.Flags & PARATEXT_FLAGS_SPACEAFTER)//if ( true === Item.Is_SpaceAfter() ) { // Добавляем длину пробелов до слова и ширину самого слова. X += SpaceLen + WordLen; Word = false; FirstItemOnLine = false; EmptyLine = false; SpaceLen = 0; WordLen = 0; } } } break; } case para_Math_Text: case para_Math_Ampersand: case para_Math_Placeholder: { // Отмечаем, что началось слово StartWord = true; // При проверке, убирается ли слово, мы должны учитывать ширину предшествующих пробелов. var LetterLen = Item.Get_Width2() / TEXTWIDTH_DIVIDER;//var LetterLen = Item.Get_Width(); if (true !== Word) { // Если слово только началось, и до него на строке ничего не было, и в строке нет разрывов, тогда не надо проверять убирается ли оно на строке. if (true !== FirstItemOnLine /*|| false === Para.Internal_Check_Ranges(ParaLine, ParaRange)*/) { if (X + SpaceLen + LetterLen > XEnd) { NewRange = true; RangeEndPos = Pos; } else if(BreakBox == true) { MoveToLBP = true; NewRange = true; PRS.Set_LineBreakPos(Pos); } } if(true !== NewRange) { if(this.Parent.bRoot == true) PRS.Set_LineBreakPos(Pos); WordLen += LetterLen; Word = true; } } else { if(X + SpaceLen + WordLen + LetterLen > XEnd) { if(true === FirstItemOnLine /*&& true === Para.Internal_Check_Ranges(ParaLine, ParaRange)*/) { // Слово оказалось единственным элементом в промежутке, и, все равно, не умещается целиком. // для Формулы слово не разбиваем, перенос не делаем, пишем в одну строку (слово выйдет за границу как в Ворде) bMathWordLarge = true; } else { // Слово не убирается в отрезке. Переносим слово в следующий отрезок MoveToLBP = true; NewRange = true; } } if (true !== NewRange) { // Мы убираемся в пределах данной строки. Прибавляем ширину буквы к ширине слова WordLen += LetterLen; } } break; } case para_Space: { FirstItemOnLine = false; if (true === Word) { // Добавляем длину пробелов до слова + длина самого слова. Не надо проверять // убирается ли слово, мы это проверяем при добавленнии букв. X += SpaceLen + WordLen; Word = false; EmptyLine = false; SpaceLen = 0; WordLen = 0; } // На пробеле не делаем перенос. Перенос строки или внутристрочный // перенос делаем при добавлении любого непробельного символа SpaceLen += Item.Width / TEXTWIDTH_DIVIDER;//SpaceLen += Item.Get_Width(); break; } case para_Math_BreakOperator: { var BrkLen = Item.Get_Width2()/TEXTWIDTH_DIVIDER; var bCompareOper = Item.Is_CompareOperator(); var bOperBefore = this.ParaMath.Is_BrkBinBefore() == true; var bOperInEndContent = bOperBefore === false && bEndRunToContent === true && Pos == ContentLen - 1 && Word == true, // необходимо для того, чтобы у контентов мат объектов (к-ые могут разбиваться на строки) не было отметки Set_LineBreakPos, иначе скобка (или GapLeft), перед которой стоит break_Operator, перенесется на следующую строку (без текста !) bLowPriority = bCompareOper == false && bContainCompareOper == false; if(Pos == 0 && true === this.MathPrp.IsBreak()) // принудительный перенос { if(FirstItemOnLine === true) { WordLen += BrkLen; } else { if(bOperBefore) { X += SpaceLen + WordLen; NewRange = true; RangeEndPos = Pos; } else { Word = false; BreakBox = true; } } } else if(bOperInEndContent || bLowPriority) // у этого break Operator приоритет низкий(находится во вложенном контенте) => по нему не разбиваем, обрабатываем как обычную букву { if(X + SpaceLen + WordLen + BrkLen > XEnd) { if(FirstItemOnLine == true) { bMathWordLarge = true; } else { // Слово не убирается в отрезке. Переносим слово в следующий отрезок MoveToLBP = true; NewRange = true; } } else { WordLen += BrkLen; } } else { var WorLenCompareOper = WordLen + X - XRange + (bOperBefore ? SpaceLen : BrkLen); var bOverXEnd; var bNotUpdBreakOper = false; var bCompareWrapIndent = PRS.bFirstLine == true ? WorLenCompareOper > PRS.WrapIndent : true; if(PRS.bPriorityOper == true && bCompareOper == true && bContainCompareOper == true && bCompareWrapIndent == true && !(Word == false && FirstItemOnLine === true)) // (Word == true && FirstItemOnLine == true) - не первый элемент в строке bContainCompareOper = false; if(bOperBefore) // оператор "до" => оператор находится в начале строки { bOverXEnd = X + WordLen + SpaceLen + BrkLen > XEnd; // BrkLen прибавляем дла случая, если идут подряд Brk Operators в конце if(bOverXEnd) { // если вышли за границы не обновляем параметр bInsideOper, т.к. если уже были breakOperator, то, соответственно, он уже выставлен в true // а если на этом уровне не было breakOperator, то и обновлять его нне нужо if(FirstItemOnLine === false) { MoveToLBP = true; NewRange = true; } else { if(Word == true) { bMathWordLarge = true; } X += SpaceLen + WordLen; if(PRS.bBreakPosInLWord == true) { PRS.Set_LineBreakPos(Pos); } else { bNotUpdBreakOper = true; } RangeEndPos = Pos; SpaceLen = 0; WordLen = 0; NewRange = true; EmptyLine = false; } } else { if(FirstItemOnLine === false) bInsideOper = true; if(Word == false && FirstItemOnLine == true ) { SpaceLen += BrkLen; } else { // проверка на FirstItemOnLine == false нужна для случая, если иду подряд несколько breakOperator // в этом случае Word == false && FirstItemOnLine == false, нужно также поставить отметку для потенциального переноса X += SpaceLen + WordLen; PRS.Set_LineBreakPos(Pos); EmptyLine = false; WordLen = BrkLen; SpaceLen = 0; } // в первой строке может не быть ни одного break Operator, при этом слово не выходит за границы, т.о. обновляем FirstItemOnLine также и на Word = true // т.к. оператор идет в начале строки, то соответственно слово в стоке не будет первым, если в строке больше одного оператора if(bNoOneBreakOperator == false || Word == true) FirstItemOnLine = false; } } else // оператор "после" => оператор находится в конце строки { bOverXEnd = X + WordLen + BrkLen - Item.GapRight > XEnd; if(bOverXEnd && FirstItemOnLine === false) // Слово не убирается в отрезке. Переносим слово в следующий отрезок { MoveToLBP = true; NewRange = true; if(Word == false) PRS.Set_LineBreakPos(Pos); } else { bInsideOper = true; // осуществляем здесь, чтобы не изменить GapRight в случае, когда новое слово не убирается на break_Operator OperGapRight = Item.GapRight; if(bOverXEnd) // FirstItemOnLine == true { bMathWordLarge = true; } X += BrkLen + WordLen; EmptyLine = false; SpaceLen = 0; WordLen = 0; var bNotUpdate = bOverXEnd == true && PRS.bBreakPosInLWord == false; // FirstItemOnLine == true if(bNotUpdate == false) // LineBreakPos обновляем здесь, т.к. слово может начаться с мат объекта, а не с Run, в мат объекте нет соответствующей проверки { PRS.Set_LineBreakPos(Pos+1); } else { bNotUpdBreakOper = true; } FirstItemOnLine = false; Word = false; } } } if(bNotUpdBreakOper == false) bNoOneBreakOperator = false; break; } case para_Drawing: { if(oSectionPr === undefined) { oSectionPr = Para.Get_SectPr(); } Item.CheckRecalcAutoFit(oSectionPr); if (true === Item.Is_Inline() || true === Para.Parent.Is_DrawingShape()) { if (true !== Item.Is_Inline()) Item.Set_DrawingType(drawing_Inline); if (true === StartWord) FirstItemOnLine = false; Item.YOffset = this.YOffset; // Если до этого было слово, тогда не надо проверять убирается ли оно, но если стояли пробелы, // тогда мы их учитываем при проверке убирается ли данный элемент, и добавляем только если // данный элемент убирается if (true === Word || WordLen > 0) { // Добавляем длину пробелов до слова + длина самого слова. Не надо проверять // убирается ли слово, мы это проверяем при добавленнии букв. X += SpaceLen + WordLen; Word = false; EmptyLine = false; SpaceLen = 0; WordLen = 0; } var DrawingWidth = Item.Get_Width(); if (X + SpaceLen + DrawingWidth > XEnd && ( false === FirstItemOnLine || false === Para.Internal_Check_Ranges(ParaLine, ParaRange) )) { // Автофигура не убирается, ставим перенос перед ней NewRange = true; RangeEndPos = Pos; } else { // Добавляем длину пробелов до автофигуры X += SpaceLen + DrawingWidth; FirstItemOnLine = false; EmptyLine = false; } SpaceLen = 0; } else { // Основная обработка происходит в Recalculate_Range_Spaces. Здесь обрабатывается единственный случай, // когда после второго пересчета с уже добавленной картинкой оказывается, что место в параграфе, где // идет картинка ушло на следующую страницу. В этом случае мы ставим перенос страницы перед картинкой. var LogicDocument = Para.Parent; var LDRecalcInfo = LogicDocument.RecalcInfo; var DrawingObjects = LogicDocument.DrawingObjects; var CurPage = PRS.Page; if (true === LDRecalcInfo.Check_FlowObject(Item) && true === LDRecalcInfo.Is_PageBreakBefore()) { LDRecalcInfo.Reset(); // Добавляем разрыв страницы. Если это первая страница, тогда ставим разрыв страницы в начале параграфа, // если нет, тогда в начале текущей строки. if (null != Para.Get_DocumentPrev() && true != Para.Parent.Is_TableCellContent() && 0 === CurPage) { Para.Recalculate_Drawing_AddPageBreak(0, 0, true); PRS.RecalcResult = recalcresult_NextPage; PRS.NewRange = true; return; } else { if (ParaLine != Para.Pages[CurPage].FirstLine) { Para.Recalculate_Drawing_AddPageBreak(ParaLine, CurPage, false); PRS.RecalcResult = recalcresult_NextPage; PRS.NewRange = true; return; } else { RangeEndPos = Pos; NewRange = true; ForceNewPage = true; } } // Если до этого было слово, тогда не надо проверять убирается ли оно if (true === Word || WordLen > 0) { // Добавляем длину пробелов до слова + длина самого слова. Не надо проверять // убирается ли слово, мы это проверяем при добавленнии букв. X += SpaceLen + WordLen; Word = false; SpaceLen = 0; WordLen = 0; } } } break; } case para_PageNum: { // Выставляем номер страницы var LogicDocument = Para.LogicDocument; var SectionPage = LogicDocument.Get_SectionPageNumInfo2(PRS.Page + Para.Get_StartPage_Absolute()).CurPage; Item.Set_Page(SectionPage); // Если до этого было слово, тогда не надо проверять убирается ли оно, но если стояли пробелы, // тогда мы их учитываем при проверке убирается ли данный элемент, и добавляем только если // данный элемент убирается if (true === Word || WordLen > 0) { // Добавляем длину пробелов до слова + длина самого слова. Не надо проверять // убирается ли слово, мы это проверяем при добавленнии букв. X += SpaceLen + WordLen; Word = false; EmptyLine = false; SpaceLen = 0; WordLen = 0; } // Если на строке начиналось какое-то слово, тогда данная строка уже не пустая if (true === StartWord) FirstItemOnLine = false; var PageNumWidth = Item.Get_Width(); if (X + SpaceLen + PageNumWidth > XEnd && ( false === FirstItemOnLine || false === Para.Internal_Check_Ranges(ParaLine, ParaRange) )) { // Данный элемент не убирается, ставим перенос перед ним NewRange = true; RangeEndPos = Pos; } else { // Добавляем длину пробелов до слова и ширину данного элемента X += SpaceLen + PageNumWidth; FirstItemOnLine = false; EmptyLine = false; } SpaceLen = 0; break; } case para_Tab: { // Сначала проверяем, если у нас уже есть таб, которым мы должны рассчитать, тогда высчитываем // его ширину. X = this.Internal_Recalculate_LastTab(PRS.LastTab, X, XEnd, Word, WordLen, SpaceLen); // Добавляем длину пробелов до слова + длина самого слова. Не надо проверять // убирается ли слово, мы это проверяем при добавленнии букв. X += SpaceLen + WordLen; Word = false; SpaceLen = 0; WordLen = 0; var TabPos = Para.Internal_GetTabPos(X, ParaPr, PRS.Page); var NewX = TabPos.NewX; var TabValue = TabPos.TabValue; // Если таб не левый, значит он не может быть сразу рассчитан, а если левый, тогда // рассчитываем его сразу здесь if (tab_Left !== TabValue) { PRS.LastTab.TabPos = NewX; PRS.LastTab.Value = TabValue; PRS.LastTab.X = X; PRS.LastTab.Item = Item; Item.Width = 0; Item.WidthVisible = 0; } else { if (NewX > XEnd && ( false === FirstItemOnLine || false === Para.Internal_Check_Ranges(ParaLine, ParaRange) )) { WordLen = NewX - X; RangeEndPos = Pos; NewRange = true; } else { Item.Width = NewX - X; Item.WidthVisible = NewX - X; X = NewX; } } // Если перенос идет по строке, а не из-за обтекания, тогда разрываем перед табом, а если // из-за обтекания, тогда разрываем перед последним словом, идущим перед табом if (RangesCount === CurRange) { if (true === StartWord) { FirstItemOnLine = false; EmptyLine = false; } } // Считаем, что с таба начинается слово PRS.Set_LineBreakPos(Pos); StartWord = true; Word = true; break; } case para_NewLine: { // Сначала проверяем, если у нас уже есть таб, которым мы должны рассчитать, тогда высчитываем // его ширину. X = this.Internal_Recalculate_LastTab(PRS.LastTab, X, XEnd, Word, WordLen, SpaceLen); X += WordLen; if (true === Word) { EmptyLine = false; Word = false; X += SpaceLen; SpaceLen = 0; } if (break_Page === Item.BreakType) { if (true === PRS.SkipPageBreak && Item === PRS.PageBreak) continue; Item.Flags.NewLine = true; // PageBreak вне самого верхнего документа не надо учитывать if (!(Para.Parent instanceof CDocument) || true !== Para.Is_Inline()) { // TODO: Продумать, как избавиться от данного элемента, т.к. удалять его при пересчете нельзя, // иначе будут проблемы с совместным редактированием. Item.Flags.Use = false; continue; } NewPage = true; NewRange = true; BreakPageLine = true; PRS.PageBreak = Item; } else { NewRange = true; EmptyLine = false; // здесь оставляем проверку, т.к. в случае, если после неинлайновой формулы нах-ся инлайновая необходимо в любом случае сделать перенос (проверка в private_RecalculateRange(), где выставляется PRS.ForceNewLine = true не пройдет) if (true === PRS.MathNotInline) PRS.ForceNewLine = true; } RangeEndPos = Pos + 1; break; } case para_End: { if (true === Word) { FirstItemOnLine = false; EmptyLine = false; } // false === PRS.ExtendBoundToBottom, потому что это уже делалось для PageBreak if (false === PRS.ExtendBoundToBottom) { X += WordLen; if (true === Word) { X += SpaceLen; SpaceLen = 0; WordLen = 0; } X = this.Internal_Recalculate_LastTab(PRS.LastTab, X, XEnd, Word, WordLen, SpaceLen); } NewRange = true; End = true; RangeEndPos = Pos + 1; break; } } if (true === NewRange) break; } } PRS.MoveToLBP = MoveToLBP; PRS.NewRange = NewRange; PRS.ForceNewPage = ForceNewPage; PRS.NewPage = NewPage; PRS.BreakPageLine = BreakPageLine; PRS.End = End; PRS.Word = Word; PRS.StartWord = StartWord; PRS.FirstItemOnLine = FirstItemOnLine; PRS.EmptyLine = EmptyLine; PRS.SpaceLen = SpaceLen; PRS.WordLen = WordLen; PRS.bMathWordLarge = bMathWordLarge; PRS.OperGapRight = OperGapRight; PRS.OperGapLeft = OperGapLeft; PRS.X = X; PRS.XEnd = XEnd; PRS.bInsideOper = bInsideOper; PRS.bContainCompareOper = bContainCompareOper; PRS.bEndRunToContent = bEndRunToContent; PRS.bNoOneBreakOperator = bNoOneBreakOperator; PRS.BreakBox = BreakBox; if(this.Type == para_Math_Run) { if(true === NewRange) { var WidthLine = X - XRange; if(this.ParaMath.Is_BrkBinBefore() == false) WidthLine += SpaceLen; this.ParaMath.UpdateWidthLine(PRS, WidthLine); } else { // для пустого Run, обновляем LineBreakPos на случай, если пустой Run находится между break_operator (мат. объект) и мат объектом if(this.Content.length == 0 && this.ParaMath.Is_BrkBinBefore() == false && Word == false && PRS.bBoxOperator == true) { PRS.Set_LineBreakPos(Pos); PRS.X += SpaceLen; PRS.SpaceLen = 0; } // запоминаем конец Run PRS.PosEndRun.Set(PRS.CurPos); PRS.PosEndRun.Update2(this.Content.length, Depth); } } if ( Pos >= ContentLen ) { RangeEndPos = Pos; } this.protected_FillRange(CurLine, CurRange, RangeStartPos, RangeEndPos); this.RecalcInfo.Recalc = false; }; ParaRun.prototype.Recalculate_Set_RangeEndPos = function(PRS, PRP, Depth) { var CurLine = PRS.Line - this.StartLine; var CurRange = ( 0 === CurLine ? PRS.Range - this.StartRange : PRS.Range ); var CurPos = PRP.Get(Depth); this.protected_FillRangeEndPos(CurLine, CurRange, CurPos); }; ParaRun.prototype.Recalculate_LineMetrics = function(PRS, ParaPr, _CurLine, _CurRange, ContentMetrics) { var Para = PRS.Paragraph; // Если заданный отрезок пустой, тогда мы не должны учитывать метрики данного рана. var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var UpdateLineMetricsText = false; var LineRule = ParaPr.Spacing.LineRule; for (var CurPos = StartPos; CurPos < EndPos; CurPos++) { var Item = this.Content[CurPos]; if (Item === Para.Numbering.Item) { PRS.LineAscent = Para.Numbering.LineAscent; } switch (Item.Type) { case para_Sym: case para_Text: case para_PageNum: { UpdateLineMetricsText = true; break; } case para_Math_Text: case para_Math_Ampersand: case para_Math_Placeholder: case para_Math_BreakOperator: { ContentMetrics.UpdateMetrics(Item.size); UpdateLineMetricsText = true; break; } case para_Space: { break; } case para_Drawing: { if (true === Item.Is_Inline() || true === Para.Parent.Is_DrawingShape()) { // Обновим метрики строки if (linerule_Exact === LineRule) { if (PRS.LineAscent < Item.Height) PRS.LineAscent = Item.Height; } else { if (PRS.LineAscent < Item.Height + this.YOffset) PRS.LineAscent = Item.Height + this.YOffset; if (PRS.LineDescent < -this.YOffset) PRS.LineDescent = -this.YOffset; } } break; } case para_End: { // TODO: Тут можно сделать проверку на пустую строку. break; } } } if ( true === UpdateLineMetricsText) { // Пересчитаем метрику строки относительно размера данного текста if ( PRS.LineTextAscent < this.TextAscent ) PRS.LineTextAscent = this.TextAscent; if ( PRS.LineTextAscent2 < this.TextAscent2 ) PRS.LineTextAscent2 = this.TextAscent2; if ( PRS.LineTextDescent < this.TextDescent ) PRS.LineTextDescent = this.TextDescent; if ( linerule_Exact === LineRule ) { // Смещение не учитывается в метриках строки, когда расстояние между строк точное if ( PRS.LineAscent < this.TextAscent ) PRS.LineAscent = this.TextAscent; if ( PRS.LineDescent < this.TextDescent ) PRS.LineDescent = this.TextDescent; } else { if ( PRS.LineAscent < this.TextAscent + this.YOffset ) PRS.LineAscent = this.TextAscent + this.YOffset; if ( PRS.LineDescent < this.TextDescent - this.YOffset ) PRS.LineDescent = this.TextDescent - this.YOffset; } } }; ParaRun.prototype.Recalculate_Range_Width = function(PRSC, _CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; switch( ItemType ) { case para_Sym: case para_Text: { PRSC.Letters++; if ( true !== PRSC.Word ) { PRSC.Word = true; PRSC.Words++; } PRSC.Range.W += Item.Width / TEXTWIDTH_DIVIDER;//Item.Get_Width(); PRSC.Range.W += PRSC.SpaceLen; PRSC.SpaceLen = 0; // Пробелы перед первым словом в строке не считаем if (PRSC.Words > 1) PRSC.Spaces += PRSC.SpacesCount; else PRSC.SpacesSkip += PRSC.SpacesCount; PRSC.SpacesCount = 0; // Если текущий символ, например, дефис, тогда на нем заканчивается слово if (Item.Flags & PARATEXT_FLAGS_SPACEAFTER)//if ( true === Item.Is_SpaceAfter() ) PRSC.Word = false; break; } case para_Math_Text: case para_Math_Placeholder: case para_Math_Ampersand: case para_Math_BreakOperator: { PRSC.Letters++; PRSC.Range.W += Item.Get_Width() / TEXTWIDTH_DIVIDER; // Get_Width рассчитываем ширину с учетом состояний Gaps break; } case para_Space: { if ( true === PRSC.Word ) { PRSC.Word = false; PRSC.SpacesCount = 1; PRSC.SpaceLen = Item.Width / TEXTWIDTH_DIVIDER;//Item.Get_Width(); } else { PRSC.SpacesCount++; PRSC.SpaceLen += Item.Width / TEXTWIDTH_DIVIDER;//Item.Get_Width(); } break; } case para_Drawing: { PRSC.Words++; PRSC.Range.W += PRSC.SpaceLen; if (PRSC.Words > 1) PRSC.Spaces += PRSC.SpacesCount; else PRSC.SpacesSkip += PRSC.SpacesCount; PRSC.Word = false; PRSC.SpacesCount = 0; PRSC.SpaceLen = 0; if ( true === Item.Is_Inline() || true === PRSC.Paragraph.Parent.Is_DrawingShape() ) PRSC.Range.W += Item.Get_Width(); break; } case para_PageNum: { PRSC.Words++; PRSC.Range.W += PRSC.SpaceLen; if (PRSC.Words > 1) PRSC.Spaces += PRSC.SpacesCount; else PRSC.SpacesSkip += PRSC.SpacesCount; PRSC.Word = false; PRSC.SpacesCount = 0; PRSC.SpaceLen = 0; PRSC.Range.W += Item.Get_Width(); break; } case para_Tab: { PRSC.Range.W += Item.Get_Width(); PRSC.Range.W += PRSC.SpaceLen; // Учитываем только слова и пробелы, идущие после последнего таба PRSC.LettersSkip += PRSC.Letters; PRSC.SpacesSkip += PRSC.Spaces; PRSC.Words = 0; PRSC.Spaces = 0; PRSC.Letters = 0; PRSC.SpaceLen = 0; PRSC.SpacesCount = 0; PRSC.Word = false; break; } case para_NewLine: { if (true === PRSC.Word && PRSC.Words > 1) PRSC.Spaces += PRSC.SpacesCount; PRSC.SpacesCount = 0; PRSC.Word = false; break; } case para_End: { if ( true === PRSC.Word ) PRSC.Spaces += PRSC.SpacesCount; break; } } } }; ParaRun.prototype.Recalculate_Range_Spaces = function(PRSA, _CurLine, _CurRange, CurPage) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; switch( ItemType ) { case para_Sym: case para_Text: { var WidthVisible = 0; if ( 0 !== PRSA.LettersSkip ) { WidthVisible = Item.Width / TEXTWIDTH_DIVIDER;//WidthVisible = Item.Get_Width(); PRSA.LettersSkip--; } else WidthVisible = Item.Width / TEXTWIDTH_DIVIDER + PRSA.JustifyWord;//WidthVisible = Item.Get_Width() + PRSA.JustifyWord; Item.WidthVisible = (WidthVisible * TEXTWIDTH_DIVIDER) | 0;//Item.Set_WidthVisible(WidthVisible); PRSA.X += WidthVisible; PRSA.LastW = WidthVisible; break; } case para_Math_Text: case para_Math_Placeholder: case para_Math_BreakOperator: case para_Math_Ampersand: { var WidthVisible = Item.Get_Width() / TEXTWIDTH_DIVIDER; // Get_Width рассчитываем ширину с учетом состояний Gaps Item.WidthVisible = (WidthVisible * TEXTWIDTH_DIVIDER)| 0;//Item.Set_WidthVisible(WidthVisible); PRSA.X += WidthVisible; PRSA.LastW = WidthVisible; break; } case para_Space: { var WidthVisible = Item.Width / TEXTWIDTH_DIVIDER;//WidthVisible = Item.Get_Width(); if ( 0 !== PRSA.SpacesSkip ) { PRSA.SpacesSkip--; } else if ( 0 !== PRSA.SpacesCounter ) { WidthVisible += PRSA.JustifySpace; PRSA.SpacesCounter--; } Item.WidthVisible = (WidthVisible * TEXTWIDTH_DIVIDER) | 0;//Item.Set_WidthVisible(WidthVisible); PRSA.X += WidthVisible; PRSA.LastW = WidthVisible; break; } case para_Drawing: { var Para = PRSA.Paragraph; var LogicDocument = this.Paragraph.LogicDocument; var LD_PageLimits = LogicDocument.Get_PageLimits( CurPage ); var LD_PageFields = LogicDocument.Get_PageFields( CurPage ); var Page_Width = LD_PageLimits.XLimit; var Page_Height = LD_PageLimits.YLimit; var X_Left_Field = LD_PageFields.X; var Y_Top_Field = LD_PageFields.Y; var X_Right_Field = LD_PageFields.XLimit; var Y_Bottom_Field = LD_PageFields.YLimit; var X_Left_Margin = X_Left_Field; var X_Right_Margin = Page_Width - X_Right_Field; var Y_Bottom_Margin = Page_Height - Y_Bottom_Field; var Y_Top_Margin = Y_Top_Field; var DrawingObjects = Para.Parent.DrawingObjects; var PageLimits = Para.Parent.Get_PageLimits(Para.PageNum + CurPage); var PageFields = Para.Parent.Get_PageFields(Para.PageNum + CurPage); var ColumnStartX = (0 === CurPage ? Para.X_ColumnStart : Para.Pages[CurPage].X ); var ColumnEndX = (0 === CurPage ? Para.X_ColumnEnd : Para.Pages[CurPage].XLimit); var Top_Margin = Y_Top_Margin; var Bottom_Margin = Y_Bottom_Margin; var Page_H = Page_Height; if ( true === Para.Parent.Is_TableCellContent() && true == Item.Use_TextWrap() ) { Top_Margin = 0; Bottom_Margin = 0; Page_H = 0; } if ( true != Item.Use_TextWrap() ) { PageFields.X = X_Left_Field; PageFields.Y = Y_Top_Field; PageFields.XLimit = X_Right_Field; PageFields.YLimit = Y_Bottom_Field; PageLimits.X = 0; PageLimits.Y = 0; PageLimits.XLimit = Page_Width; PageLimits.YLimit = Page_Height; } var PageLimitsOrigin = Para.Parent.Get_PageLimits(Para.PageNum + CurPage); if ( true === Item.Is_Inline() || true === Para.Parent.Is_DrawingShape() ) { Item.Update_Position(PRSA.Paragraph, new CParagraphLayout( PRSA.X, PRSA.Y , Para.Get_StartPage_Absolute() + CurPage, PRSA.LastW, ColumnStartX, ColumnEndX, X_Left_Margin, X_Right_Margin, Page_Width, Top_Margin, Bottom_Margin, Page_H, PageFields.X, PageFields.Y, Para.Pages[CurPage].Y + Para.Lines[CurLine].Y - Para.Lines[CurLine].Metrics.Ascent, Para.Pages[CurPage].Y), PageLimits, PageLimitsOrigin, _CurLine); Item.Reset_SavedPosition(); PRSA.X += Item.WidthVisible; PRSA.LastW = Item.WidthVisible; } else { Para.Pages[CurPage].Add_Drawing(Item); if ( true === PRSA.RecalcFast ) { // Если у нас быстрый пересчет, тогда мы не трогаем плавающие картинки // TODO: Если здесь привязка к символу, тогда быстрый пересчет надо отменить break; } if (true === PRSA.RecalcFast2) { // Тут мы должны сравнить положение картинок var oRecalcObj = Item.Save_RecalculateObject(); var Page_abs = Para.Get_StartPage_Absolute() + CurPage; Item.Update_Position(PRSA.Paragraph, new CParagraphLayout( PRSA.X, PRSA.Y , Page_abs, PRSA.LastW, ColumnStartX, ColumnEndX, X_Left_Margin, X_Right_Margin, Page_Width, Top_Margin, Bottom_Margin, Page_H, PageFields.X, PageFields.Y, Para.Pages[CurPage].Y + Para.Lines[CurLine].Y - Para.Lines[CurLine].Metrics.Ascent, Para.Pages[CurPage].Y), PageLimits, PageLimitsOrigin, _CurLine); if (Math.abs(Item.X - oRecalcObj.X) > 0.001 || Math.abs(Item.Y - oRecalcObj.Y) > 0.001 || Item.PageNum !== oRecalcObj.PageNum) { // Положение картинок не совпало, отправляем пересчет текущей страницы. PRSA.RecalcResult = recalcresult_CurPage; return; } break; } // У нас Flow-объект. Если он с обтеканием, тогда мы останавливаем пересчет и // запоминаем текущий объект. В функции Internal_Recalculate_2 пересчитываем // его позицию и сообщаем ее внешнему классу. if ( true === Item.Use_TextWrap() ) { var LogicDocument = Para.Parent; var LDRecalcInfo = Para.Parent.RecalcInfo; var Page_abs = Para.Get_StartPage_Absolute() + CurPage; if ( true === LDRecalcInfo.Can_RecalcObject() ) { // Обновляем позицию объекта Item.Update_Position(PRSA.Paragraph, new CParagraphLayout( PRSA.X, PRSA.Y , Page_abs, PRSA.LastW, ColumnStartX, ColumnEndX, X_Left_Margin, X_Right_Margin, Page_Width, Top_Margin, Bottom_Margin, Page_H, PageFields.X, PageFields.Y, Para.Pages[CurPage].Y + Para.Lines[CurLine].Y - Para.Lines[CurLine].Metrics.Ascent, Para.Pages[CurPage].Y), PageLimits, PageLimitsOrigin, _CurLine); LDRecalcInfo.Set_FlowObject( Item, 0, recalcresult_NextElement, -1 ); if (0 === PRSA.CurPage && Item.wrappingPolygon.top > PRSA.PageY + 0.001) PRSA.RecalcResult = recalcresult_CurPagePara; else PRSA.RecalcResult = recalcresult_CurPage; return; } else if ( true === LDRecalcInfo.Check_FlowObject(Item) ) { // Если мы находимся с таблице, тогда делаем как Word, не пересчитываем предыдущую страницу, // даже если это необходимо. Такое поведение нужно для точного определения рассчиталась ли // данная страница окончательно или нет. Если у нас будет ветка с переходом на предыдущую страницу, // тогда не рассчитав следующую страницу мы о конечном рассчете текущей страницы не узнаем. // Если данный объект нашли, значит он уже был рассчитан и нам надо проверить номер страницы if ( Item.PageNum === Page_abs ) { // Все нормально, можно продолжить пересчет LDRecalcInfo.Reset(); Item.Reset_SavedPosition(); } else if ( true === Para.Parent.Is_TableCellContent() ) { // Картинка не на нужной странице, но так как это таблица // мы пересчитываем заново текущую страницу, а не предыдущую // Обновляем позицию объекта Item.Update_Position(PRSA.Paragraph, new CParagraphLayout( PRSA.X, PRSA.Y, Page_abs, PRSA.LastW, ColumnStartX, ColumnEndX, X_Left_Margin, X_Right_Margin, Page_Width, Top_Margin, Bottom_Margin, Page_H, PageFields.X, PageFields.Y, Para.Pages[CurPage].Y + Para.Lines[CurLine].Y - Para.Lines[CurLine].Metrics.Ascent, Para.Pages[CurPage].Y), PageLimits, PageLimitsOrigin, _CurLine); LDRecalcInfo.Set_FlowObject( Item, 0, recalcresult_NextElement, -1 ); LDRecalcInfo.Set_PageBreakBefore( false ); PRSA.RecalcResult = recalcresult_CurPage; return; } else { LDRecalcInfo.Set_PageBreakBefore( true ); DrawingObjects.removeById( Item.PageNum, Item.Get_Id() ); PRSA.RecalcResult = recalcresult_PrevPage; return; } } else { // Либо данный элемент уже обработан, либо будет обработан в будущем } continue; } else { // Картинка ложится на или под текст, в данном случае пересчет можно спокойно продолжать // Здесь под верхом параграфа понимаем верх первой строки, а не значение, с которого начинается пересчет. var ParagraphTop = Para.Lines[Para.Pages[CurPage].StartLine].Top + Para.Pages[CurPage].Y; Item.Update_Position(PRSA.Paragraph, new CParagraphLayout( PRSA.X, PRSA.Y , Para.Get_StartPage_Absolute() + CurPage, PRSA.LastW, ColumnStartX, ColumnEndX, X_Left_Margin, X_Right_Margin, Page_Width, Top_Margin, Bottom_Margin, Page_H, PageFields.X, PageFields.Y, Para.Pages[CurPage].Y + Para.Lines[CurLine].Y - Para.Lines[CurLine].Metrics.Ascent, ParagraphTop), PageLimits, PageLimitsOrigin, _CurLine); Item.Reset_SavedPosition(); } } break; } case para_PageNum: { PRSA.X += Item.WidthVisible; PRSA.LastW = Item.WidthVisible; break; } case para_Tab: { PRSA.X += Item.WidthVisible; break; } case para_End: { var SectPr = PRSA.Paragraph.Get_SectionPr(); if (!PRSA.Paragraph.LogicDocument || PRSA.Paragraph.LogicDocument !== PRSA.Paragraph.Parent) SectPr = undefined; if ( undefined !== SectPr ) { // Нас интересует следующая секция var LogicDocument = PRSA.Paragraph.LogicDocument; var NextSectPr = LogicDocument.SectionsInfo.Get_SectPr(PRSA.Paragraph.Index + 1).SectPr; Item.Update_SectionPr(NextSectPr, PRSA.XEnd - PRSA.X); } else Item.Clear_SectionPr(); PRSA.X += Item.Get_Width(); break; } case para_NewLine: { if ( break_Page === Item.BreakType ) Item.Update_String( PRSA.XEnd - PRSA.X ); PRSA.X += Item.WidthVisible; break; } } } }; ParaRun.prototype.Recalculate_PageEndInfo = function(PRSI, _CurLine, _CurRange) { }; ParaRun.prototype.private_RecalculateNumbering = function(PRS, Item, ParaPr, _X) { var X = PRS.Recalculate_Numbering(Item, this, ParaPr, _X); // Запоминаем, что на данном элементе была добавлена нумерация this.RecalcInfo.NumberingAdd = false; this.RecalcInfo.NumberingUse = true; this.RecalcInfo.NumberingItem = PRS.Paragraph.Numbering; return X; }; ParaRun.prototype.Internal_Recalculate_LastTab = function(LastTab, X, XEnd, Word, WordLen, SpaceLen) { if ( -1 !== LastTab.Value ) { var TempXPos = X; if ( true === Word || WordLen > 0 ) TempXPos += SpaceLen + WordLen; var TabItem = LastTab.Item; var TabStartX = LastTab.X; var TabRangeW = TempXPos - TabStartX; var TabValue = LastTab.Value; var TabPos = LastTab.TabPos; var TabCalcW = 0; if ( tab_Right === TabValue ) TabCalcW = Math.max( TabPos - (TabStartX + TabRangeW), 0 ); else if ( tab_Center === TabValue ) TabCalcW = Math.max( TabPos - (TabStartX + TabRangeW / 2), 0 ); if ( X + TabCalcW > XEnd ) TabCalcW = XEnd - X; TabItem.Width = TabCalcW; TabItem.WidthVisible = TabCalcW; LastTab.Reset(); return X + TabCalcW; } return X; }; ParaRun.prototype.Refresh_RecalcData = function(Data) { var Para = this.Paragraph; if(this.Type == para_Math_Run) { if(this.Parent !== null && this.Parent !== undefined) { this.Parent.Refresh_RecalcData(); } } else if ( -1 !== this.StartLine && undefined !== Para ) { var CurLine = this.StartLine; var PagesCount = Para.Pages.length; for (var CurPage = 0 ; CurPage < PagesCount; CurPage++ ) { var Page = Para.Pages[CurPage]; if ( Page.StartLine <= CurLine && Page.EndLine >= CurLine ) { Para.Refresh_RecalcData2(CurPage); return; } } Para.Refresh_RecalcData2(0); } }; ParaRun.prototype.Save_RecalculateObject = function(Copy) { var RecalcObj = new CRunRecalculateObject(this.StartLine, this.StartRange); RecalcObj.Save_Lines( this, Copy ); RecalcObj.Save_RunContent( this, Copy ); return RecalcObj; }; ParaRun.prototype.Load_RecalculateObject = function(RecalcObj) { RecalcObj.Load_Lines(this); RecalcObj.Load_RunContent(this); }; ParaRun.prototype.Prepare_RecalculateObject = function() { this.protected_ClearLines(); var Count = this.Content.length; for ( var Index = 0; Index < Count; Index++ ) { var Item = this.Content[Index]; var ItemType = Item.Type; if ( para_PageNum === ItemType || para_Drawing === ItemType ) Item.Prepare_RecalculateObject(); } }; ParaRun.prototype.Is_EmptyRange = function(_CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); if ( EndPos <= StartPos ) return true; return false; }; ParaRun.prototype.Check_Range_OnlyMath = function(Checker, _CurRange, _CurLine) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); for (var Pos = StartPos; Pos < EndPos; Pos++) { var Item = this.Content[Pos]; var ItemType = Item.Type; if (para_End === ItemType || para_NewLine === ItemType || (para_Drawing === ItemType && true !== Item.Is_Inline())) continue; else { Checker.Result = false; Checker.Math = null; break; } } }; ParaRun.prototype.Check_MathPara = function(Checker) { var Count = this.Content.length; if ( Count <= 0 ) return; var Item = ( Checker.Direction > 0 ? this.Content[0] : this.Content[Count - 1] ); var ItemType = Item.Type; if ( para_End === ItemType || para_NewLine === ItemType ) { Checker.Result = true; Checker.Found = true; } else { Checker.Result = false; Checker.Found = true; } }; ParaRun.prototype.Check_PageBreak = function() { var Count = this.Content.length; for (var Pos = 0; Pos < Count; Pos++) { var Item = this.Content[Pos]; if (para_NewLine === Item.Type && break_Page === Item.BreakType) return true; } return false; }; ParaRun.prototype.Check_BreakPageEnd = function(PBChecker) { var ContentLen = this.Content.length; for ( var CurPos = 0; CurPos < ContentLen; CurPos++ ) { var Item = this.Content[CurPos]; if ( true === PBChecker.FindPB ) { if ( Item === PBChecker.PageBreak ) { PBChecker.FindPB = false; PBChecker.PageBreak.Flags.NewLine = true; } } else { var ItemType = Item.Type; if ( para_End === ItemType ) return true; else if ( para_Drawing !== ItemType || drawing_Anchor !== Item.Get_DrawingType() ) return false; } } return true; }; ParaRun.prototype.Recalculate_MinMaxContentWidth = function(MinMax) { this.Recalculate_MeasureContent(); var bWord = MinMax.bWord; var nWordLen = MinMax.nWordLen; var nSpaceLen = MinMax.nSpaceLen; var nMinWidth = MinMax.nMinWidth; var nMaxWidth = MinMax.nMaxWidth; var nCurMaxWidth = MinMax.nCurMaxWidth; var Count = this.Content.length; for ( var Pos = 0; Pos < Count; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; switch( ItemType ) { case para_Text: { var ItemWidth = Item.Width / TEXTWIDTH_DIVIDER;//var ItemWidth = Item.Get_Width(); if ( false === bWord ) { bWord = true; nWordLen = ItemWidth; } else { nWordLen += ItemWidth; if (Item.Flags & PARATEXT_FLAGS_SPACEAFTER) { if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; bWord = false; nWordLen = 0; } } if ( nSpaceLen > 0 ) { nCurMaxWidth += nSpaceLen; nSpaceLen = 0; } nCurMaxWidth += ItemWidth; break; } case para_Math_Text: case para_Math_Ampersand: case para_Math_Placeholder: { var ItemWidth = Item.Get_Width() / TEXTWIDTH_DIVIDER; if ( false === bWord ) { bWord = true; nWordLen = ItemWidth; } else { nWordLen += ItemWidth; } nCurMaxWidth += ItemWidth; break; } case para_Space: { if ( true === bWord ) { if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; bWord = false; nWordLen = 0; } // Мы сразу не добавляем ширину пробелов к максимальной ширине, потому что // пробелы, идущие в конце параграфа или перед переносом строки(явным), не // должны учитываться. nSpaceLen += Item.Width / TEXTWIDTH_DIVIDER;//nSpaceLen += Item.Get_Width(); break; } case para_Math_BreakOperator: { if ( true === bWord ) { if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; bWord = false; nWordLen = 0; } nCurMaxWidth += Item.Get_Width() / TEXTWIDTH_DIVIDER; break; } case para_Drawing: { if ( true === bWord ) { if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; bWord = false; nWordLen = 0; } if ((true === Item.Is_Inline() || true === this.Paragraph.Parent.Is_DrawingShape()) && Item.Width > nMinWidth) { nMinWidth = Item.Width; } else if (true === Item.Use_TextWrap()) { var DrawingW = Item.getXfrmExtX(); if (DrawingW > nMinWidth) nMinWidth = DrawingW; } if ( nSpaceLen > 0 ) { nCurMaxWidth += nSpaceLen; nSpaceLen = 0; } if ( true === Item.Is_Inline() || true === this.Paragraph.Parent.Is_DrawingShape() ) nCurMaxWidth += Item.Width; break; } case para_PageNum: { if ( true === bWord ) { if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; bWord = false; nWordLen = 0; } if ( Item.Width > nMinWidth ) nMinWidth = Item.Width; if ( nSpaceLen > 0 ) { nCurMaxWidth += nSpaceLen; nSpaceLen = 0; } nCurMaxWidth += Item.Width; break; } case para_Tab: { nWordLen += Item.Width; if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; bWord = false; nWordLen = 0; if ( nSpaceLen > 0 ) { nCurMaxWidth += nSpaceLen; nSpaceLen = 0; } nCurMaxWidth += Item.Width; break; } case para_NewLine: { if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; bWord = false; nWordLen = 0; nSpaceLen = 0; if ( nCurMaxWidth > nMaxWidth ) nMaxWidth = nCurMaxWidth; nCurMaxWidth = 0; break; } case para_End: { if ( nMinWidth < nWordLen ) nMinWidth = nWordLen; if ( nCurMaxWidth > nMaxWidth ) nMaxWidth = nCurMaxWidth; break; } } } MinMax.bWord = bWord; MinMax.nWordLen = nWordLen; MinMax.nSpaceLen = nSpaceLen; MinMax.nMinWidth = nMinWidth; MinMax.nMaxWidth = nMaxWidth; MinMax.nCurMaxWidth = nCurMaxWidth; }; ParaRun.prototype.Get_Range_VisibleWidth = function(RangeW, _CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; switch( ItemType ) { case para_Sym: case para_Text: case para_Space: case para_Math_Text: case para_Math_Ampersand: case para_Math_Placeholder: case para_Math_BreakOperator: { RangeW.W += Item.Get_WidthVisible(); break; } case para_Drawing: { if ( true === Item.Is_Inline() ) RangeW.W += Item.Width; break; } case para_PageNum: case para_Tab: { RangeW.W += Item.Width; break; } case para_NewLine: { RangeW.W += Item.WidthVisible; break; } case para_End: { RangeW.W += Item.Get_WidthVisible(); RangeW.End = true; break; } } } }; ParaRun.prototype.Shift_Range = function(Dx, Dy, _CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); for ( var CurPos = StartPos; CurPos < EndPos; CurPos++ ) { var Item = this.Content[CurPos]; if ( para_Drawing === Item.Type ) Item.Shift( Dx, Dy ); } }; //----------------------------------------------------------------------------------- // Функции отрисовки //----------------------------------------------------------------------------------- ParaRun.prototype.Draw_HighLights = function(PDSH) { var pGraphics = PDSH.Graphics; var CurLine = PDSH.Line - this.StartLine; var CurRange = ( 0 === CurLine ? PDSH.Range - this.StartRange : PDSH.Range ); var aHigh = PDSH.High; var aColl = PDSH.Coll; var aFind = PDSH.Find; var aComm = PDSH.Comm; var aShd = PDSH.Shd; var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var Para = PDSH.Paragraph; var SearchResults = Para.SearchResults; var bDrawFind = PDSH.DrawFind; var bDrawColl = PDSH.DrawColl; var oCompiledPr = this.Get_CompiledPr(false); var oShd = oCompiledPr.Shd; var bDrawShd = ( oShd === undefined || shd_Nil === oShd.Value ? false : true ); var ShdColor = ( true === bDrawShd ? oShd.Get_Color( PDSH.Paragraph ) : null ); if(this.Type == para_Math_Run && this.IsPlaceholder()) bDrawShd = false; var X = PDSH.X; var Y0 = PDSH.Y0; var Y1 = PDSH.Y1; var CommentsCount = PDSH.Comments.length; var CommentId = ( CommentsCount > 0 ? PDSH.Comments[CommentsCount - 1] : null ); var CommentsFlag = PDSH.CommentsFlag; var HighLight = oCompiledPr.HighLight; var SearchMarksCount = this.SearchMarks.length; this.CollaborativeMarks.Init_Drawing(); for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; var ItemWidthVisible = Item.Get_WidthVisible(); // Определим попадание в поиск и совместное редактирование. Попадание в комментарий определять не надо, // т.к. класс CParaRun попадает или не попадает в комментарий целиком. for ( var SPos = 0; SPos < SearchMarksCount; SPos++) { var Mark = this.SearchMarks[SPos]; var MarkPos = Mark.SearchResult.StartPos.Get(Mark.Depth); if ( Pos === MarkPos && true === Mark.Start ) PDSH.SearchCounter++; } var DrawSearch = ( PDSH.SearchCounter > 0 && true === bDrawFind ? true : false ); var DrawColl = this.CollaborativeMarks.Check( Pos ); if ( true === bDrawShd ) aShd.Add( Y0, Y1, X, X + ItemWidthVisible, 0, ShdColor.r, ShdColor.g, ShdColor.b, undefined, oShd ); switch( ItemType ) { case para_PageNum: case para_Drawing: case para_Tab: case para_Text: case para_Math_Text: case para_Math_Placeholder: case para_Math_BreakOperator: case para_Math_Ampersand: case para_Sym: { if ( para_Drawing === ItemType && drawing_Anchor === Item.DrawingType ) break; if ( CommentsFlag != comments_NoComment ) aComm.Add( Y0, Y1, X, X + ItemWidthVisible, 0, 0, 0, 0, { Active : CommentsFlag === comments_ActiveComment ? true : false, CommentId : CommentId } ); else if ( highlight_None != HighLight ) aHigh.Add( Y0, Y1, X, X + ItemWidthVisible, 0, HighLight.r, HighLight.g, HighLight.b, undefined, HighLight ); if ( true === DrawSearch ) aFind.Add( Y0, Y1, X, X + ItemWidthVisible, 0, 0, 0, 0 ); else if ( null !== DrawColl ) aColl.Add( Y0, Y1, X, X + ItemWidthVisible, 0, DrawColl.r, DrawColl.g, DrawColl.b ); if ( para_Drawing != ItemType || drawing_Anchor != Item.DrawingType ) X += ItemWidthVisible; break; } case para_Space: { // Пробелы в конце строки (и строку состоящую из пробелов) не подчеркиваем, не зачеркиваем и не выделяем if ( PDSH.Spaces > 0 ) { if ( CommentsFlag != comments_NoComment ) aComm.Add( Y0, Y1, X, X + ItemWidthVisible, 0, 0, 0, 0, { Active : CommentsFlag === comments_ActiveComment ? true : false, CommentId : CommentId } ); else if ( highlight_None != HighLight ) aHigh.Add( Y0, Y1, X, X + ItemWidthVisible, 0, HighLight.r, HighLight.g, HighLight.b, undefined, HighLight ); PDSH.Spaces--; } if ( true === DrawSearch ) aFind.Add( Y0, Y1, X, X + ItemWidthVisible, 0, 0, 0, 0 ); else if ( null !== DrawColl ) aColl.Add( Y0, Y1, X, X + ItemWidthVisible, 0, DrawColl.r, DrawColl.g, DrawColl.b ); X += ItemWidthVisible; break; } case para_End: { if ( null !== DrawColl ) aColl.Add( Y0, Y1, X, X + ItemWidthVisible, 0, DrawColl.r, DrawColl.g, DrawColl.b ); X += Item.Get_Width(); break; } case para_NewLine: { X += ItemWidthVisible; break; } } for ( var SPos = 0; SPos < SearchMarksCount; SPos++) { var Mark = this.SearchMarks[SPos]; var MarkPos = Mark.SearchResult.EndPos.Get(Mark.Depth); if ( Pos + 1 === MarkPos && true !== Mark.Start ) PDSH.SearchCounter--; } } // Обновим позицию X PDSH.X = X; }; ParaRun.prototype.Draw_Elements = function(PDSE) { var CurLine = PDSE.Line - this.StartLine; var CurRange = ( 0 === CurLine ? PDSE.Range - this.StartRange : PDSE.Range ); var CurPage = PDSE.Page; var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var Para = PDSE.Paragraph; var pGraphics = PDSE.Graphics; var BgColor = PDSE.BgColor; var Theme = PDSE.Theme; var X = PDSE.X; var Y = PDSE.Y; var CurTextPr = this.Get_CompiledPr( false ); pGraphics.SetTextPr( CurTextPr, Theme ); var InfoMathText ; if(this.Type == para_Math_Run) { var ArgSize = this.Parent.Compiled_ArgSz.value, bNormalText = this.IsNormalText(); var InfoTextPr = { TextPr: CurTextPr, ArgSize: ArgSize, bNormalText: bNormalText, bEqArray: this.bEqArray }; InfoMathText = new CMathInfoTextPr(InfoTextPr); } if ( undefined !== CurTextPr.Shd && shd_Nil !== CurTextPr.Shd.Value ) BgColor = CurTextPr.Shd.Get_Color( Para ); var AutoColor = ( undefined != BgColor && false === BgColor.Check_BlackAutoColor() ? new CDocumentColor( 255, 255, 255, false ) : new CDocumentColor( 0, 0, 0, false ) ); var RGBA; var ReviewType = this.Get_ReviewType(); if (reviewtype_Add === ReviewType || reviewtype_Remove === ReviewType) { pGraphics.b_color1(REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b, 255); } else if (CurTextPr.Unifill) { CurTextPr.Unifill.check(PDSE.Theme, PDSE.ColorMap); RGBA = CurTextPr.Unifill.getRGBAColor(); if ( true === PDSE.VisitedHyperlink && ( undefined === this.Pr.Color && undefined === this.Pr.Unifill ) ) { G_O_VISITED_HLINK_COLOR.check(PDSE.Theme, PDSE.ColorMap); RGBA = G_O_VISITED_HLINK_COLOR.getRGBAColor(); pGraphics.b_color1( RGBA.R, RGBA.G, RGBA.B, RGBA.A ); } else { pGraphics.b_color1( RGBA.R, RGBA.G, RGBA.B, RGBA.A); } } else { if ( true === PDSE.VisitedHyperlink && ( undefined === this.Pr.Color && undefined === this.Pr.Unifill ) ) { G_O_VISITED_HLINK_COLOR.check(PDSE.Theme, PDSE.ColorMap); RGBA = G_O_VISITED_HLINK_COLOR.getRGBAColor(); pGraphics.b_color1( RGBA.R, RGBA.G, RGBA.B, RGBA.A ); } else if ( true === CurTextPr.Color.Auto ) { pGraphics.b_color1( AutoColor.r, AutoColor.g, AutoColor.b, 255); } else { pGraphics.b_color1( CurTextPr.Color.r, CurTextPr.Color.g, CurTextPr.Color.b, 255); } } for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; var TempY = Y; switch( CurTextPr.VertAlign ) { case vertalign_SubScript: { Y -= vertalign_Koef_Sub * CurTextPr.FontSize * g_dKoef_pt_to_mm; break; } case vertalign_SuperScript: { Y -= vertalign_Koef_Super * CurTextPr.FontSize * g_dKoef_pt_to_mm; break; } } switch( ItemType ) { case para_PageNum: case para_Drawing: case para_Tab: case para_Text: case para_Sym: { if (para_Tab === ItemType) { pGraphics.p_color(0, 0, 0, 255); pGraphics.b_color1(0, 0, 0, 255); } if ( para_Drawing != ItemType || drawing_Anchor != Item.DrawingType ) { Item.Draw( X, Y - this.YOffset, pGraphics ); X += Item.Get_WidthVisible(); } // Внутри отрисовки инлайн-автофигур могут изменится цвета и шрифт, поэтому восстанавливаем настройки if ((para_Drawing === ItemType && drawing_Inline === Item.DrawingType) || (para_Tab === ItemType)) { pGraphics.SetTextPr( CurTextPr, Theme ); if (reviewtype_Add === ReviewType || reviewtype_Remove === ReviewType) { pGraphics.b_color1(REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b, 255); } else if (RGBA) { pGraphics.b_color1( RGBA.R, RGBA.G, RGBA.B, 255); pGraphics.p_color( RGBA.R, RGBA.G, RGBA.B, 255); } else { if ( true === CurTextPr.Color.Auto ) { pGraphics.b_color1( AutoColor.r, AutoColor.g, AutoColor.b, 255); pGraphics.p_color( AutoColor.r, AutoColor.g, AutoColor.b, 255); } else { pGraphics.b_color1( CurTextPr.Color.r, CurTextPr.Color.g, CurTextPr.Color.b, 255); pGraphics.p_color( CurTextPr.Color.r, CurTextPr.Color.g, CurTextPr.Color.b, 255); } } } break; } case para_Space: { Item.Draw( X, Y - this.YOffset, pGraphics ); X += Item.Get_WidthVisible(); break; } case para_End: { var SectPr = Para.Get_SectionPr(); if (!Para.LogicDocument || Para.LogicDocument !== Para.Parent) SectPr = undefined; if ( undefined === SectPr ) { // Выставляем настройки для символа параграфа var EndTextPr = Para.Get_CompiledPr2(false).TextPr.Copy(); EndTextPr.Merge(Para.TextPr.Value); if (reviewtype_Common !== ReviewType) { pGraphics.SetTextPr(EndTextPr, PDSE.Theme); pGraphics.b_color1(REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b, 255); } else if (EndTextPr.Unifill) { EndTextPr.Unifill.check(PDSE.Theme, PDSE.ColorMap); var RGBAEnd = EndTextPr.Unifill.getRGBAColor(); pGraphics.SetTextPr(EndTextPr, PDSE.Theme); pGraphics.b_color1(RGBAEnd.R, RGBAEnd.G, RGBAEnd.B, 255); } else { pGraphics.SetTextPr(EndTextPr, PDSE.Theme); if (true === EndTextPr.Color.Auto) pGraphics.b_color1(AutoColor.r, AutoColor.g, AutoColor.b, 255); else pGraphics.b_color1(EndTextPr.Color.r, EndTextPr.Color.g, EndTextPr.Color.b, 255); } var bEndCell = false; if (null === Para.Get_DocumentNext() && true === Para.Parent.Is_TableCellContent()) bEndCell = true; Item.Draw(X, Y - this.YOffset, pGraphics, bEndCell, reviewtype_Common !== ReviewType ? true : false); } else { Item.Draw(X, Y - this.YOffset, pGraphics, false, false); } X += Item.Get_Width(); break; } case para_NewLine: { Item.Draw( X, Y - this.YOffset, pGraphics ); X += Item.WidthVisible; break; } case para_Math_Ampersand: case para_Math_Text: case para_Math_BreakOperator: { var PosLine = this.ParaMath.GetLinePosition(PDSE.Line, PDSE.Range); Item.Draw(PosLine.x, PosLine.y, pGraphics, InfoMathText); X += Item.Get_WidthVisible(); break; } case para_Math_Placeholder: { if(pGraphics.RENDERER_PDF_FLAG !== true) // если идет печать/ конвертация в PDF плейсхолдер не отрисовываем { var PosLine = this.ParaMath.GetLinePosition(PDSE.Line, PDSE.Range); Item.Draw(PosLine.x, PosLine.y, pGraphics, InfoMathText); X += Item.Get_WidthVisible(); } break; } } Y = TempY; } // Обновляем позицию PDSE.X = X; }; ParaRun.prototype.Draw_Lines = function(PDSL) { var CurLine = PDSL.Line - this.StartLine; var CurRange = ( 0 === CurLine ? PDSL.Range - this.StartRange : PDSL.Range ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var X = PDSL.X; var Y = PDSL.Baseline; var UndOff = PDSL.UnderlineOffset; var Para = PDSL.Paragraph; var aStrikeout = PDSL.Strikeout; var aDStrikeout = PDSL.DStrikeout; var aUnderline = PDSL.Underline; var aSpelling = PDSL.Spelling; var CurTextPr = this.Get_CompiledPr( false ); var StrikeoutY = Y - this.YOffset; var fontCoeff = 1; // учтем ArgSize if(this.Type == para_Math_Run) { var ArgSize = this.Parent.Compiled_ArgSz; fontCoeff = MatGetKoeffArgSize(CurTextPr.FontSize, ArgSize.value); } switch(CurTextPr.VertAlign) { case vertalign_Baseline : StrikeoutY += -CurTextPr.FontSize * fontCoeff * g_dKoef_pt_to_mm * 0.27; break; case vertalign_SubScript : StrikeoutY += -CurTextPr.FontSize * fontCoeff * vertalign_Koef_Size * g_dKoef_pt_to_mm * 0.27 - vertalign_Koef_Sub * CurTextPr.FontSize * fontCoeff * g_dKoef_pt_to_mm; break; case vertalign_SuperScript: StrikeoutY += -CurTextPr.FontSize * fontCoeff * vertalign_Koef_Size * g_dKoef_pt_to_mm * 0.27 - vertalign_Koef_Super * CurTextPr.FontSize * fontCoeff * g_dKoef_pt_to_mm; break; } var UnderlineY = Y + UndOff - this.YOffset; var LineW = (CurTextPr.FontSize / 18) * g_dKoef_pt_to_mm; var BgColor = PDSL.BgColor; if ( undefined !== CurTextPr.Shd && shd_Nil !== CurTextPr.Shd.Value ) BgColor = CurTextPr.Shd.Get_Color( Para ); var AutoColor = ( undefined != BgColor && false === BgColor.Check_BlackAutoColor() ? new CDocumentColor( 255, 255, 255, false ) : new CDocumentColor( 0, 0, 0, false ) ); var CurColor, RGBA, Theme = this.Paragraph.Get_Theme(), ColorMap = this.Paragraph.Get_ColorMap(); var ReviewType = this.Get_ReviewType(); var bAddReview = reviewtype_Add === ReviewType ? true : false; var bRemReview = reviewtype_Remove === ReviewType ? true : false; // Выставляем цвет обводки if ( true === PDSL.VisitedHyperlink && ( undefined === this.Pr.Color && undefined === this.Pr.Unifill ) ) CurColor = new CDocumentColor( 128, 0, 151 ); else if ( true === CurTextPr.Color.Auto && !CurTextPr.Unifill) CurColor = new CDocumentColor( AutoColor.r, AutoColor.g, AutoColor.b ); else { if(CurTextPr.Unifill) { CurTextPr.Unifill.check(Theme, ColorMap); RGBA = CurTextPr.Unifill.getRGBAColor(); CurColor = new CDocumentColor( RGBA.R, RGBA.G, RGBA.B ); } else { CurColor = new CDocumentColor( CurTextPr.Color.r, CurTextPr.Color.g, CurTextPr.Color.b ); } } var SpellingMarksArray = {}; var SpellingMarksCount = this.SpellingMarks.length; for ( var SPos = 0; SPos < SpellingMarksCount; SPos++) { var Mark = this.SpellingMarks[SPos]; if ( false === Mark.Element.Checked ) { if ( true === Mark.Start ) { var MarkPos = Mark.Element.StartPos.Get(Mark.Depth); if ( undefined === SpellingMarksArray[MarkPos] ) SpellingMarksArray[MarkPos] = 1; else SpellingMarksArray[MarkPos] += 1; } else { var MarkPos = Mark.Element.EndPos.Get(Mark.Depth); if ( undefined === SpellingMarksArray[MarkPos] ) SpellingMarksArray[MarkPos] = 2; else SpellingMarksArray[MarkPos] += 2; } } } for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; var ItemWidthVisible = Item.Get_WidthVisible(); if ( 1 === SpellingMarksArray[Pos] || 3 === SpellingMarksArray[Pos] ) PDSL.SpellingCounter++; switch( ItemType ) { case para_End: { if (this.Paragraph) { if (bAddReview) aUnderline.Add(UnderlineY, UnderlineY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b); else if (bRemReview) aStrikeout.Add(StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b); } X += ItemWidthVisible; break; } case para_NewLine: { X += ItemWidthVisible; break; } case para_PageNum: case para_Drawing: case para_Tab: case para_Text: case para_Sym: { if ( para_Drawing != ItemType || drawing_Anchor != Item.DrawingType ) { if (true === bRemReview) aStrikeout.Add(StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b); else if (true === CurTextPr.DStrikeout) aDStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); else if ( true === CurTextPr.Strikeout ) aStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); if (true === bAddReview) aUnderline.Add(UnderlineY, UnderlineY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b); else if (true === CurTextPr.Underline) aUnderline.Add(UnderlineY, UnderlineY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); if ( PDSL.SpellingCounter > 0 ) aSpelling.Add( UnderlineY, UnderlineY, X, X + ItemWidthVisible, LineW, 0, 0, 0 ); X += ItemWidthVisible; } break; } case para_Space: { // Пробелы, идущие в конце строки, не подчеркиваем и не зачеркиваем if ( PDSL.Spaces > 0 ) { if (true === bRemReview) aStrikeout.Add(StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b); else if (true === CurTextPr.DStrikeout) aDStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); else if ( true === CurTextPr.Strikeout ) aStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); if (true === bAddReview) aUnderline.Add(UnderlineY, UnderlineY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b); else if (true === CurTextPr.Underline) aUnderline.Add( UnderlineY, UnderlineY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); PDSL.Spaces--; } X += ItemWidthVisible; break; } case para_Math_Text: case para_Math_BreakOperator: case para_Math_Ampersand: { if (true === bRemReview) aStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b, undefined, CurTextPr ); else if (true === CurTextPr.DStrikeout) aDStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); else if ( true === CurTextPr.Strikeout ) aStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); X += ItemWidthVisible; break; } case para_Math_Placeholder: { var ctrPrp = this.Parent.GetCtrPrp(); if (true === bRemReview) aStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, REVIEW_COLOR.r, REVIEW_COLOR.g, REVIEW_COLOR.b, undefined, CurTextPr ); if(true === ctrPrp.DStrikeout) aDStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); else if(true === ctrPrp.Strikeout) aStrikeout.Add( StrikeoutY, StrikeoutY, X, X + ItemWidthVisible, LineW, CurColor.r, CurColor.g, CurColor.b, undefined, CurTextPr ); X += ItemWidthVisible; break; } } if ( 2 === SpellingMarksArray[Pos + 1] || 3 === SpellingMarksArray[Pos + 1] ) PDSL.SpellingCounter--; } if (true === this.Pr.Have_PrChange() && para_Math_Run !== this.Type) PDSL.RunReview.Add(0, 0, PDSL.X, X, 0, 255, 0, 0, {RunPr : this.Pr}); var CollPrChangeColor = this.private_GetCollPrChangeOther(); if (false !== CollPrChangeColor) PDSL.CollChange.Add(0, 0, PDSL.X, X, 0, CollPrChangeColor.r, CollPrChangeColor.g, CollPrChangeColor.b, {RunPr : this.Pr}); // Обновляем позицию PDSL.X = X; }; //----------------------------------------------------------------------------------- // Функции для работы с курсором //----------------------------------------------------------------------------------- // Находится ли курсор в начале рана ParaRun.prototype.Is_CursorPlaceable = function() { return true; }; ParaRun.prototype.Cursor_Is_Start = function() { if ( this.State.ContentPos <= 0 ) return true; return false; }; // Проверяем нужно ли поправить позицию курсора ParaRun.prototype.Cursor_Is_NeededCorrectPos = function() { if ( true === this.Is_Empty(false) ) return true; var NewRangeStart = false; var RangeEnd = false; var Pos = this.State.ContentPos; var LinesLen = this.protected_GetLinesCount(); for ( var CurLine = 0; CurLine < LinesLen; CurLine++ ) { var RangesLen = this.protected_GetRangesCount(CurLine); for ( var CurRange = 0; CurRange < RangesLen; CurRange++ ) { var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); if (0 !== CurLine || 0 !== CurRange) { if (Pos === StartPos) { NewRangeStart = true; } } if (Pos === EndPos) { RangeEnd = true; } } if ( true === NewRangeStart ) break; } if ( true !== NewRangeStart && true !== RangeEnd && true === this.Cursor_Is_Start() ) return true; return false; }; ParaRun.prototype.Cursor_Is_End = function() { if ( this.State.ContentPos >= this.Content.length ) return true; return false; }; ParaRun.prototype.Cursor_MoveToStartPos = function() { this.State.ContentPos = 0; }; ParaRun.prototype.Cursor_MoveToEndPos = function(SelectFromEnd) { if ( true === SelectFromEnd ) { var Selection = this.State.Selection; Selection.Use = true; Selection.StartPos = this.Content.length; Selection.EndPos = this.Content.length; } else { var CurPos = this.Content.length; while ( CurPos > 0 ) { if ( para_End === this.Content[CurPos - 1].Type ) CurPos--; else break; } this.State.ContentPos = CurPos; } }; ParaRun.prototype.Get_ParaContentPosByXY = function(SearchPos, Depth, _CurLine, _CurRange, StepEnd) { var Result = false; var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var CurPos = StartPos; var InMathText = this.Type == para_Math_Run ? SearchPos.InText == true : false; for (; CurPos < EndPos; CurPos++ ) { var Item = this.Content[CurPos]; var ItemType = Item.Type; var TempDx = 0; if (para_Drawing != ItemType || true === Item.Is_Inline()) { TempDx = Item.Get_WidthVisible(); } if(this.Type == para_Math_Run) { var PosLine = this.ParaMath.GetLinePosition(_CurLine, _CurRange); var loc = this.Content[CurPos].GetLocationOfLetter(); SearchPos.CurX = PosLine.x + loc.x; // позиция формулы в строке + смещение буквы в контенте } // Проверяем, попали ли мы в данный элемент var Diff = SearchPos.X - SearchPos.CurX; if ((Math.abs( Diff ) < SearchPos.DiffX + 0.001 && (SearchPos.CenterMode || SearchPos.X > SearchPos.CurX)) && InMathText == false) { SearchPos.DiffX = Math.abs( Diff ); SearchPos.Pos.Update( CurPos, Depth ); Result = true; if ( Diff >= - 0.001 && Diff <= TempDx + 0.001 ) { SearchPos.InTextPos.Update( CurPos, Depth ); SearchPos.InText = true; } } SearchPos.CurX += TempDx; // Заглушка для знака параграфа и конца строки Diff = SearchPos.X - SearchPos.CurX; if ((Math.abs( Diff ) < SearchPos.DiffX + 0.001 && (SearchPos.CenterMode || SearchPos.X > SearchPos.CurX)) && InMathText == false) { if ( para_End === ItemType ) { SearchPos.End = true; // Если мы ищем позицию для селекта, тогда нужно искать и за знаком параграфа if ( true === StepEnd ) { SearchPos.Pos.Update( this.Content.length, Depth ); Result = true; } } else if ( CurPos === EndPos - 1 && para_NewLine != ItemType ) { SearchPos.Pos.Update( EndPos, Depth ); Result = true; } } } // Такое возможно, если все раны до этого (в том числе и этот) были пустыми, тогда, чтобы не возвращать // неправильную позицию вернем позицию начала данного путого рана. if ( SearchPos.DiffX > 1000000 - 1 ) { SearchPos.Pos.Update( StartPos, Depth ); Result = true; } if (this.Type == para_Math_Run) // не только для пустых Run, но и для проверки на конец Run (т.к. Diff не обновляется) { //для пустых Run искомая позиция - позиция самого Run var bEmpty = this.Is_Empty(); var PosLine = this.ParaMath.GetLinePosition(_CurLine, _CurRange); if(bEmpty) SearchPos.CurX = PosLine.x + this.pos.x; Diff = SearchPos.X - SearchPos.CurX; if(SearchPos.InText == false && (bEmpty || StartPos !== EndPos) && (Math.abs( Diff ) < SearchPos.DiffX + 0.001 && (SearchPos.CenterMode || SearchPos.X > SearchPos.CurX))) { SearchPos.DiffX = Math.abs( Diff ); SearchPos.Pos.Update( CurPos, Depth ); Result = true; } } return Result; }; ParaRun.prototype.Get_ParaContentPos = function(bSelection, bStart, ContentPos) { var Pos = ( true !== bSelection ? this.State.ContentPos : ( false !== bStart ? this.State.Selection.StartPos : this.State.Selection.EndPos ) ); ContentPos.Add(Pos); }; ParaRun.prototype.Set_ParaContentPos = function(ContentPos, Depth) { var Pos = ContentPos.Get(Depth); var Count = this.Content.length; if ( Pos > Count ) Pos = Count; // TODO: Как только переделаем работу c Para_End переделать здесь for ( var TempPos = 0; TempPos < Pos; TempPos++ ) { if ( para_End === this.Content[TempPos].Type ) { Pos = TempPos; break; } } if ( Pos < 0 ) Pos = 0; this.State.ContentPos = Pos; }; ParaRun.prototype.Get_PosByElement = function(Class, ContentPos, Depth, UseRange, Range, Line) { if ( this === Class ) return true; return false; }; ParaRun.prototype.Get_ElementByPos = function(ContentPos, Depth) { return this; }; ParaRun.prototype.Get_PosByDrawing = function(Id, ContentPos, Depth) { var Count = this.Content.length; for ( var CurPos = 0; CurPos < Count; CurPos++ ) { var Item = this.Content[CurPos]; if ( para_Drawing === Item.Type && Id === Item.Get_Id() ) { ContentPos.Update( CurPos, Depth ); return true; } } return false; }; ParaRun.prototype.Get_RunElementByPos = function(ContentPos, Depth) { if ( undefined !== ContentPos ) { var CurPos = ContentPos.Get(Depth); var ContentLen = this.Content.length; if ( CurPos >= this.Content.length || CurPos < 0 ) return null; return this.Content[CurPos]; } else { if ( this.Content.length > 0 ) return this.Content[0]; else return null; } }; ParaRun.prototype.Get_LastRunInRange = function(_CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); return this; }; ParaRun.prototype.Get_LeftPos = function(SearchPos, ContentPos, Depth, UseContentPos) { var CurPos = ( true === UseContentPos ? ContentPos.Get(Depth) : this.Content.length ); while ( true ) { CurPos--; var Item = this.Content[CurPos]; if ( CurPos < 0 || para_Drawing !== Item.Type || false !== Item.Is_Inline() ) break; } if ( CurPos >= 0 ) { SearchPos.Found = true; SearchPos.Pos.Update( CurPos, Depth ); } }; ParaRun.prototype.Get_RightPos = function(SearchPos, ContentPos, Depth, UseContentPos, StepEnd) { var CurPos = ( true === UseContentPos ? ContentPos.Get(Depth) : 0 ); var Count = this.Content.length; while ( true ) { CurPos++; // Мы встали в конец рана: // Если мы перешагнули para_End или para_Drawing Anchor, тогда возвращаем false // В противном случае true if ( Count === CurPos ) { if ( CurPos === 0 ) return; var PrevItem = this.Content[CurPos - 1]; var PrevItemType = PrevItem.Type; if ((true !== StepEnd && para_End === PrevItemType) || (para_Drawing === PrevItemType && false === PrevItem.Is_Inline())) return; break; } if (CurPos > Count) break; var Item = this.Content[CurPos]; var ItemType = Item.Type; if ((para_Drawing !== ItemType && (false !== StepEnd || para_End !== this.Content[CurPos - 1].Type)) || (para_Drawing === ItemType && false !== Item.Is_Inline())) break; } if ( CurPos <= Count ) { SearchPos.Found = true; SearchPos.Pos.Update( CurPos, Depth ); } }; ParaRun.prototype.Get_WordStartPos = function(SearchPos, ContentPos, Depth, UseContentPos) { var CurPos = ( true === UseContentPos ? ContentPos.Get(Depth) - 1 : this.Content.length - 1 ); if ( CurPos < 0 ) return; SearchPos.Shift = true; var NeedUpdate = false; // На первом этапе ищем позицию первого непробельного элемента if ( 0 === SearchPos.Stage ) { while ( true ) { var Item = this.Content[CurPos]; var Type = Item.Type; var bSpace = false; if ( para_Space === Type || para_Tab === Type || ( para_Text === Type && true === Item.Is_NBSP() ) || ( para_Drawing === Type && true !== Item.Is_Inline() ) ) bSpace = true; if ( true === bSpace ) { CurPos--; // Выходим из данного рана if ( CurPos < 0 ) return; } else { // Если мы остановились на нетекстовом элементе, тогда его и возвращаем if ( para_Text !== this.Content[CurPos].Type && para_Math_Text !== this.Content[CurPos].Type) { SearchPos.Pos.Update( CurPos, Depth ); SearchPos.Found = true; SearchPos.UpdatePos = true; return; } SearchPos.Pos.Update( CurPos, Depth ); SearchPos.Stage = 1; SearchPos.Punctuation = this.Content[CurPos].Is_Punctuation(); NeedUpdate = true; break; } } } else { CurPos = ( true === UseContentPos ? ContentPos.Get(Depth) : this.Content.length ); } // На втором этапе мы смотрим на каком элементе мы встали: если текст - пунктуация, тогда сдвигаемся // до конца всех знаков пунктуации while ( CurPos > 0 ) { CurPos--; var Item = this.Content[CurPos]; var TempType = Item.Type; if ( (para_Text !== TempType && para_Math_Text !== TempType) || true === Item.Is_NBSP() || ( true === SearchPos.Punctuation && true !== Item.Is_Punctuation() ) || ( false === SearchPos.Punctuation && false !== Item.Is_Punctuation() ) ) { SearchPos.Found = true; break; } else { SearchPos.Pos.Update( CurPos, Depth ); NeedUpdate = true; } } SearchPos.UpdatePos = NeedUpdate; }; ParaRun.prototype.Get_WordEndPos = function(SearchPos, ContentPos, Depth, UseContentPos, StepEnd) { var CurPos = ( true === UseContentPos ? ContentPos.Get(Depth) : 0 ); var ContentLen = this.Content.length; if ( CurPos >= ContentLen ) return; var NeedUpdate = false; if ( 0 === SearchPos.Stage ) { // На первом этапе ищем первый нетекстовый ( и не таб ) элемент while ( true ) { var Item = this.Content[CurPos]; var Type = Item.Type; var bText = false; if ( (para_Text === Type || para_Math_Text === Type) && true != Item.Is_NBSP() && ( true === SearchPos.First || ( SearchPos.Punctuation === Item.Is_Punctuation() ) ) ) bText = true; if ( true === bText ) { if ( true === SearchPos.First ) { SearchPos.First = false; SearchPos.Punctuation = Item.Is_Punctuation(); } CurPos++; // Отмечаем, что сдвиг уже произошел SearchPos.Shift = true; // Выходим из рана if ( CurPos >= ContentLen ) return; } else { SearchPos.Stage = 1; // Первый найденный элемент не текстовый, смещаемся вперед if ( true === SearchPos.First ) { // Если первый найденный элемент - конец параграфа, тогда выходим из поиска if ( para_End === Type ) { if ( true === StepEnd ) { SearchPos.Pos.Update( CurPos + 1, Depth ); SearchPos.Found = true; SearchPos.UpdatePos = true; } return; } CurPos++; // Отмечаем, что сдвиг уже произошел SearchPos.Shift = true; } break; } } } if ( CurPos >= ContentLen ) return; // На втором этапе мы смотрим на каком элементе мы встали: если это не пробел, тогда // останавливаемся здесь. В противном случае сдвигаемся вперед, пока не попали на первый // не пробельный элемент. if ( !(para_Space === this.Content[CurPos].Type || ( para_Text === this.Content[CurPos].Type && true === this.Content[CurPos].Is_NBSP() ) ) ) { SearchPos.Pos.Update( CurPos, Depth ); SearchPos.Found = true; SearchPos.UpdatePos = true; } else { while ( CurPos < ContentLen - 1 ) { CurPos++; var Item = this.Content[CurPos]; var TempType = Item.Type; if ( (true !== StepEnd && para_End === TempType) || !( para_Space === TempType || ( para_Text === TempType && true === Item.Is_NBSP() ) ) ) { SearchPos.Found = true; break; } } // Обновляем позицию в конце каждого рана (хуже от этого не будет) SearchPos.Pos.Update( CurPos, Depth ); SearchPos.UpdatePos = true; } }; ParaRun.prototype.Get_EndRangePos = function(_CurLine, _CurRange, SearchPos, Depth) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var LastPos = -1; for ( var CurPos = StartPos; CurPos < EndPos; CurPos++ ) { var Item = this.Content[CurPos]; var ItemType = Item.Type; if ( !((para_Drawing === ItemType && true !== Item.Is_Inline()) || para_End === ItemType || (para_NewLine === ItemType && break_Line === Item.BreakType))) LastPos = CurPos + 1; } // Проверяем, попал ли хоть один элемент в данный отрезок, если нет, тогда не регистрируем такой ран if ( -1 !== LastPos ) { SearchPos.Pos.Update( LastPos, Depth ); return true; } else return false; }; ParaRun.prototype.Get_StartRangePos = function(_CurLine, _CurRange, SearchPos, Depth) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var FirstPos = -1; for ( var CurPos = EndPos - 1; CurPos >= StartPos; CurPos-- ) { var Item = this.Content[CurPos]; if ( !(para_Drawing === Item.Type && true !== Item.Is_Inline()) ) FirstPos = CurPos; } // Проверяем, попал ли хоть один элемент в данный отрезок, если нет, тогда не регистрируем такой ран if ( -1 !== FirstPos ) { SearchPos.Pos.Update( FirstPos, Depth ); return true; } else return false; }; ParaRun.prototype.Get_StartRangePos2 = function(_CurLine, _CurRange, ContentPos, Depth) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var Pos = this.protected_GetRangeStartPos(CurLine, CurRange); ContentPos.Update( Pos, Depth ); }; ParaRun.prototype.Get_StartPos = function(ContentPos, Depth) { ContentPos.Update( 0, Depth ); }; ParaRun.prototype.Get_EndPos = function(BehindEnd, ContentPos, Depth) { var ContentLen = this.Content.length; if ( true === BehindEnd ) ContentPos.Update( ContentLen, Depth ); else { for ( var CurPos = 0; CurPos < ContentLen; CurPos++ ) { if ( para_End === this.Content[CurPos].Type ) { ContentPos.Update( CurPos, Depth ); return; } } // Не нашли para_End ContentPos.Update( ContentLen, Depth ); } }; //----------------------------------------------------------------------------------- // Функции для работы с селектом //----------------------------------------------------------------------------------- ParaRun.prototype.Set_SelectionContentPos = function(StartContentPos, EndContentPos, Depth, StartFlag, EndFlag) { var StartPos = 0; switch (StartFlag) { case 1: StartPos = 0; break; case -1: StartPos = this.Content.length; break; case 0: StartPos = StartContentPos.Get(Depth); break; } var EndPos = 0; switch (EndFlag) { case 1: EndPos = 0; break; case -1: EndPos = this.Content.length; break; case 0: EndPos = EndContentPos.Get(Depth); break; } var Selection = this.State.Selection; Selection.StartPos = StartPos; Selection.EndPos = EndPos; Selection.Use = true; }; ParaRun.prototype.Set_ContentSelection = function(StartDocPos, EndDocPos, Depth, StartFlag, EndFlag) { var StartPos = 0; switch (StartFlag) { case 1: StartPos = 0; break; case -1: StartPos = this.Content.length; break; case 0: StartPos = StartDocPos[Depth].Position; break; } var EndPos = 0; switch (EndFlag) { case 1: EndPos = 0; break; case -1: EndPos = this.Content.length; break; case 0: EndPos = EndDocPos[Depth].Position; break; } var Selection = this.State.Selection; Selection.StartPos = StartPos; Selection.EndPos = EndPos; Selection.Use = true; }; ParaRun.prototype.Set_ContentPosition = function(DocPos, Depth, Flag) { var Pos = 0; switch (Flag) { case 1: Pos = 0; break; case -1: Pos = this.Content.length; break; case 0: Pos = DocPos[Depth].Position; break; } this.State.ContentPos = Pos; }; ParaRun.prototype.Set_SelectionAtEndPos = function() { this.Set_SelectionContentPos(null, null, 0, -1, -1); }; ParaRun.prototype.Set_SelectionAtStartPos = function() { this.Set_SelectionContentPos(null, null, 0, 1, 1); }; ParaRun.prototype.Selection_IsUse = function() { return this.State.Selection.Use; }; ParaRun.prototype.Is_SelectionUse = function() { return this.State.Selection.Use; }; ParaRun.prototype.Is_SelectedAll = function(Props) { var Selection = this.State.Selection; if ( false === Selection.Use && true !== this.Is_Empty( Props ) ) return false; var SkipAnchor = Props ? Props.SkipAnchor : false; var SkipEnd = Props ? Props.SkipEnd : false; var StartPos = Selection.StartPos; var EndPos = Selection.EndPos; if ( EndPos < StartPos ) { StartPos = Selection.EndPos; EndPos = Selection.StartPos; } for ( var Pos = 0; Pos < StartPos; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; if ( !( ( true === SkipAnchor && ( para_Drawing === ItemType && true !== Item.Is_Inline() ) ) || ( true === SkipEnd && para_End === ItemType ) ) ) return false; } var Count = this.Content.length; for ( var Pos = EndPos; Pos < Count; Pos++ ) { var Item = this.Content[Pos]; var ItemType = Item.Type; if ( !( ( true === SkipAnchor && ( para_Drawing === ItemType && true !== Item.Is_Inline() ) ) || ( true === SkipEnd && para_End === ItemType ) ) ) return false; } return true; }; ParaRun.prototype.Selection_CorrectLeftPos = function(Direction) { if ( false === this.Selection.Use || true === this.Is_Empty( { SkipAnchor : true } ) ) return true; var Selection = this.State.Selection; var StartPos = Math.min( Selection.StartPos, Selection.EndPos ); var EndPos = Math.max( Selection.StartPos, Selection.EndPos ); for ( var Pos = 0; Pos < StartPos; Pos++ ) { var Item = this.Content[Pos]; if ( para_Drawing !== Item.Type || true === Item.Is_Inline() ) return false; } for ( var Pos = StartPos; Pos < EndPos; Pos++ ) { var Item = this.Content[Pos]; if ( para_Drawing === Item.Type && true !== Item.Is_Inline() ) { if ( 1 === Direction ) Selection.StartPos = Pos + 1; else Selection.EndPos = Pos + 1; } else return false; } return true; }; ParaRun.prototype.Selection_Stop = function() { }; ParaRun.prototype.Selection_Remove = function() { var Selection = this.State.Selection; Selection.Use = false; Selection.StartPos = 0; Selection.EndPos = 0; }; ParaRun.prototype.Select_All = function(Direction) { var Selection = this.State.Selection; Selection.Use = true; if ( -1 === Direction ) { Selection.StartPos = this.Content.length; Selection.EndPos = 0; } else { Selection.StartPos = 0; Selection.EndPos = this.Content.length; } }; ParaRun.prototype.Selection_DrawRange = function(_CurLine, _CurRange, SelectionDraw) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var Selection = this.State.Selection; var SelectionUse = Selection.Use; var SelectionStartPos = Selection.StartPos; var SelectionEndPos = Selection.EndPos; if ( SelectionStartPos > SelectionEndPos ) { SelectionStartPos = Selection.EndPos; SelectionEndPos = Selection.StartPos; } var FindStart = SelectionDraw.FindStart; for(var CurPos = StartPos; CurPos < EndPos; CurPos++) { var Item = this.Content[CurPos]; var ItemType = Item.Type; var DrawSelection = false; if ( true === FindStart ) { if ( true === Selection.Use && CurPos >= SelectionStartPos && CurPos < SelectionEndPos ) { FindStart = false; DrawSelection = true; } else { if ( para_Drawing !== ItemType || true === Item.Is_Inline() ) SelectionDraw.StartX += Item.Get_WidthVisible(); } } else { if ( true === Selection.Use && CurPos >= SelectionStartPos && CurPos < SelectionEndPos ) { DrawSelection = true; } } if ( true === DrawSelection ) { if (para_Drawing === ItemType && true !== Item.Is_Inline()) { if (true === SelectionDraw.Draw) Item.Draw_Selection(); } else SelectionDraw.W += Item.Get_WidthVisible(); } } SelectionDraw.FindStart = FindStart; }; ParaRun.prototype.Selection_IsEmpty = function(CheckEnd) { var Selection = this.State.Selection; if (true !== Selection.Use) return true; if(this.Type == para_Math_Run && this.IsPlaceholder()) return true; var StartPos = Selection.StartPos; var EndPos = Selection.EndPos; if ( StartPos > EndPos ) { StartPos = Selection.EndPos; EndPos = Selection.StartPos; } if ( true === CheckEnd ) return ( EndPos > StartPos ? false : true ); else if(this.Type == para_Math_Run && this.Is_Empty()) { return false; } else { for ( var CurPos = StartPos; CurPos < EndPos; CurPos++ ) { var ItemType = this.Content[CurPos].Type; if (para_End !== ItemType) return false; } } return true; }; ParaRun.prototype.Selection_CheckParaEnd = function() { var Selection = this.State.Selection; if ( true !== Selection.Use ) return false; var StartPos = Selection.StartPos; var EndPos = Selection.EndPos; if ( StartPos > EndPos ) { StartPos = Selection.EndPos; EndPos = Selection.StartPos; } for ( var CurPos = StartPos; CurPos < EndPos; CurPos++ ) { var Item = this.Content[CurPos]; if ( para_End === Item.Type ) return true; } return false; }; ParaRun.prototype.Selection_CheckParaContentPos = function(ContentPos, Depth, bStart, bEnd) { var CurPos = ContentPos.Get(Depth); if (this.Selection.StartPos <= this.Selection.EndPos && this.Selection.StartPos <= CurPos && CurPos <= this.Selection.EndPos) { if ((true !== bEnd) || (true === bEnd && CurPos !== this.Selection.EndPos)) return true; } else if (this.Selection.StartPos > this.Selection.EndPos && this.Selection.EndPos <= CurPos && CurPos <= this.Selection.StartPos) { if ((true !== bEnd) || (true === bEnd && CurPos !== this.Selection.StartPos)) return true; } return false; }; //----------------------------------------------------------------------------------- // Функции для работы с настройками текста свойств //----------------------------------------------------------------------------------- ParaRun.prototype.Clear_TextFormatting = function( DefHyper ) { // Highlight и Lang не сбрасываются при очистке текстовых настроек this.Set_Bold( undefined ); this.Set_Italic( undefined ); this.Set_Strikeout( undefined ); this.Set_Underline( undefined ); this.Set_FontSize( undefined ); this.Set_Color( undefined ); this.Set_Unifill( undefined ); this.Set_VertAlign( undefined ); this.Set_Spacing( undefined ); this.Set_DStrikeout( undefined ); this.Set_Caps( undefined ); this.Set_SmallCaps( undefined ); this.Set_Position( undefined ); this.Set_RFonts2( undefined ); this.Set_RStyle( undefined ); this.Set_Shd( undefined ); this.Set_TextFill( undefined ); this.Set_TextOutline( undefined ); // Насильно заставим пересчитать стиль, т.к. как данная функция вызывается у параграфа, у которого мог смениться стиль this.Recalc_CompiledPr(true); }; ParaRun.prototype.Get_TextPr = function() { return this.Pr.Copy(); }; ParaRun.prototype.Get_FirstTextPr = function() { return this.Pr; }; ParaRun.prototype.Get_CompiledTextPr = function(Copy) { if ( true === this.State.Selection.Use && true === this.Selection_CheckParaEnd() ) { var ThisTextPr = this.Get_CompiledPr( true ); var Para = this.Paragraph; var EndTextPr = Para.Get_CompiledPr2(false).TextPr.Copy(); EndTextPr.Merge( Para.TextPr.Value ); ThisTextPr = ThisTextPr.Compare( EndTextPr ); return ThisTextPr; } else return this.Get_CompiledPr(Copy); }; ParaRun.prototype.Recalc_CompiledPr = function(RecalcMeasure) { this.RecalcInfo.TextPr = true; // Если изменение какой-то текстовой настройки требует пересчета элементов if ( true === RecalcMeasure ) this.RecalcInfo.Measure = true; // Если мы в формуле, тогда ее надо пересчитывать this.private_RecalcCtrPrp(); }; ParaRun.prototype.Recalc_RunsCompiledPr = function() { this.Recalc_CompiledPr(true); }; ParaRun.prototype.Get_CompiledPr = function(bCopy) { if ( true === this.RecalcInfo.TextPr ) { this.RecalcInfo.TextPr = false; this.CompiledPr = this.Internal_Compile_Pr(); } if ( false === bCopy ) return this.CompiledPr; else return this.CompiledPr.Copy(); // Отдаем копию объекта, чтобы никто не поменял извне настройки стиля }; ParaRun.prototype.Internal_Compile_Pr = function () { if ( undefined === this.Paragraph || null === this.Paragraph ) { // Сюда мы никогда не должны попадать, но на всякий случай, // чтобы не выпадало ошибок сгенерим дефолтовые настройки var TextPr = new CTextPr(); TextPr.Init_Default(); this.RecalcInfo.TextPr = true; return TextPr; } // Получим настройки текста, для данного параграфа var TextPr = this.Paragraph.Get_CompiledPr2(false).TextPr.Copy(); // Если в прямых настройках задан стиль, тогда смержим настройки стиля if ( undefined != this.Pr.RStyle ) { var Styles = this.Paragraph.Parent.Get_Styles(); var StyleTextPr = Styles.Get_Pr( this.Pr.RStyle, styletype_Character ).TextPr; TextPr.Merge( StyleTextPr ); } if(this.Type == para_Math_Run) { if (undefined === this.Parent || null === this.Parent) { // Сюда мы никогда не должны попадать, но на всякий случай, // чтобы не выпадало ошибок сгенерим дефолтовые настройки var TextPr = new CTextPr(); TextPr.Init_Default(); this.RecalcInfo.TextPr = true; return TextPr; } // var Styles = this.Paragraph.Parent.Get_Styles(); // this.Paragraph.Parent.Styles (rPrDefault, pPrDefault) не влияют на Font Name в мат тексте, поэтому выставляем в Default в текстовых настройках RFonts "Cambria Math" (дефолтовый Font) // if(!this.IsNormalText()) // math text { var Styles = this.Paragraph.Parent.Get_Styles(); // скопируем текстовые настройки прежде чем подменим на пустые var StyleDefaultTextPr = Styles.Default.TextPr.Copy(); var DefaultTextPr = new CTextPr(); DefaultTextPr.RFonts.Set_All("Cambria Math", -1); Styles.Default.TextPr = DefaultTextPr; var StyleId = this.Paragraph.Style_Get(); var Pr = Styles.Get_Pr( StyleId, styletype_Paragraph, null, null ); TextPr.RFonts.Set_FromObject(Pr.TextPr.RFonts); // подменяем обратно Styles.Default.TextPr = StyleDefaultTextPr; } // Not Apply ArgSize ! //var oWPrp = this.Parent.Get_Default_TPrp(); //TextPr.Merge(oWPrp); if(this.IsPlaceholder()) { TextPr.Merge(this.Parent.GetCtrPrp()); TextPr.Merge( this.Pr ); // Мержим прямые настройки данного рана } else { TextPr.Merge( this.Pr ); // Мержим прямые настройки данного рана if(!this.IsNormalText()) // math text { var MPrp = this.MathPrp.GetTxtPrp(); TextPr.Merge(MPrp); // bold, italic } } } else { TextPr.Merge( this.Pr ); // Мержим прямые настройки данного рана if(this.Pr.Color && !this.Pr.Unifill) { TextPr.Unifill = undefined; } } // Для совместимости со старыми версиями запишем FontFamily TextPr.FontFamily.Name = TextPr.RFonts.Ascii.Name; TextPr.FontFamily.Index = TextPr.RFonts.Ascii.Index; return TextPr; }; // В данной функции мы жестко меняем настройки на те, которые пришли (т.е. полностью удаляем старые) ParaRun.prototype.Set_Pr = function(TextPr) { var OldValue = this.Pr; this.Pr = TextPr; History.Add( this, { Type : historyitem_ParaRun_TextPr, New : TextPr, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(true); }; ParaRun.prototype.Apply_TextPr = function(TextPr, IncFontSize, ApplyToAll) { var bReview = false; if (this.Paragraph && this.Paragraph.LogicDocument && true === this.Paragraph.LogicDocument.Is_TrackRevisions()) bReview = true; var ReviewType = this.Get_ReviewType(); var IsPrChange = this.Have_PrChange(); if ( true === ApplyToAll ) { if (true === bReview && true !== this.Have_PrChange()) this.Add_PrChange(); if ( undefined === IncFontSize ) { this.Apply_Pr(TextPr); } else { var _TextPr = new CTextPr(); var CurTextPr = this.Get_CompiledPr( false ); this.private_AddCollPrChangeMine(); this.Set_FontSize( FontSize_IncreaseDecreaseValue( IncFontSize, CurTextPr.FontSize ) ); } // Дополнительно проверим, если у нас para_End лежит в данном ране и попадает в выделение, тогда // применим заданные настроки к символу конца параграфа // TODO: Возможно, стоит на этапе пересчета запонимать, лежит ли para_End в данном ране. Чтобы в каждом // ране потом не бегать каждый раз по всему массиву в поисках para_End. var bEnd = false; var Count = this.Content.length; for ( var Pos = 0; Pos < Count; Pos++ ) { if ( para_End === this.Content[Pos].Type ) { bEnd = true; break; } } if ( true === bEnd ) { if ( undefined === IncFontSize ) { if(!TextPr.AscFill && !TextPr.AscLine && !TextPr.AscUnifill) { this.Paragraph.TextPr.Apply_TextPr( TextPr ); } else { var EndTextPr = this.Paragraph.Get_CompiledPr2(false).TextPr.Copy(); EndTextPr.Merge( this.Paragraph.TextPr.Value ); if(TextPr.AscFill) { this.Paragraph.TextPr.Set_TextFill(CorrectUniFill(TextPr.AscFill, EndTextPr.TextFill, 0)); } if(TextPr.AscUnifill) { this.Paragraph.TextPr.Set_Unifill(CorrectUniFill(TextPr.AscUnifill, EndTextPr.Unifill, 0)); } if(TextPr.AscLine) { this.Paragraph.TextPr.Set_TextOutline(CorrectUniStroke(TextPr.AscLine, EndTextPr.TextOutline, 0)); } } } else { var Para = this.Paragraph; // Выставляем настройки для символа параграфа var EndTextPr = Para.Get_CompiledPr2(false).TextPr.Copy(); EndTextPr.Merge( Para.TextPr.Value ); // TODO: Как только перенесем историю изменений TextPr в сам класс CTextPr, переделать тут Para.TextPr.Set_FontSize( FontSize_IncreaseDecreaseValue( IncFontSize, EndTextPr.FontSize ) ); } } } else { var Result = []; var LRun = this, CRun = null, RRun = null; if ( true === this.State.Selection.Use ) { var StartPos = this.State.Selection.StartPos; var EndPos = this.State.Selection.EndPos; var Direction = 1; if ( StartPos > EndPos ) { var Temp = StartPos; StartPos = EndPos; EndPos = Temp; Direction = -1; } // Если выделено не до конца, тогда разделяем по последней точке if ( EndPos < this.Content.length ) { RRun = LRun.Split_Run(EndPos); RRun.Set_ReviewType(ReviewType); if (IsPrChange) RRun.Add_PrChange(); } // Если выделено не с начала, тогда делим по начальной точке if ( StartPos > 0 ) { CRun = LRun.Split_Run(StartPos); CRun.Set_ReviewType(ReviewType); if (IsPrChange) CRun.Add_PrChange(); } else { CRun = LRun; LRun = null; } if ( null !== LRun ) { LRun.Selection.Use = true; LRun.Selection.StartPos = LRun.Content.length; LRun.Selection.EndPos = LRun.Content.length; } CRun.Select_All(Direction); if (true === bReview && true !== CRun.Have_PrChange()) CRun.Add_PrChange(); if ( undefined === IncFontSize ) CRun.Apply_Pr( TextPr ); else { var _TextPr = new CTextPr(); var CurTextPr = this.Get_CompiledPr( false ); CRun.private_AddCollPrChangeMine(); CRun.Set_FontSize( FontSize_IncreaseDecreaseValue( IncFontSize, CurTextPr.FontSize ) ); } if ( null !== RRun ) { RRun.Selection.Use = true; RRun.Selection.StartPos = 0; RRun.Selection.EndPos = 0; } // Дополнительно проверим, если у нас para_End лежит в данном ране и попадает в выделение, тогда // применим заданные настроки к символу конца параграфа // TODO: Возможно, стоит на этапе пересчета запонимать, лежит ли para_End в данном ране. Чтобы в каждом // ране потом не бегать каждый раз по всему массиву в поисках para_End. if ( true === this.Selection_CheckParaEnd() ) { if ( undefined === IncFontSize ) { if(!TextPr.AscFill && !TextPr.AscLine && !TextPr.AscUnifill) { this.Paragraph.TextPr.Apply_TextPr( TextPr ); } else { var EndTextPr = this.Paragraph.Get_CompiledPr2(false).TextPr.Copy(); EndTextPr.Merge( this.Paragraph.TextPr.Value ); if(TextPr.AscFill) { this.Paragraph.TextPr.Set_TextFill(CorrectUniFill(TextPr.AscFill, EndTextPr.TextFill, 0)); } if(TextPr.AscUnifill) { this.Paragraph.TextPr.Set_Unifill(CorrectUniFill(TextPr.AscUnifill, EndTextPr.Unifill, 0)); } if(TextPr.AscLine) { this.Paragraph.TextPr.Set_TextOutline(CorrectUniStroke(TextPr.AscLine, EndTextPr.TextOutline, 0)); } } } else { var Para = this.Paragraph; // Выставляем настройки для символа параграфа var EndTextPr = Para.Get_CompiledPr2(false).TextPr.Copy(); EndTextPr.Merge( Para.TextPr.Value ); // TODO: Как только перенесем историю изменений TextPr в сам класс CTextPr, переделать тут Para.TextPr.Set_FontSize( FontSize_IncreaseDecreaseValue( IncFontSize, EndTextPr.FontSize ) ); } } } else { var CurPos = this.State.ContentPos; // Если выделено не до конца, тогда разделяем по последней точке if ( CurPos < this.Content.length ) { RRun = LRun.Split_Run(CurPos); RRun.Set_ReviewType(ReviewType); if (IsPrChange) RRun.Add_PrChange(); } if ( CurPos > 0 ) { CRun = LRun.Split_Run(CurPos); CRun.Set_ReviewType(ReviewType); if (IsPrChange) CRun.Add_PrChange(); } else { CRun = LRun; LRun = null; } if ( null !== LRun ) LRun.Selection_Remove(); CRun.Selection_Remove(); CRun.Cursor_MoveToStartPos(); if (true === bReview && true !== CRun.Have_PrChange()) CRun.Add_PrChange(); if ( undefined === IncFontSize ) { CRun.Apply_Pr( TextPr ); } else { var _TextPr = new CTextPr(); var CurTextPr = this.Get_CompiledPr( false ); CRun.private_AddCollPrChangeMine(); CRun.Set_FontSize( FontSize_IncreaseDecreaseValue( IncFontSize, CurTextPr.FontSize ) ); } if ( null !== RRun ) RRun.Selection_Remove(); } Result.push( LRun ); Result.push( CRun ); Result.push( RRun ); return Result; } }; ParaRun.prototype.Split_Run = function(Pos) { History.Add(this, {Type : historyitem_ParaRun_OnStartSplit, Pos : Pos}); CollaborativeEditing.OnStart_SplitRun(this, Pos); // Создаем новый ран var bMathRun = this.Type == para_Math_Run; var NewRun = new ParaRun(this.Paragraph, bMathRun); // Копируем настройки NewRun.Set_Pr(this.Pr.Copy(true)); if(bMathRun) NewRun.Set_MathPr(this.MathPrp.Copy()); var OldCrPos = this.State.ContentPos; var OldSSPos = this.State.Selection.StartPos; var OldSEPos = this.State.Selection.EndPos; // Разделяем содержимое по ранам NewRun.Concat_ToContent( this.Content.slice(Pos) ); this.Remove_FromContent( Pos, this.Content.length - Pos, true ); // Подправим точки селекта и текущей позиции if ( OldCrPos >= Pos ) { NewRun.State.ContentPos = OldCrPos - Pos; this.State.ContentPos = this.Content.length; } else { NewRun.State.ContentPos = 0; } if ( OldSSPos >= Pos ) { NewRun.State.Selection.StartPos = OldSSPos - Pos; this.State.Selection.StartPos = this.Content.length; } else { NewRun.State.Selection.StartPos = 0; } if ( OldSEPos >= Pos ) { NewRun.State.Selection.EndPos = OldSEPos - Pos; this.State.Selection.EndPos = this.Content.length; } else { NewRun.State.Selection.EndPos = 0; } // Если были точки орфографии, тогда переместим их в новый ран var SpellingMarksCount = this.SpellingMarks.length; for ( var Index = 0; Index < SpellingMarksCount; Index++ ) { var Mark = this.SpellingMarks[Index]; var MarkPos = ( true === Mark.Start ? Mark.Element.StartPos.Get(Mark.Depth) : Mark.Element.EndPos.Get(Mark.Depth) ); if ( MarkPos >= Pos ) { var MarkElement = Mark.Element; if ( true === Mark.Start ) { //MarkElement.ClassesS[Mark.Depth] = NewRun; MarkElement.StartPos.Data[Mark.Depth] -= Pos; } else { //MarkElement.ClassesE[Mark.Depth] = NewRun; MarkElement.EndPos.Data[Mark.Depth] -= Pos; } NewRun.SpellingMarks.push( Mark ); this.SpellingMarks.splice( Index, 1 ); SpellingMarksCount--; Index--; } } History.Add(this, {Type : historyitem_ParaRun_OnEndSplit, NewRun : NewRun}); CollaborativeEditing.OnEnd_SplitRun(NewRun); return NewRun; }; ParaRun.prototype.Clear_TextPr = function() { // Данная функция вызывается пока только при изменении стиля параграфа. Оставляем в этой ситуации язык неизмененным. var NewTextPr = new CTextPr(); NewTextPr.Lang = this.Pr.Lang.Copy(); this.Set_Pr( NewTextPr ); }; // В данной функции мы применяем приходящие настройки поверх старых, т.е. старые не удаляем ParaRun.prototype.Apply_Pr = function(TextPr) { this.private_AddCollPrChangeMine(); if(this.Type == para_Math_Run && false === this.IsNormalText()) { if(null === TextPr.Bold && null === TextPr.Italic) this.Math_Apply_Style(undefined); else { if(undefined != TextPr.Bold) { if(TextPr.Bold == true) { if(this.MathPrp.sty == STY_ITALIC || this.MathPrp.sty == undefined) this.Math_Apply_Style(STY_BI); else if(this.MathPrp.sty == STY_PLAIN) this.Math_Apply_Style(STY_BOLD); } else if(TextPr.Bold == false || TextPr.Bold == null) { if(this.MathPrp.sty == STY_BI || this.MathPrp.sty == undefined) this.Math_Apply_Style(STY_ITALIC); else if(this.MathPrp.sty == STY_BOLD) this.Math_Apply_Style(STY_PLAIN); } } if(undefined != TextPr.Italic) { if(TextPr.Italic == true) { if(this.MathPrp.sty == STY_BOLD) this.Math_Apply_Style(STY_BI); else if(this.MathPrp.sty == STY_PLAIN || this.MathPrp.sty == undefined) this.Math_Apply_Style(STY_ITALIC); } else if(TextPr.Italic == false || TextPr.Italic == null) { if(this.MathPrp.sty == STY_BI) this.Math_Apply_Style(STY_BOLD); else if(this.MathPrp.sty == STY_ITALIC || this.MathPrp.sty == undefined) this.Math_Apply_Style(STY_PLAIN); } } } } else { if ( undefined != TextPr.Bold ) this.Set_Bold( null === TextPr.Bold ? undefined : TextPr.Bold ); if( undefined != TextPr.Italic ) this.Set_Italic( null === TextPr.Italic ? undefined : TextPr.Italic ); } if ( undefined != TextPr.Strikeout ) this.Set_Strikeout( null === TextPr.Strikeout ? undefined : TextPr.Strikeout ); if ( undefined !== TextPr.Underline ) this.Set_Underline( null === TextPr.Underline ? undefined : TextPr.Underline ); if ( undefined != TextPr.FontSize ) this.Set_FontSize( null === TextPr.FontSize ? undefined : TextPr.FontSize ); if ( undefined !== TextPr.Color && undefined === TextPr.Unifill ) { this.Set_Color( null === TextPr.Color ? undefined : TextPr.Color ); this.Set_Unifill( undefined ); this.Set_TextFill(undefined); } if ( undefined !== TextPr.Unifill ) { this.Set_Unifill(null === TextPr.Unifill ? undefined : TextPr.Unifill); this.Set_Color(undefined); this.Set_TextFill(undefined); } else if(undefined !== TextPr.AscUnifill && this.Paragraph) { if(!this.Paragraph.bFromDocument) { var oCompiledPr = this.Get_CompiledPr(true); this.Set_Unifill(CorrectUniFill(TextPr.AscUnifill, oCompiledPr.Unifill, 0), isRealObject(TextPr.AscUnifill) && TextPr.AscUnifill.asc_CheckForseSet() ); this.Set_Color(undefined); this.Set_TextFill(undefined); } } if(undefined !== TextPr.TextFill) { this.Set_Unifill(undefined); this.Set_Color(undefined); this.Set_TextFill(null === TextPr.TextFill ? undefined : TextPr.TextFill); } else if(undefined !== TextPr.AscFill && this.Paragraph) { var oMergeUnifill, oColor; if(this.Paragraph.bFromDocument) { var oCompiledPr = this.Get_CompiledPr(true); if(oCompiledPr.TextFill) { oMergeUnifill = oCompiledPr.TextFill; } else if(oCompiledPr.Unifill) { oMergeUnifill = oCompiledPr.Unifill; } else if(oCompiledPr.Color) { oColor = oCompiledPr.Color; oMergeUnifill = CreateUnfilFromRGB(oColor.r, oColor.g, oColor.b); } this.Set_Unifill(undefined); this.Set_Color(undefined); this.Set_TextFill(CorrectUniFill(TextPr.AscFill, oMergeUnifill, 0), isRealObject(TextPr.AscFill) && TextPr.AscFill.asc_CheckForseSet()); } } if(undefined !== TextPr.TextOutline) { this.Set_TextOutline(null === TextPr.TextOutline ? undefined : TextPr.TextOutline); } else if(undefined !== TextPr.AscLine && this.Paragraph) { var oCompiledPr = this.Get_CompiledPr(true); this.Set_TextOutline(CorrectUniStroke(TextPr.AscLine, oCompiledPr.TextOutline, 0)); } if ( undefined != TextPr.VertAlign ) this.Set_VertAlign( null === TextPr.VertAlign ? undefined : TextPr.VertAlign ); if ( undefined != TextPr.HighLight ) this.Set_HighLight( null === TextPr.HighLight ? undefined : TextPr.HighLight ); if ( undefined !== TextPr.RStyle ) this.Set_RStyle( null === TextPr.RStyle ? undefined : TextPr.RStyle ); if ( undefined != TextPr.Spacing ) this.Set_Spacing( null === TextPr.Spacing ? undefined : TextPr.Spacing ); if ( undefined != TextPr.DStrikeout ) this.Set_DStrikeout( null === TextPr.DStrikeout ? undefined : TextPr.DStrikeout ); if ( undefined != TextPr.Caps ) this.Set_Caps( null === TextPr.Caps ? undefined : TextPr.Caps ); if ( undefined != TextPr.SmallCaps ) this.Set_SmallCaps( null === TextPr.SmallCaps ? undefined : TextPr.SmallCaps ); if ( undefined != TextPr.Position ) this.Set_Position( null === TextPr.Position ? undefined : TextPr.Position ); if ( undefined != TextPr.RFonts ) { if(this.Type == para_Math_Run && !this.IsNormalText()) // при смене Font в этом случае (даже на Cambria Math) cs, eastAsia не меняются { // только для редактирования // делаем так для проверки действительно ли нужно сменить Font, чтобы при смене других текстовых настроек не выставился Cambria Math (TextPr.RFonts приходит всегда в виде объекта) if(TextPr.RFonts.Ascii !== undefined || TextPr.RFonts.HAnsi !== undefined) { var RFonts = new CRFonts(); RFonts.Set_All("Cambria Math", -1); this.Set_RFonts2(RFonts); } } else this.Set_RFonts2(TextPr.RFonts); } if ( undefined != TextPr.Lang ) this.Set_Lang2( TextPr.Lang ); if ( undefined !== TextPr.Shd ) this.Set_Shd( TextPr.Shd ); }; ParaRun.prototype.Have_PrChange = function() { return this.Pr.Have_PrChange(); }; ParaRun.prototype.Add_PrChange = function() { if (false === this.Have_PrChange()) { this.Pr.Add_PrChange(); History.Add(this, {Type : historyitem_ParaRun_PrChange, New : {PrChange : this.Pr.PrChange, ReviewInfo : this.Pr.ReviewInfo}, Old : {PrChange : undefined, ReviewInfo : undefined}}); this.private_UpdateTrackRevisions(); } }; ParaRun.prototype.Set_PrChange = function(PrChange, ReviewInfo) { History.Add(this, {Type : historyitem_ParaRun_PrChange, New : {PrChange : PrChange, ReviewInfo : ReviewInfo ? ReviewInfo.Copy() : undefined}, Old : {PrChange : this.Pr.PrChange, ReviewInfo : this.Pr.ReviewInfo ? this.Pr.ReviewInfo.Copy() : undefined}}); this.Pr.Set_PrChange(PrChange, ReviewInfo); this.private_UpdateTrackRevisions(); }; ParaRun.prototype.Remove_PrChange = function() { if (true === this.Have_PrChange()) { History.Add(this, {Type : historyitem_ParaRun_PrChange, New : {PrChange : undefined, ReviewInfo : undefined}, Old : {PrChange : this.Pr.PrChange, ReviewInfo : this.Pr.ReviewInfo}}); this.Pr.Remove_PrChange(); this.private_UpdateTrackRevisions(); } }; ParaRun.prototype.Reject_PrChange = function() { if (true === this.Have_PrChange()) { this.Set_Pr(this.Pr.PrChange); this.Remove_PrChange(); } }; ParaRun.prototype.Accept_PrChange = function() { this.Remove_PrChange(); }; ParaRun.prototype.Get_DiffPrChange = function() { return this.Pr.Get_DiffPrChange(); }; ParaRun.prototype.Set_Bold = function(Value) { if ( Value !== this.Pr.Bold ) { var OldValue = this.Pr.Bold; this.Pr.Bold = Value; History.Add( this, { Type : historyitem_ParaRun_Bold, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_Bold = function() { return this.Get_CompiledPr(false).Bold; }; ParaRun.prototype.Set_Italic = function(Value) { if ( Value !== this.Pr.Italic ) { var OldValue = this.Pr.Italic; this.Pr.Italic = Value; History.Add( this, { Type : historyitem_ParaRun_Italic, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_Italic = function() { return this.Get_CompiledPr(false).Italic; }; ParaRun.prototype.Set_Strikeout = function(Value) { if ( Value !== this.Pr.Strikeout ) { var OldValue = this.Pr.Strikeout; this.Pr.Strikeout = Value; History.Add( this, { Type : historyitem_ParaRun_Strikeout, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_Strikeout = function() { return this.Get_CompiledPr(false).Strikeout; }; ParaRun.prototype.Set_Underline = function(Value) { if ( Value !== this.Pr.Underline ) { var OldValue = this.Pr.Underline; this.Pr.Underline = Value; History.Add( this, { Type : historyitem_ParaRun_Underline, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_Underline = function() { return this.Get_CompiledPr(false).Underline; }; ParaRun.prototype.Set_FontSize = function(Value) { if ( Value !== this.Pr.FontSize ) { var OldValue = this.Pr.FontSize; this.Pr.FontSize = Value; History.Add( this, { Type : historyitem_ParaRun_FontSize, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_FontSize = function() { return this.Get_CompiledPr(false).FontSize; }; ParaRun.prototype.Set_Color = function(Value) { if ( ( undefined === Value && undefined !== this.Pr.Color ) || ( Value instanceof CDocumentColor && ( undefined === this.Pr.Color || false === Value.Compare(this.Pr.Color) ) ) ) { var OldValue = this.Pr.Color; this.Pr.Color = Value; History.Add( this, { Type : historyitem_ParaRun_Color, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_Unifill = function(Value, bForce) { if ( ( undefined === Value && undefined !== this.Pr.Unifill ) || ( Value instanceof CUniFill && ( undefined === this.Pr.Unifill || false === CompareUnifillBool(this.Pr.Unifill, Value) ) ) || bForce ) { var OldValue = this.Pr.Unifill; this.Pr.Unifill = Value; History.Add( this, { Type : historyitem_ParaRun_Unifill, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_TextFill = function(Value, bForce) { if ( ( undefined === Value && undefined !== this.Pr.TextFill ) || ( Value instanceof CUniFill && ( undefined === this.Pr.TextFill || false === CompareUnifillBool(this.Pr.TextFill.IsIdentical, Value) ) ) || bForce ) { var OldValue = this.Pr.TextFill; this.Pr.TextFill = Value; History.Add( this, { Type : historyitem_ParaRun_TextFill, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_TextOutline = function(Value) { if ( ( undefined === Value && undefined !== this.Pr.TextOutline ) || ( Value instanceof CLn && ( undefined === this.Pr.TextOutline || false === this.Pr.TextOutline.IsIdentical(Value) ) ) ) { var OldValue = this.Pr.TextOutline; this.Pr.TextOutline = Value; History.Add( this, { Type : historyitem_ParaRun_TextOutline, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_Color = function() { return this.Get_CompiledPr(false).Color; }; ParaRun.prototype.Set_VertAlign = function(Value) { if ( Value !== this.Pr.VertAlign ) { var OldValue = this.Pr.VertAlign; this.Pr.VertAlign = Value; History.Add( this, { Type : historyitem_ParaRun_VertAlign, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_VertAlign = function() { return this.Get_CompiledPr(false).VertAlign; }; ParaRun.prototype.Set_HighLight = function(Value) { var OldValue = this.Pr.HighLight; if ( (undefined === Value && undefined !== OldValue) || ( highlight_None === Value && highlight_None !== OldValue ) || ( Value instanceof CDocumentColor && ( undefined === OldValue || highlight_None === OldValue || false === Value.Compare(OldValue) ) ) ) { this.Pr.HighLight = Value; History.Add( this, { Type : historyitem_ParaRun_HighLight, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_HighLight = function() { return this.Get_CompiledPr(false).HighLight; }; ParaRun.prototype.Set_RStyle = function(Value) { if ( Value !== this.Pr.RStyle ) { var OldValue = this.Pr.RStyle; this.Pr.RStyle = Value; History.Add( this, { Type : historyitem_ParaRun_RStyle, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_Spacing = function(Value) { if (Value !== this.Pr.Spacing) { var OldValue = this.Pr.Spacing; this.Pr.Spacing = Value; History.Add( this, { Type : historyitem_ParaRun_Spacing, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_Spacing = function() { return this.Get_CompiledPr(false).Spacing; }; ParaRun.prototype.Set_DStrikeout = function(Value) { if ( Value !== this.Pr.Value ) { var OldValue = this.Pr.DStrikeout; this.Pr.DStrikeout = Value; History.Add( this, { Type : historyitem_ParaRun_DStrikeout, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_DStrikeout = function() { return this.Get_CompiledPr(false).DStrikeout; }; ParaRun.prototype.Set_Caps = function(Value) { if ( Value !== this.Pr.Caps ) { var OldValue = this.Pr.Caps; this.Pr.Caps = Value; History.Add( this, { Type : historyitem_ParaRun_Caps, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_Caps = function() { return this.Get_CompiledPr(false).Caps; }; ParaRun.prototype.Set_SmallCaps = function(Value) { if ( Value !== this.Pr.SmallCaps ) { var OldValue = this.Pr.SmallCaps; this.Pr.SmallCaps = Value; History.Add( this, { Type : historyitem_ParaRun_SmallCaps, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Get_SmallCaps = function() { return this.Get_CompiledPr(false).SmallCaps; }; ParaRun.prototype.Set_Position = function(Value) { if ( Value !== this.Pr.Position ) { var OldValue = this.Pr.Position; this.Pr.Position = Value; History.Add( this, { Type : historyitem_ParaRun_Position, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); this.YOffset = this.Get_Position(); } }; ParaRun.prototype.Get_Position = function() { return this.Get_CompiledPr(false).Position; }; ParaRun.prototype.Set_RFonts = function(Value) { var OldValue = this.Pr.RFonts; this.Pr.RFonts = Value; History.Add( this, { Type : historyitem_ParaRun_RFonts, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); }; ParaRun.prototype.Get_RFonts = function() { return this.Get_CompiledPr(false).RFonts; }; ParaRun.prototype.Set_RFonts2 = function(RFonts) { if ( undefined != RFonts ) { if ( undefined != RFonts.Ascii ) this.Set_RFonts_Ascii( RFonts.Ascii ); if ( undefined != RFonts.HAnsi ) this.Set_RFonts_HAnsi( RFonts.HAnsi ); if ( undefined != RFonts.CS ) this.Set_RFonts_CS( RFonts.CS ); if ( undefined != RFonts.EastAsia ) this.Set_RFonts_EastAsia( RFonts.EastAsia ); if ( undefined != RFonts.Hint ) this.Set_RFonts_Hint( RFonts.Hint ); } else { this.Set_RFonts_Ascii( undefined ); this.Set_RFonts_HAnsi( undefined ); this.Set_RFonts_CS( undefined ); this.Set_RFonts_EastAsia( undefined ); this.Set_RFonts_Hint( undefined ); } }; ParaRun.prototype.Set_RFont_ForMathRun = function() { this.Set_RFonts_Ascii({Name : "Cambria Math", Index : -1}); this.Set_RFonts_CS({Name : "Cambria Math", Index : -1}); this.Set_RFonts_EastAsia({Name : "Cambria Math", Index : -1}); this.Set_RFonts_HAnsi({Name : "Cambria Math", Index : -1}); }; ParaRun.prototype.Set_RFonts_Ascii = function(Value) { if ( Value !== this.Pr.RFonts.Ascii ) { var OldValue = this.Pr.RFonts.Ascii; this.Pr.RFonts.Ascii = Value; History.Add( this, { Type : historyitem_ParaRun_RFonts_Ascii, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_RFonts_HAnsi = function(Value) { if ( Value !== this.Pr.RFonts.HAnsi ) { var OldValue = this.Pr.RFonts.HAnsi; this.Pr.RFonts.HAnsi = Value; History.Add( this, { Type : historyitem_ParaRun_RFonts_HAnsi, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_RFonts_CS = function(Value) { if ( Value !== this.Pr.RFonts.CS ) { var OldValue = this.Pr.RFonts.CS; this.Pr.RFonts.CS = Value; History.Add( this, { Type : historyitem_ParaRun_RFonts_CS, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_RFonts_EastAsia = function(Value) { if ( Value !== this.Pr.RFonts.EastAsia ) { var OldValue = this.Pr.RFonts.EastAsia; this.Pr.RFonts.EastAsia = Value; History.Add( this, { Type : historyitem_ParaRun_RFonts_EastAsia, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_RFonts_Hint = function(Value) { if ( Value !== this.Pr.RFonts.Hint ) { var OldValue = this.Pr.RFonts.Hint; this.Pr.RFonts.Hint = Value; History.Add( this, { Type : historyitem_ParaRun_RFonts_Hint, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_Lang = function(Value) { var OldValue = this.Pr.Lang; this.Pr.Lang = new CLang(); if ( undefined != Value ) this.Pr.Lang.Set_FromObject( Value ); History.Add( this, { Type : historyitem_ParaRun_Lang, New : this.Pr.Lang, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); }; ParaRun.prototype.Set_Lang2 = function(Lang) { if ( undefined != Lang ) { if ( undefined != Lang.Bidi ) this.Set_Lang_Bidi( Lang.Bidi ); if ( undefined != Lang.EastAsia ) this.Set_Lang_EastAsia( Lang.EastAsia ); if ( undefined != Lang.Val ) this.Set_Lang_Val( Lang.Val ); this.protected_UpdateSpellChecking(); } }; ParaRun.prototype.Set_Lang_Bidi = function(Value) { if ( Value !== this.Pr.Lang.Bidi ) { var OldValue = this.Pr.Lang.Bidi; this.Pr.Lang.Bidi = Value; History.Add( this, { Type : historyitem_ParaRun_Lang_Bidi, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_Lang_EastAsia = function(Value) { if ( Value !== this.Pr.Lang.EastAsia ) { var OldValue = this.Pr.Lang.EastAsia; this.Pr.Lang.EastAsia = Value; History.Add( this, { Type : historyitem_ParaRun_Lang_EastAsia, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_Lang_Val = function(Value) { if ( Value !== this.Pr.Lang.Val ) { var OldValue = this.Pr.Lang.Val; this.Pr.Lang.Val = Value; History.Add( this, { Type : historyitem_ParaRun_Lang_Val, New : Value, Old : OldValue, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.Set_Shd = function(Shd) { if ( (undefined === this.Pr.Shd && undefined === Shd) || (undefined !== this.Pr.Shd && undefined !== Shd && true === this.Pr.Shd.Compare( Shd ) ) ) return; var OldShd = this.Pr.Shd; if ( undefined !== Shd ) { this.Pr.Shd = new CDocumentShd(); this.Pr.Shd.Set_FromObject( Shd ); } else this.Pr.Shd = undefined; History.Add( this, { Type : historyitem_ParaRun_Shd, New : this.Pr.Shd, Old : OldShd, Color : this.private_IsCollPrChangeMine() } ); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(true); }; //----------------------------------------------------------------------------------- // Undo/Redo функции //----------------------------------------------------------------------------------- ParaRun.prototype.Undo = function(Data) { var Type = Data.Type; switch ( Type ) { case historyitem_ParaRun_AddItem : { this.Content.splice( Data.Pos, Data.EndPos - Data.Pos + 1 ); this.RecalcInfo.Measure = true; this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(false); break; } case historyitem_ParaRun_RemoveItem : { var Pos = Data.Pos; var Array_start = this.Content.slice( 0, Pos ); var Array_end = this.Content.slice( Pos ); this.Content = Array_start.concat( Data.Items, Array_end ); this.RecalcInfo.Measure = true; this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(false); break; } case historyitem_ParaRun_TextPr: { if ( undefined != Data.Old ) this.Pr = Data.Old; else this.Pr = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Bold: { if ( undefined != Data.Old ) this.Pr.Bold = Data.Old; else this.Pr.Bold = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Italic: { if ( undefined != Data.Old ) this.Pr.Italic = Data.Old; else this.Pr.Italic = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Strikeout: { if ( undefined != Data.Old ) this.Pr.Strikeout = Data.Old; else this.Pr.Strikeout = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Underline: { if ( undefined != Data.Old ) this.Pr.Underline = Data.Old; else this.Pr.Underline = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_FontSize: { if ( undefined != Data.Old ) this.Pr.FontSize = Data.Old; else this.Pr.FontSize = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Color: { if ( undefined != Data.Old ) this.Pr.Color = Data.Old; else this.Pr.Color = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Unifill: { if ( undefined != Data.Old ) this.Pr.Unifill = Data.Old; else this.Pr.Unifill = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_TextFill: { if ( undefined != Data.Old ) this.Pr.TextFill = Data.Old; else this.Pr.TextFill = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_TextOutline: { if ( undefined != Data.Old ) this.Pr.TextOutline = Data.Old; else this.Pr.TextOutline = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_VertAlign: { if ( undefined != Data.Old ) this.Pr.VertAlign = Data.Old; else this.Pr.VertAlign = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_HighLight: { if ( undefined != Data.Old ) this.Pr.HighLight = Data.Old; else this.Pr.HighLight = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RStyle: { if ( undefined != Data.Old ) this.Pr.RStyle = Data.Old; else this.Pr.RStyle = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Spacing: { if ( undefined != Data.Old ) this.Pr.Spacing = Data.Old; else this.Pr.Spacing = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_DStrikeout: { if ( undefined != Data.Old ) this.Pr.DStrikeout = Data.Old; else this.Pr.DStrikeout = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Caps: { if ( undefined != Data.Old ) this.Pr.Caps = Data.Old; else this.Pr.Caps = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_SmallCaps: { if ( undefined != Data.Old ) this.Pr.SmallCaps = Data.Old; else this.Pr.SmallCaps = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Position: { if ( undefined != Data.Old ) this.Pr.Position = Data.Old; else this.Pr.Position = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts: { if ( undefined != Data.Old ) this.Pr.RFonts = Data.Old; else this.Pr.RFonts = new CRFonts(); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_Ascii: { if ( undefined != Data.Old ) this.Pr.RFonts.Ascii = Data.Old; else this.Pr.RFonts.Ascii = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_HAnsi: { if ( undefined != Data.Old ) this.Pr.RFonts.HAnsi = Data.Old; else this.Pr.RFonts.HAnsi = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_CS: { if ( undefined != Data.Old ) this.Pr.RFonts.CS = Data.Old; else this.Pr.RFonts.CS = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_EastAsia: { if ( undefined != Data.Old ) this.Pr.RFonts.EastAsia = Data.Old; else this.Pr.RFonts.EastAsia = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_Hint: { if ( undefined != Data.Old ) this.Pr.RFonts.Hint = Data.Old; else this.Pr.RFonts.Hint = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang: { if ( undefined != Data.Old ) this.Pr.Lang = Data.Old; else this.Pr.Lang = new CLang(); this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_Bidi: { if ( undefined != Data.Old ) this.Pr.Lang.Bidi = Data.Old; else this.Pr.Lang.Bidi = undefined; this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_EastAsia: { if ( undefined != Data.Old ) this.Pr.Lang.EastAsia = Data.Old; else this.Pr.Lang.EastAsia = undefined; this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_Val: { if ( undefined != Data.Old ) this.Pr.Lang.Val = Data.Old; else this.Pr.Lang.Val = undefined; this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Shd: { this.Pr.Shd = Data.Old; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_MathStyle: { this.MathPrp.sty = Data.Old; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_MathPrp: { this.MathPrp = Data.Old; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_ReviewType: { this.ReviewType = Data.Old.ReviewType; this.ReviewInfo = Data.Old.ReviewInfo; this.private_UpdateTrackRevisions(); break; } case historyitem_ParaRun_PrChange: { this.Pr.PrChange = Data.Old.PrChange; this.Pr.ReviewInfo = Data.Old.ReviewInfo; this.private_UpdateTrackRevisions(); break; } case historyitem_ParaRun_ContentReviewInfo: { this.ReviewInfo = Data.Old; break; } case historyitem_ParaRun_PrReviewInfo: { this.Pr.ReviewInfo = Data.Old; break; } } }; ParaRun.prototype.Redo = function(Data) { var Type = Data.Type; switch ( Type ) { case historyitem_ParaRun_AddItem: { var Pos = Data.Pos; var Array_start = this.Content.slice( 0, Pos ); var Array_end = this.Content.slice( Pos ); this.Content = Array_start.concat( Data.Items, Array_end ); this.RecalcInfo.Measure = true; this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(false); break; } case historyitem_ParaRun_RemoveItem: { this.Content.splice( Data.Pos, Data.EndPos - Data.Pos + 1 ); this.RecalcInfo.Measure = true; this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(false); break; } case historyitem_ParaRun_TextPr: { if ( undefined != Data.New ) this.Pr = Data.New; else this.Pr = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Bold: { if ( undefined != Data.New ) this.Pr.Bold = Data.New; else this.Pr.Bold = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Italic: { if ( undefined != Data.New ) this.Pr.Italic = Data.New; else this.Pr.Italic = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Strikeout: { if ( undefined != Data.New ) this.Pr.Strikeout = Data.New; else this.Pr.Strikeout = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Underline: { if ( undefined != Data.New ) this.Pr.Underline = Data.New; else this.Pr.Underline = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_FontSize: { if ( undefined != Data.New ) this.Pr.FontSize = Data.New; else this.Pr.FontSize = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Color: { if ( undefined != Data.New ) this.Pr.Color = Data.New; else this.Pr.Color = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Unifill: { if ( undefined != Data.New ) this.Pr.Unifill = Data.New; else this.Pr.Unifill = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_TextFill: { if ( undefined != Data.New ) this.Pr.TextFill = Data.New; else this.Pr.TextFill = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_TextOutline: { if ( undefined != Data.New ) this.Pr.TextOutline = Data.New; else this.Pr.TextOutline = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_VertAlign: { if ( undefined != Data.New ) this.Pr.VertAlign = Data.New; else this.Pr.VertAlign = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_HighLight: { if ( undefined != Data.New ) this.Pr.HighLight = Data.New; else this.Pr.HighLight = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RStyle: { if ( undefined != Data.New ) this.Pr.RStyle = Data.New; else this.Pr.RStyle = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Spacing: { if ( undefined != Data.New ) this.Pr.Spacing = Data.New; else this.Pr.Spacing = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_DStrikeout: { if ( undefined != Data.New ) this.Pr.DStrikeout = Data.New; else this.Pr.DStrikeout = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Caps: { if ( undefined != Data.New ) this.Pr.Caps = Data.New; else this.Pr.Caps = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_SmallCaps: { if ( undefined != Data.New ) this.Pr.SmallCaps = Data.New; else this.Pr.SmallCaps = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Position: { if ( undefined != Data.New ) this.Pr.Position = Data.New; else this.Pr.Position = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts: { if ( undefined != Data.New ) this.Pr.RFonts = Data.New; else this.Pr.RFonts = new CRFonts(); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_Ascii: { if ( undefined != Data.New ) this.Pr.RFonts.Ascii = Data.New; else this.Pr.RFonts.Ascii = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_HAnsi: { if ( undefined != Data.New ) this.Pr.RFonts.HAnsi = Data.New; else this.Pr.RFonts.HAnsi = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_CS: { if ( undefined != Data.New ) this.Pr.RFonts.CS = Data.New; else this.Pr.RFonts.CS = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_EastAsia: { if ( undefined != Data.New ) this.Pr.RFonts.EastAsia = Data.New; else this.Pr.RFonts.EastAsia = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_Hint: { if ( undefined != Data.New ) this.Pr.RFonts.Hint = Data.New; else this.Pr.RFonts.Hint = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang: { if ( undefined != Data.New ) this.Pr.Lang = Data.New; else this.Pr.Lang = new CLang(); this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_Bidi: { if ( undefined != Data.New ) this.Pr.Lang.Bidi = Data.New; else this.Pr.Lang.Bidi = undefined; this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_EastAsia: { if ( undefined != Data.New ) this.Pr.Lang.EastAsia = Data.New; else this.Pr.Lang.EastAsia = undefined; this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_Val: { if ( undefined != Data.New ) this.Pr.Lang.Val = Data.New; else this.Pr.Lang.Val = undefined; this.Recalc_CompiledPr(false); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Shd: { this.Pr.Shd = Data.New; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_MathStyle: { this.MathPrp.sty = Data.New; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_MathPrp: { this.MathPrp = Data.New; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_ReviewType: { this.ReviewType = Data.New.ReviewType; this.ReviewInfo = Data.New.ReviewInfo; this.private_UpdateTrackRevisions(); break; } case historyitem_ParaRun_PrChange: { this.Pr.PrChange = Data.New.PrChange; this.Pr.ReviewInfo = Data.New.ReviewInfo; this.private_UpdateTrackRevisions(); break; } case historyitem_ParaRun_ContentReviewInfo: { this.ReviewInfo = Data.New; break; } case historyitem_ParaRun_PrReviewInfo: { this.Pr.ReviewInfo = Data.New; break; } } }; ParaRun.prototype.Check_HistoryUninon = function(Data1, Data2) { var Type1 = Data1.Type; var Type2 = Data2.Type; if ( historyitem_ParaRun_AddItem === Type1 && historyitem_ParaRun_AddItem === Type2 ) { if ( 1 === Data1.Items.length && 1 === Data2.Items.length && Data1.Pos === Data2.Pos - 1 && para_Text === Data1.Items[0].Type && para_Text === Data2.Items[0].Type ) return true; } return false; }; //----------------------------------------------------------------------------------- // Функции для совместного редактирования //----------------------------------------------------------------------------------- ParaRun.prototype.Save_Changes = function(Data, Writer) { // Сохраняем изменения из тех, которые используются для Undo/Redo в бинарный файл. // Long : тип класса // Long : тип изменений Writer.WriteLong( historyitem_type_ParaRun ); var Type = Data.Type; // Пишем тип Writer.WriteLong( Type ); switch ( Type ) { case historyitem_ParaRun_AddItem: { // Bool : Подсвечивать ли данные изменения // Long : Количество элементов // Array of : // { // Long : Позиция // Variable : Элемент // } var bArray = Data.UseArray; var Count = Data.Items.length; if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); Writer.WriteLong( Count ); for ( var Index = 0; Index < Count; Index++ ) { if ( true === bArray ) Writer.WriteLong( Data.PosArray[Index] ); else Writer.WriteLong( Data.Pos + Index ); Data.Items[Index].Write_ToBinary(Writer); } break; } case historyitem_ParaRun_RemoveItem: { // Long : Количество удаляемых элементов // Array of Long : позиции удаляемых элементов var bArray = Data.UseArray; var Count = Data.Items.length; var StartPos = Writer.GetCurPosition(); Writer.Skip(4); var RealCount = Count; for ( var Index = 0; Index < Count; Index++ ) { if ( true === bArray ) { if ( false === Data.PosArray[Index] ) RealCount--; else Writer.WriteLong( Data.PosArray[Index] ); } else Writer.WriteLong( Data.Pos ); } var EndPos = Writer.GetCurPosition(); Writer.Seek( StartPos ); Writer.WriteLong( RealCount ); Writer.Seek( EndPos ); break; } case historyitem_ParaRun_TextPr: { // Bool : Подсвечивать ли данные изменения // CTextPr if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); this.Pr.Write_ToBinary( Writer ); break; } case historyitem_ParaRun_Bold: case historyitem_ParaRun_Italic: case historyitem_ParaRun_Strikeout: case historyitem_ParaRun_Underline: { // Bool : Подсвечивать ли данные изменения // Bool : IsUndefined // Bool : Value if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteBool( Data.New ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_FontSize: { // Bool : Подсвечивать ли данные изменения // Bool : IsUndefined // Double : FontSize if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool(false); Writer.WriteDouble( Data.New ); } else Writer.WriteBool(true); break; } case historyitem_ParaRun_Color: { // Bool : Подсвечивать ли данные изменения // Bool : IsUndefined // Variable : Color (CDocumentColor) if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool(false); Data.New.Write_ToBinary( Writer ); } else Writer.WriteBool(true); break; } case historyitem_ParaRun_Unifill: case historyitem_ParaRun_TextFill: case historyitem_ParaRun_TextOutline: { if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool(false); Data.New.Write_ToBinary( Writer ); } else Writer.WriteBool(true); break; } case historyitem_ParaRun_VertAlign: { // Bool : IsUndefined // Long : VertAlign if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool(false); Writer.WriteLong(Data.New); } else Writer.WriteBool(true); break; } case historyitem_ParaRun_HighLight: { // Bool : IsUndefined // Если false // Bool : IsNone // Если false // Variable : Color (CDocumentColor) if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool(false); if ( highlight_None != Data.New ) { Writer.WriteBool( false ); Data.New.Write_ToBinary( Writer ); } else Writer.WriteBool( true ); } else Writer.WriteBool(true); break; } case historyitem_ParaRun_RStyle: { // Bool : IsUndefined // Если false // String : RStyle if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteString2( Data.New ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_Spacing: case historyitem_ParaRun_Position: { // Bool : IsUndefined // Если false // Double : Spacing if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteDouble( Data.New ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_DStrikeout: case historyitem_ParaRun_Caps: case historyitem_ParaRun_SmallCaps: { // Bool : IsUndefined // Если false // Bool : value if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteBool( Data.New ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_RFonts: { // Bool : undefined ? // false -> CRFonts if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Data.New.Write_ToBinary( Writer ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_RFonts_Ascii: case historyitem_ParaRun_RFonts_HAnsi: case historyitem_ParaRun_RFonts_CS: case historyitem_ParaRun_RFonts_EastAsia: { // Bool : undefined? // false -> String if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteString2( Data.New.Name ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_RFonts_Hint: { // Bool : undefined? // false -> Long if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteLong( Data.New ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_Lang: { // Bool : undefined ? // false -> CLang if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Data.New.Write_ToBinary( Writer ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_Lang_Bidi: case historyitem_ParaRun_Lang_EastAsia: case historyitem_ParaRun_Lang_Val: { // Bool : undefined ? // false -> Long if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteLong( Data.New ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_Shd: { // Bool : undefined // false - > // Variable : CDocumentShd if (false === Data.Color) Writer.WriteBool(false); else Writer.WriteBool(true); if ( undefined !== Data.New ) { Writer.WriteBool(false); Data.New.Write_ToBinary(Writer); } else Writer.WriteBool(true); break; } case historyitem_ParaRun_MathStyle: { // Bool : undefined ? // false -> Long if ( undefined != Data.New ) { Writer.WriteBool( false ); Writer.WriteLong( Data.New ); } else Writer.WriteBool( true ); break; } case historyitem_ParaRun_MathPrp: { var StartPos = Writer.GetCurPosition(); Writer.Skip(4); var Flags = 0; if ( undefined != this.MathPrp.aln ) { Writer.WriteBool( this.MathPrp.aln ); Flags |= 1; } if ( undefined != this.MathPrp.brk ) { this.MathPrp.brk.Write_ToBinary(Writer); Flags |= 2; } if ( undefined != this.MathPrp.lit ) { Writer.WriteBool( this.MathPrp.lit ); Flags |= 4; } if ( undefined != this.MathPrp.nor ) { Writer.WriteBool( this.MathPrp.nor ); Flags |= 8; } if ( undefined != this.MathPrp.scr ) { Writer.WriteLong( this.MathPrp.scr ); Flags |= 16; } if ( undefined != this.MathPrp.sty ) { Writer.WriteLong( this.MathPrp.sty ); Flags |= 32; } var EndPos = Writer.GetCurPosition(); Writer.Seek( StartPos ); Writer.WriteLong( Flags ); Writer.Seek( EndPos ); break; } case historyitem_ParaRun_ReviewType: { // Long : ReviewType // CReviewInfo : ReviewInfo Writer.WriteLong(Data.New.ReviewType); Data.New.ReviewInfo.Write_ToBinary(Writer); break; } case historyitem_ParaRun_PrChange: { // Bool : is undefined ? // false -> TextPr // Bool : is undefined ? // false -> ReviewInfo if (undefined === Data.New.PrChange) { Writer.WriteBool(true); } else { Writer.WriteBool(false); Data.New.PrChange.Write_ToBinary(Writer); } if (undefined === Data.New.ReviewInfo) { Writer.WriteBool(true); } else { Writer.WriteBool(false); Data.New.ReviewInfo.Write_ToBinary(Writer); } break; } case historyitem_ParaRun_ContentReviewInfo: { // Bool : is undefined ? // false -> ReviewInfo if (undefined === Data.New) { Writer.WriteBool(true); } else { Writer.WriteBool(false); Data.New.Write_ToBinary(Writer); } break; } case historyitem_ParaRun_PrReviewInfo: { // Bool : is undefined ? // false -> ReviewInfo if (undefined === Data.New) { Writer.WriteBool(true); } else { Writer.WriteBool(false); Data.New.Write_ToBinary(Writer); } break; } case historyitem_ParaRun_OnStartSplit: { Writer.WriteLong(Data.Pos); break; } case historyitem_ParaRun_OnEndSplit: { Writer.WriteString2(Data.NewRun.Get_Id()); break; } } return Writer; }; ParaRun.prototype.Load_Changes = function(Reader, Reader2, Color) { // Сохраняем изменения из тех, которые используются для Undo/Redo в бинарный файл. // Long : тип класса // Long : тип изменений var ClassType = Reader.GetLong(); if ( historyitem_type_ParaRun != ClassType ) return; var Type = Reader.GetLong(); var bColorPrChange = false; switch ( Type ) { case historyitem_ParaRun_AddItem : { // Bool : Подсвечивать ли данные изменения // Long : Количество элементов // Array of : // { // Long : Позиция // Variable : Id Элемента // } var bColorChanges = Reader.GetBool(); var Count = Reader.GetLong(); for ( var Index = 0; Index < Count; Index++ ) { var Pos = this.m_oContentChanges.Check( contentchanges_Add, Reader.GetLong() ); var Element = ParagraphContent_Read_FromBinary(Reader); if ( null != Element ) { if (true === bColorChanges && null !== Color) { this.CollaborativeMarks.Update_OnAdd( Pos ); this.CollaborativeMarks.Add( Pos, Pos + 1, Color ); CollaborativeEditing.Add_ChangedClass(this); } this.Content.splice(Pos, 0, Element); this.private_UpdatePositionsOnAdd(Pos); CollaborativeEditing.Update_DocumentPositionsOnAdd(this, Pos); } } this.RecalcInfo.Measure = true; this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(false); break; } case historyitem_ParaRun_RemoveItem: { // Long : Количество удаляемых элементов // Array of Long : позиции удаляемых элементов var Count = Reader.GetLong(); for ( var Index = 0; Index < Count; Index++ ) { var ChangesPos = this.m_oContentChanges.Check(contentchanges_Remove, Reader.GetLong()); // действие совпало, не делаем его if (false === ChangesPos) continue; this.CollaborativeMarks.Update_OnRemove(ChangesPos, 1); this.Content.splice(ChangesPos, 1); this.private_UpdatePositionsOnRemove(ChangesPos, 1); CollaborativeEditing.Update_DocumentPositionsOnRemove(this, ChangesPos, 1); } this.RecalcInfo.Measure = true; this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeContent(false); break; } case historyitem_ParaRun_TextPr: { // CTextPr bColorPrChange = Reader.GetBool(); this.Pr = new CTextPr(); this.Pr.Read_FromBinary( Reader ); var unifill = this.Pr.Unifill; if(typeof CollaborativeEditing !== "undefined") { if(unifill && unifill.fill && unifill.fill.type === FILL_TYPE_BLIP && typeof unifill.fill.RasterImageId === "string" && unifill.fill.RasterImageId.length > 0) { CollaborativeEditing.Add_NewImage(getFullImageSrc2(unifill.fill.RasterImageId)); } } this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Bold: { // Bool : IsUndefined // Bool : Bold bColorPrChange = Reader.GetBool(); if ( true === Reader.GetBool() ) this.Pr.Bold = undefined; else this.Pr.Bold = Reader.GetBool(); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Italic: { // Bool : IsUndefined // Bool : Italic bColorPrChange = Reader.GetBool(); if ( true === Reader.GetBool() ) this.Pr.Italic = undefined; else this.Pr.Italic = Reader.GetBool(); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Strikeout: { // Bool : IsUndefined // Bool : Strikeout bColorPrChange = Reader.GetBool(); if ( true === Reader.GetBool() ) this.Pr.Strikeout = undefined; else this.Pr.Strikeout = Reader.GetBool(); this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Underline: { // Bool : IsUndefined? // Bool : Underline bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.Underline = Reader.GetBool(); else this.Pr.Underline = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_FontSize: { // Bool : IsUndefined // Double : FontSize bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.FontSize = Reader.GetDouble(); else this.Pr.FontSize = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Color: { // Bool : IsUndefined // Variable : Color (CDocumentColor) bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) { this.Pr.Color = new CDocumentColor(0, 0, 0, false); this.Pr.Color.Read_FromBinary(Reader); } else this.Pr.Color = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Unifill: { bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) { var unifill = new CUniFill(); unifill.Read_FromBinary(Reader); this.Pr.Unifill = unifill; if(typeof CollaborativeEditing !== "undefined") { if(unifill.fill && unifill.fill.type === FILL_TYPE_BLIP && typeof unifill.fill.RasterImageId === "string" && unifill.fill.RasterImageId.length > 0) { CollaborativeEditing.Add_NewImage(getFullImageSrc2(unifill.fill.RasterImageId)); } } } else this.Pr.Unifill = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_TextFill: { bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) { var unifill = new CUniFill(); unifill.Read_FromBinary(Reader); this.Pr.TextFill = unifill; } else this.Pr.TextFill = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_TextOutline: { bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) { var ln = new CLn(); ln.Read_FromBinary(Reader); this.Pr.TextOutline = ln; } else this.Pr.TextOutline = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_VertAlign: { // Bool : IsUndefined // Long : VertAlign bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.VertAlign = Reader.GetLong(); else this.Pr.VertAlign = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_HighLight: { // Bool : IsUndefined // Если false // Bool : IsNull // Если false // Variable : Color (CDocumentColor) bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) { if ( true != Reader.GetBool() ) { this.Pr.HighLight = new CDocumentColor(0,0,0); this.Pr.HighLight.Read_FromBinary(Reader); } else this.Pr.HighLight = highlight_None; } else this.Pr.HighLight = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RStyle: { // Bool : IsUndefined // Если false // String : RStyle bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.RStyle = Reader.GetString2(); else this.Pr.RStyle = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Spacing: { // Bool : IsUndefined // Если false // Double : Spacing bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.Spacing = Reader.GetDouble(); else this.Pr.Spacing = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_DStrikeout: { // Bool : IsUndefined // Если false // Bool : DStrikeout bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.DStrikeout = Reader.GetBool(); else this.Pr.DStrikeout = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Caps: { // Bool : IsUndefined // Если false // Bool : Caps bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.Caps = Reader.GetBool(); else this.Pr.Caps = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_SmallCaps: { // Bool : IsUndefined // Если false // Bool : SmallCaps bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.SmallCaps = Reader.GetBool(); else this.Pr.SmallCaps = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Position: { // Bool : IsUndefined // Если false // Double : Position bColorPrChange = Reader.GetBool(); if ( true != Reader.GetBool() ) this.Pr.Position = Reader.GetDouble(); else this.Pr.Position = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts: { // Bool : undefined ? // false -> CRFonts bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) { this.Pr.RFonts = new CRFonts(); this.Pr.RFonts.Read_FromBinary( Reader ); } else this.Pr.RFonts = new CRFonts(); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_Ascii: { // Bool : undefined ? // false -> String bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) { this.Pr.RFonts.Ascii = { Name : Reader.GetString2(), Index : -1 }; } else this.Pr.RFonts.Ascii = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_HAnsi: { // Bool : undefined ? // false -> String bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) { this.Pr.RFonts.HAnsi = { Name : Reader.GetString2(), Index : -1 }; } else this.Pr.RFonts.HAnsi = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_CS: { // Bool : undefined ? // false -> String bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) { this.Pr.RFonts.CS = { Name : Reader.GetString2(), Index : -1 }; } else this.Pr.RFonts.CS = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_EastAsia: { // Bool : undefined ? // false -> String bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) { this.Pr.RFonts.EastAsia = { Name : Reader.GetString2(), Index : -1 }; } else this.Pr.RFonts.EastAsia = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_RFonts_Hint: { // Bool : undefined ? // false -> Long bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) this.Pr.RFonts.Hint = Reader.GetLong(); else this.Pr.RFonts.Hint = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang: { // Bool : undefined ? // false -> Lang bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) { this.Pr.Lang = new CLang(); this.Pr.Lang.Read_FromBinary( Reader ); } else this.Pr.Lang = new CLang(); this.Recalc_CompiledPr(true); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_Bidi: { // Bool : undefined ? // false -> Long bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) this.Pr.Lang.Bidi = Reader.GetLong(); else this.Pr.Lang.Bidi = undefined; this.Recalc_CompiledPr(true); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_EastAsia: { // Bool : undefined ? // false -> Long bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) this.Pr.Lang.EastAsia = Reader.GetLong(); else this.Pr.Lang.EastAsia = undefined; this.Recalc_CompiledPr(true); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Lang_Val: { // Bool : undefined ? // false -> Long bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) this.Pr.Lang.Val = Reader.GetLong(); else this.Pr.Lang.Val = undefined; this.Recalc_CompiledPr(true); this.protected_UpdateSpellChecking(); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_Shd: { // Bool : undefined // false - > // Variable : CDocumentShd bColorPrChange = Reader.GetBool(); if ( false === Reader.GetBool() ) { this.Pr.Shd = new CDocumentShd(); this.Pr.Shd.Read_FromBinary( Reader ); } else this.Pr.Shd = undefined; this.Recalc_CompiledPr(false); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_MathStyle: { // Bool : undefined ? // false -> Long if ( false === Reader.GetBool() ) this.MathPrp.sty = Reader.GetLong(); else this.MathPrp.sty = undefined; this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_MathPrp: { var Flags = Reader.GetLong(); if ( Flags & 1 ) this.MathPrp.aln = Reader.GetBool(); if ( Flags & 2 ) { this.MathPrp.brk = new CMathBreak(); this.MathPrp.brk.Read_FromBinary(Reader); } if ( Flags & 4 ) this.MathPrp.lit = Reader.GetBool(); if ( Flags & 8 ) this.MathPrp.nor = Reader.GetBool(); if ( Flags & 16 ) this.MathPrp.scr = Reader.GetLong(); if ( Flags & 32 ) this.MathPrp.sty = Reader.GetLong(); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(false); break; } case historyitem_ParaRun_ReviewType: { // Long : ReviewType // CReviewInfo : ReviewInfo this.ReviewType = Reader.GetLong(); this.ReviewInfo.Read_FromBinary(Reader); this.private_UpdateTrackRevisions(); break; } case historyitem_ParaRun_PrChange: { // Bool : is undefined ? // false -> TextPr // Bool : is undefined ? // false -> ReviewInfo if (false === Reader.GetBool()) { this.Pr.PrChange = new CTextPr(); this.Pr.PrChange.Read_FromBinary(Reader); } if (false === Reader.GetBool()) { this.Pr.ReviewInfo = new CReviewInfo(); this.Pr.ReviewInfo.Read_FromBinary(Reader); } this.private_UpdateTrackRevisions(); break; } case historyitem_ParaRun_ContentReviewInfo: { // Bool : is undefined ? // false -> ReviewInfo if (false === Reader.GetBool()) { this.ReviewInfo = new CReviewInfo(); this.ReviewInfo.Read_FromBinary(Reader); } break; } case historyitem_ParaRun_PrReviewInfo: { // Bool : is undefined ? // false -> ReviewInfo if (false === Reader.GetBool()) { this.ReviewInfo = new CReviewInfo(); this.ReviewInfo.Read_FromBinary(Reader); } else { this.ReviewInfo = undefined; } break; } case historyitem_ParaRun_OnStartSplit: { // Long var Pos = Reader.GetLong(); CollaborativeEditing.OnStart_SplitRun(this, Pos); break; } case historyitem_ParaRun_OnEndSplit: { // String2 var RunId = Reader.GetString2(); CollaborativeEditing.OnEnd_SplitRun(g_oTableId.Get_ById(RunId)); break; } } if (bColorPrChange && Color) { this.private_AddCollPrChangeOther(Color); } }; ParaRun.prototype.Write_ToBinary2 = function(Writer) { Writer.WriteLong( historyitem_type_ParaRun ); // Long : Type // String : Id // String : Paragraph Id // Variable : CTextPr // Long : ReviewType // Long : Количество элементов // Array of variable : массив с элементами Writer.WriteLong(this.Type); var ParagraphToWrite, PrToWrite, ContentToWrite; if(this.StartState) { ParagraphToWrite = this.StartState.Paragraph; PrToWrite = this.StartState.Pr; ContentToWrite = this.StartState.Content; } else { ParagraphToWrite = this.Paragraph; PrToWrite = this.Pr; ContentToWrite = this.Content; } Writer.WriteString2( this.Id ); Writer.WriteString2( null !== ParagraphToWrite && undefined !== ParagraphToWrite ? ParagraphToWrite.Get_Id() : "" ); PrToWrite.Write_ToBinary( Writer ); Writer.WriteLong(this.ReviewType); var Count = ContentToWrite.length; Writer.WriteLong( Count ); for ( var Index = 0; Index < Count; Index++ ) { var Item = ContentToWrite[Index]; Item.Write_ToBinary( Writer ); } }; ParaRun.prototype.Read_FromBinary2 = function(Reader) { // Long : Type // String : Id // String : Paragraph Id // Variable : CTextPr // Long : ReviewType // Long : Количество элементов // Array of variable : массив с элементами this.Type = Reader.GetLong(); this.Id = Reader.GetString2(); this.Paragraph = g_oTableId.Get_ById( Reader.GetString2() ); this.Pr = new CTextPr(); this.Pr.Read_FromBinary( Reader ); this.ReviewType = Reader.GetLong(); if (para_Math_Run == this.Type) { this.MathPrp = new CMPrp(); this.size = new CMathSize(); this.pos = new CMathPosition(); } if(undefined !== editor && true === editor.isDocumentEditor) { var Count = Reader.GetLong(); this.Content = []; for ( var Index = 0; Index < Count; Index++ ) { var Element = ParagraphContent_Read_FromBinary( Reader ); if ( null !== Element ) this.Content.push( Element ); } } }; ParaRun.prototype.Clear_CollaborativeMarks = function() { this.CollaborativeMarks.Clear(); this.CollPrChangeOther = false; }; ParaRun.prototype.private_AddCollPrChangeMine = function() { this.CollPrChangeMine = true; this.CollPrChangeOther = false; }; ParaRun.prototype.private_IsCollPrChangeMine = function() { if (true === this.CollPrChangeMine) return true; return false; }; ParaRun.prototype.private_AddCollPrChangeOther = function(Color) { this.CollPrChangeOther = Color; CollaborativeEditing.Add_ChangedClass(this); }; ParaRun.prototype.private_GetCollPrChangeOther = function() { return this.CollPrChangeOther; }; ParaRun.prototype.private_RecalcCtrPrp = function() { if (para_Math_Run === this.Type && undefined !== this.Parent && null !== this.Parent && null !== this.Parent.ParaMath) this.Parent.ParaMath.SetRecalcCtrPrp(this); }; function CParaRunSelection() { this.Use = false; this.StartPos = 0; this.EndPos = 0; } function CParaRunState() { this.Selection = new CParaRunSelection(); this.ContentPos = 0; } function CParaRunRecalcInfo() { this.TextPr = true; // Нужно ли пересчитать скомпилированные настройки this.Measure = true; // Нужно ли перемерять элементы this.Recalc = true; // Нужно ли пересчитывать (только если текстовый ран) this.RunLen = 0; // Далее идут параметры, которые выставляются после пересчета данного Range, такие как пересчитывать ли нумерацию this.NumberingItem = null; this.NumberingUse = false; // Используется ли нумерация в данном ране this.NumberingAdd = true; // Нужно ли в следующем ране использовать нумерацию } CParaRunRecalcInfo.prototype = { Reset : function() { this.TextPr = true; this.Measure = true; this.Recalc = true; this.RunLen = 0; } }; function CParaRunRange(StartPos, EndPos) { this.StartPos = StartPos; // Начальная позиция в контенте, с которой начинается данный отрезок this.EndPos = EndPos; // Конечная позиция в контенте, на которой заканчивается данный отрезок (перед которой) } function CParaRunLine() { this.Ranges = []; this.Ranges[0] = new CParaRunRange( 0, 0 ); this.RangesLength = 0; } CParaRunLine.prototype = { Add_Range : function(RangeIndex, StartPos, EndPos) { if ( 0 !== RangeIndex ) { this.Ranges[RangeIndex] = new CParaRunRange( StartPos, EndPos ); this.RangesLength = RangeIndex + 1; } else { this.Ranges[0].StartPos = StartPos; this.Ranges[0].EndPos = EndPos; this.RangesLength = 1; } if ( this.Ranges.length > this.RangesLength ) this.Ranges.legth = this.RangesLength; }, Copy : function() { var NewLine = new CParaRunLine(); NewLine.RangesLength = this.RangesLength; for ( var CurRange = 0; CurRange < this.RangesLength; CurRange++ ) { var Range = this.Ranges[CurRange]; NewLine.Ranges[CurRange] = new CParaRunRange( Range.StartPos, Range.EndPos ); } return NewLine; }, Compare : function(OtherLine, CurRange) { // Сначала проверим наличие данного отрезка в обеих строках if ( this.RangesLength <= CurRange || OtherLine.RangesLength <= CurRange ) return false; var OtherRange = OtherLine.Ranges[CurRange]; var ThisRange = this.Ranges[CurRange]; if ( OtherRange.StartPos !== ThisRange.StartPos || OtherRange.EndPos !== ThisRange.EndPos ) return false; return true; } }; // Метка о конце или начале изменений пришедших от других соавторов документа var pararun_CollaborativeMark_Start = 0x00; var pararun_CollaborativeMark_End = 0x01; function CParaRunCollaborativeMark(Pos, Type) { this.Pos = Pos; this.Type = Type; } function FontSize_IncreaseDecreaseValue(bIncrease, Value) { // Закон изменения размеров : // 1. Если значение меньше 8, тогда мы увеличиваем/уменьшаем по 1 (от 1 до 8) // 2. Если значение больше 72, тогда мы увеличиваем/уменьшаем по 10 (от 80 до бесконечности // 3. Если значение в отрезке [8,72], тогда мы переходим по следующим числам 8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72 var Sizes = [8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72]; var NewValue = Value; if ( true === bIncrease ) { if ( Value < Sizes[0] ) { if ( Value >= Sizes[0] - 1 ) NewValue = Sizes[0]; else NewValue = Math.floor(Value + 1); } else if ( Value >= Sizes[Sizes.length - 1] ) { NewValue = Math.min( 300, Math.floor( Value / 10 + 1 ) * 10 ); } else { for ( var Index = 0; Index < Sizes.length; Index++ ) { if ( Value < Sizes[Index] ) { NewValue = Sizes[Index]; break; } } } } else { if ( Value <= Sizes[0] ) { NewValue = Math.max( Math.floor( Value - 1 ), 1 ); } else if ( Value > Sizes[Sizes.length - 1] ) { if ( Value <= Math.floor( Sizes[Sizes.length - 1] / 10 + 1 ) * 10 ) NewValue = Sizes[Sizes.length - 1]; else NewValue = Math.floor( Math.ceil(Value / 10) - 1 ) * 10; } else { for ( var Index = Sizes.length - 1; Index >= 0; Index-- ) { if ( Value > Sizes[Index] ) { NewValue = Sizes[Index]; break; } } } } return NewValue; } function CRunCollaborativeMarks() { this.Ranges = []; this.DrawingObj = {}; } CRunCollaborativeMarks.prototype = { Add : function(PosS, PosE, Color) { var Count = this.Ranges.length; for ( var Index = 0; Index < Count; Index++ ) { var Range = this.Ranges[Index]; if ( PosS > Range.PosE ) continue; else if ( PosS >= Range.PosS && PosS <= Range.PosE && PosE >= Range.PosS && PosE <= Range.PosE ) { if ( true !== Color.Compare(Range.Color) ) { var _PosE = Range.PosE; Range.PosE = PosS; this.Ranges.splice( Index + 1, 0, new CRunCollaborativeRange(PosS, PosE, Color) ); this.Ranges.splice( Index + 2, 0, new CRunCollaborativeRange(PosE, _PosE, Range.Color) ); } return; } else if ( PosE < Range.PosS ) { this.Ranges.splice( Index, 0, new CRunCollaborativeRange(PosS, PosE, Color) ); return; } else if ( PosS < Range.PosS && PosE > Range.PosE ) { Range.PosS = PosS; Range.PosE = PosE; Range.Color = Color; return; } else if ( PosS < Range.PosS ) // && PosE <= Range.PosE ) { if ( true === Color.Compare(Range.Color) ) Range.PosS = PosS; else { Range.PosS = PosE; this.Ranges.splice( Index, 0, new CRunCollaborativeRange(PosS, PosE, Color) ); } return; } else //if ( PosS >= Range.PosS && PosE > Range.Pos.E ) { if ( true === Color.Compare(Range.Color) ) Range.PosE = PosE; else { Range.PosE = PosS; this.Ranges.splice( Index + 1, 0, new CRunCollaborativeRange(PosS, PosE, Color) ); } return; } } this.Ranges.push( new CRunCollaborativeRange(PosS, PosE, Color) ); }, Update_OnAdd : function(Pos) { var Count = this.Ranges.length; for ( var Index = 0; Index < Count; Index++ ) { var Range = this.Ranges[Index]; if ( Pos <= Range.PosS ) { Range.PosS++; Range.PosE++; } else if ( Pos > Range.PosS && Pos < Range.PosE ) { var NewRange = new CRunCollaborativeRange( Pos + 1, Range.PosE + 1, Range.Color.Copy() ); this.Ranges.splice( Index + 1, 0, NewRange ); Range.PosE = Pos; Count++; Index++; } //else if ( Pos < Range.PosE ) // Range.PosE++; } }, Update_OnRemove : function(Pos, Count) { var Len = this.Ranges.length; for ( var Index = 0; Index < Len; Index++ ) { var Range = this.Ranges[Index]; var PosE = Pos + Count; if ( Pos < Range.PosS ) { if ( PosE <= Range.PosS ) { Range.PosS -= Count; Range.PosE -= Count; } else if ( PosE >= Range.PosE ) { this.Ranges.splice( Index, 1 ); Len--; Index--;continue; } else { Range.PosS = Pos; Range.PosE -= Count; } } else if ( Pos >= Range.PosS && Pos < Range.PosE ) { if ( PosE >= Range.PosE ) Range.PosE = Pos; else Range.PosE -= Count; } else continue; } }, Clear : function() { this.Ranges = []; }, Init_Drawing : function() { this.DrawingObj = {}; var Count = this.Ranges.length; for ( var CurPos = 0; CurPos < Count; CurPos++ ) { var Range = this.Ranges[CurPos]; for ( var Pos = Range.PosS; Pos < Range.PosE; Pos++ ) this.DrawingObj[Pos] = Range.Color; } }, Check : function(Pos) { if ( undefined !== this.DrawingObj[Pos] ) return this.DrawingObj[Pos]; return null; } }; function CRunCollaborativeRange(PosS, PosE, Color) { this.PosS = PosS; this.PosE = PosE; this.Color = Color; } ParaRun.prototype.Math_SetPosition = function(pos, PosInfo) { var Line = PosInfo.CurLine, Range = PosInfo.CurRange; var CurLine = Line - this.StartLine; var CurRange = ( 0 === CurLine ? Range - this.StartRange : Range ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); // запомним позицию для Recalculate_CurPos, когда Run пустой this.pos.x = pos.x; this.pos.y = pos.y; for(var Pos = StartPos; Pos < EndPos; Pos++) { var Item = this.Content[Pos]; if(PosInfo.DispositionOpers !== null && Item.Type == para_Math_BreakOperator) { PosInfo.DispositionOpers.push(pos.x + Item.GapLeft); } this.Content[Pos].setPosition(pos); pos.x += this.Content[Pos].Get_WidthVisible(); // Get_Width => Get_WidthVisible // Get_WidthVisible - Width + Gaps с учетом настроек состояния } }; ParaRun.prototype.Math_Get_StartRangePos = function(_CurLine, _CurRange, SearchPos, Depth, bStartLine) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var Pos = this.State.ContentPos; var Result = true; if(bStartLine || StartPos < Pos) { SearchPos.Pos.Update(StartPos, Depth); } else { Result = false; } return Result; }; ParaRun.prototype.Math_Get_EndRangePos = function(_CurLine, _CurRange, SearchPos, Depth, bEndLine) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var Pos = this.State.ContentPos; var Result = true; if(bEndLine || Pos < EndPos) { SearchPos.Pos.Update(EndPos, Depth); } else { Result = false; } return Result; }; ParaRun.prototype.Math_Is_End = function(_CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); return EndPos == this.Content.length; }; ParaRun.prototype.IsEmptyRange = function(_CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); return StartPos == EndPos; }; ParaRun.prototype.Recalculate_Range_OneLine = function(PRS, ParaPr, Depth) { // данная функция используется только для мат объектов, которые на строки не разбиваются // ParaText (ParagraphContent.js) // для настройки TextPr // Measure // FontClassification.js // Get_FontClass var Lng = this.Content.length; var CurLine = PRS.Line - this.StartLine; var CurRange = ( 0 === CurLine ? PRS.Range - this.StartRange : PRS.Range ); // обновляем позиции start и end для Range var RangeStartPos = this.protected_AddRange(CurLine, CurRange); var RangeEndPos = Lng; this.Math_RecalculateContent(PRS); this.protected_FillRange(CurLine, CurRange, RangeStartPos, RangeEndPos); }; ParaRun.prototype.Math_RecalculateContent = function(PRS) { var WidthPoints = this.Parent.Get_WidthPoints(); this.bEqArray = this.Parent.IsEqArray(); var ascent = 0, descent = 0, width = 0; this.Recalculate_MeasureContent(); var Lng = this.Content.length; for(var i = 0 ; i < Lng; i++) { var Item = this.Content[i]; var size = Item.size, Type = Item.Type; var WidthItem = Item.Get_WidthVisible(); // Get_Width => Get_WidthVisible // Get_WidthVisible - Width + Gaps с учетом настроек состояния width += WidthItem; if(ascent < size.ascent) ascent = size.ascent; if (descent < size.height - size.ascent) descent = size.height - size.ascent; if(this.bEqArray) { if(Type === para_Math_Ampersand && true === Item.IsAlignPoint()) { WidthPoints.AddNewAlignRange(); } else { WidthPoints.UpdatePoint(WidthItem); } } } this.size.width = width; this.size.ascent = ascent; this.size.height = ascent + descent; }; ParaRun.prototype.Math_Set_EmptyRange = function(_CurLine, _CurRange) { var CurLine = _CurLine - this.StartLine; var CurRange = (0 === CurLine ? _CurRange - this.StartRange : _CurRange); var RangeStartPos = this.protected_AddRange(CurLine, CurRange); var RangeEndPos = RangeStartPos; this.protected_FillRange(CurLine, CurRange, RangeStartPos, RangeEndPos); }; // в этой функции проставляем состояние Gaps (крайние или нет) для всех операторов, к-ые участвуют в разбиении, чтобы не получилось случайно, что при изменении разбивки формулы на строки произошло, что у оператора не будет проставлен Gap ParaRun.prototype.UpdateOperators = function(_CurLine, _CurRange, bEmptyGapLeft, bEmptyGapRight) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); for(var Pos = StartPos; Pos < EndPos; Pos++) { var _bEmptyGapLeft = bEmptyGapLeft && Pos == StartPos, _bEmptyGapRight = bEmptyGapRight && Pos == EndPos - 1; this.Content[Pos].Update_StateGapLeft(_bEmptyGapLeft); this.Content[Pos].Update_StateGapRight(_bEmptyGapRight); } }; ParaRun.prototype.Math_Apply_Style = function(Value) { if(Value !== this.MathPrp.sty) { var OldValue = this.MathPrp.sty; this.MathPrp.sty = Value; History.Add( this, { Type : historyitem_ParaRun_MathStyle, New : Value, Old : OldValue } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); } }; ParaRun.prototype.IsNormalText = function() { var comp_MPrp = this.MathPrp.GetCompiled_ScrStyles(); return comp_MPrp.nor === true; }; ParaRun.prototype.getPropsForWrite = function() { var wRPrp = this.Pr.Copy(), mathRPrp = this.MathPrp.Copy(); return {wRPrp: wRPrp, mathRPrp: mathRPrp}; }; ParaRun.prototype.Math_PreRecalc = function(Parent, ParaMath, ArgSize, RPI, GapsInfo) { this.Parent = Parent; this.Paragraph = ParaMath.Paragraph; var FontSize = this.Get_CompiledPr(false).FontSize; if(RPI.bChangeInline) this.RecalcInfo.Measure = true; // нужно сделать пересчет элементов, например для дроби, т.к. ArgSize у внутренних контентов будет другой => размер if(RPI.bCorrect_FontSize) { var ArgSize = this.Parent.Compiled_ArgSz.value; var FontKoef; if(ArgSize == -1 || ArgSize == -2) { var Pr = new CTextPr(); if(this.Pr.FontSize !== null && this.Pr.FontSize !== undefined) { FontKoef = MatGetKoeffArgSize(this.Pr.FontSize, ArgSize); Pr.FontSize = (((this.Pr.FontSize/FontKoef * 2 + 0.5) | 0) / 2); this.RecalcInfo.TextPr = true; this.RecalcInfo.Measure = true; } if(this.Pr.FontSizeCS !== null && this.Pr.FontSizeCS !== undefined) { FontKoef = MatGetKoeffArgSize( this.Pr.FontSizeCS, ArgSize); Pr.FontSizeCS = (((this.Pr.FontSizeCS/FontKoef * 2 + 0.5) | 0) / 2); this.RecalcInfo.TextPr = true; this.RecalcInfo.Measure = true; } this.Apply_Pr(Pr); } } for (var Pos = 0 ; Pos < this.Content.length; Pos++ ) { if( !this.Content[Pos].IsAlignPoint() ) GapsInfo.setGaps(this.Content[Pos], FontSize); this.Content[Pos].PreRecalc(this, ParaMath); this.Content[Pos].SetUpdateGaps(false); } }; ParaRun.prototype.Math_EmptyRange = function(_CurLine, _CurRange) // до пересчета нужно узнать будет ли данный Run пустым или нет в данном Range, необходимо для того, чтобы выставить wrapIndent { var bEmptyRange = true; var Lng = this.Content.length; if(Lng > 0) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); bEmptyRange = this.protected_GetPrevRangeEndPos(CurLine, CurRange) >= Lng; } return bEmptyRange; }; ParaRun.prototype.Math_UpdateGaps = function(_CurLine, _CurRange, GapsInfo) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var StartPos = this.protected_GetRangeStartPos(CurLine, CurRange); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var FontSize = this.Get_CompiledPr(false).FontSize; for(var Pos = StartPos; Pos < EndPos; Pos++) { GapsInfo.updateCurrentObject(this.Content[Pos], FontSize); var bUpdateCurrent = this.Content[Pos].IsNeedUpdateGaps(); if(bUpdateCurrent || GapsInfo.bUpdate) { GapsInfo.updateGaps(); } GapsInfo.bUpdate = bUpdateCurrent; this.Content[Pos].SetUpdateGaps(false); } }; ParaRun.prototype.UpdLastElementForGaps = function(_CurLine, _CurRange, GapsInfo) { var CurLine = _CurLine - this.StartLine; var CurRange = ( 0 === CurLine ? _CurRange - this.StartRange : _CurRange ); var EndPos = this.protected_GetRangeEndPos(CurLine, CurRange); var FontSize = this.Get_CompiledPr(false).FontSize; var Last = this.Content[EndPos]; GapsInfo.updateCurrentObject(Last, FontSize); }; ParaRun.prototype.IsPlaceholder = function() { return this.Content.length == 1 && this.Content[0].IsPlaceholder(); }; ParaRun.prototype.fillPlaceholders = function() { var placeholder = new CMathText(false); placeholder.fillPlaceholders(); this.Add_ToContent(0, placeholder, false); }; ParaRun.prototype.Math_Correct_Content = function() { for(var i = 0; i < this.Content.length; i++) { if(this.Content[i].Type == para_Math_Placeholder) this.Remove_FromContent(i, 1, true); } }; ParaRun.prototype.OnlyOnePlaceholder = function() { return this.Content.length == 1 && this.Content[0].Type == para_Math_Placeholder; }; ParaRun.prototype.Set_MathPr = function(MPrp) { var OldValue = this.MathPrp; this.MathPrp.Set_Pr(MPrp); History.Add( this, { Type : historyitem_ParaRun_MathPrp, New : this.MathPrp, Old : OldValue } ); this.Recalc_CompiledPr(true); this.private_UpdateTrackRevisionOnChangeTextPr(true); }; ParaRun.prototype.Set_MathTextPr2 = function(TextPr, MathPr) { this.Set_Pr(TextPr.Copy()); this.Set_MathPr(MathPr.Copy()); }; ParaRun.prototype.IsAccent = function() { return this.Parent.IsAccent(); }; ParaRun.prototype.GetCompiled_ScrStyles = function() { return this.MathPrp.GetCompiled_ScrStyles(); }; ParaRun.prototype.IsEqArray = function() { return this.Parent.IsEqArray(); }; ParaRun.prototype.IsBreak = function() { return this.MathPrp.IsBreak(); }; ParaRun.prototype.Get_AlignBrk = function() { return this.MathPrp.Get_AlignBrk(); }; ParaRun.prototype.Math_Is_InclineLetter = function() { var result = false; if(this.Content.length == 1) result = this.Content[0].Is_InclineLetter(); return result; }; ParaRun.prototype.GetMathTextPrForMenu = function() { var TextPr = new CTextPr(); if(this.IsPlaceholder()) TextPr.Merge(this.Parent.GetCtrPrp()); TextPr.Merge(this.Pr); var MathTextPr = this.MathPrp.Copy(); var BI = MathTextPr.GetBoldItalic(); TextPr.Italic = BI.Italic; TextPr.Bold = BI.Bold; return TextPr; }; ParaRun.prototype.ApplyPoints = function(PointsInfo) { if(this.Parent.IsEqArray()) { this.size.width = 0; for(var Pos = 0; Pos < this.Content.length; Pos++) { var Item = this.Content[Pos]; if(Item.Type === para_Math_Ampersand && true === Item.IsAlignPoint()) { PointsInfo.NextAlignRange(); Item.size.width = PointsInfo.GetAlign(); } this.size.width += this.Content[Pos].Get_WidthVisible(); // Get_Width => Get_WidthVisible // Get_WidthVisible - Width + Gaps с учетом настроек состояния } } }; ParaRun.prototype.Get_TextForAutoCorrect = function(AutoCorrectEngine, RunPos) { var ActionElement = AutoCorrectEngine.Get_ActionElement(); var nCount = this.Content.length; for (var nPos = 0; nPos < nCount; nPos++) { var Item = this.Content[nPos]; if (para_Math_Text === Item.Type || para_Math_BreakOperator === Item.Type) { AutoCorrectEngine.Add_Text(String.fromCharCode(Item.value), this, nPos, RunPos); } else if (para_Math_Ampersand === Item.Type) { AutoCorrectEngine.Add_Text('&', this, nPos, RunPos); } if (Item === ActionElement) { AutoCorrectEngine.Stop_CollectText(); break; } } if (null === AutoCorrectEngine.TextPr) AutoCorrectEngine.TextPr = this.Pr.Copy(); if (null == AutoCorrectEngine.MathPr) AutoCorrectEngine.MathPr = this.MathPrp.Copy(); }; ParaRun.prototype.IsShade = function() { var oShd = this.Get_CompiledPr(false).Shd; return !(oShd === undefined || shd_Nil === oShd.Value); }; ParaRun.prototype.Get_RangesByPos = function(Pos) { var Ranges = []; var LinesCount = this.protected_GetLinesCount(); for (var LineIndex = 0; LineIndex < LinesCount; LineIndex++) { var RangesCount = this.protected_GetRangesCount(LineIndex); for (var RangeIndex = 0; RangeIndex < RangesCount; RangeIndex++) { var StartPos = this.protected_GetRangeStartPos(LineIndex, RangeIndex); var EndPos = this.protected_GetRangeEndPos(LineIndex, RangeIndex); if (StartPos <= Pos && Pos <= EndPos) Ranges.push({Range : (LineIndex === 0 ? RangeIndex + this.StartRange : RangeIndex), Line : LineIndex + this.StartLine}); } } return Ranges; }; ParaRun.prototype.Compare_DrawingsLogicPositions = function(CompareObject) { var Drawing1 = CompareObject.Drawing1; var Drawing2 = CompareObject.Drawing2; for (var Pos = 0, Count = this.Content.length; Pos < Count; Pos++) { var Item = this.Content[Pos]; if (Item === Drawing1) { CompareObject.Result = 1; return; } else if (Item === Drawing2) { CompareObject.Result = -1; return; } } }; ParaRun.prototype.Get_ReviewType = function() { return this.ReviewType; }; ParaRun.prototype.Set_ReviewType = function(Value) { if (Value !== this.ReviewType) { var OldReviewType = this.ReviewType; var OldReviewInfo = this.ReviewInfo.Copy(); this.ReviewType = Value; this.ReviewInfo.Update(); History.Add(this, {Type : historyitem_ParaRun_ReviewType, New : {ReviewType : this.ReviewType, ReviewInfo : this.ReviewInfo.Copy()}, Old : {ReviewType : OldReviewType, ReviewInfo : OldReviewInfo}}); this.private_UpdateTrackRevisions(); } }; ParaRun.prototype.Set_ReviewTypeWithInfo = function(ReviewType, ReviewInfo) { History.Add(this, {Type : historyitem_ParaRun_ReviewType, Old : {ReviewType : this.ReviewType, ReviewInfo : this.ReviewInfo ? this.ReviewInfo.Copy() : undefined}, New : {ReviewType : ReviewType, ReviewInfo : ReviewInfo ? ReviewInfo.Copy() : undefined}}); this.ReviewType = ReviewType; this.ReviewInfo = ReviewInfo; this.private_UpdateTrackRevisions(); }; ParaRun.prototype.Get_Parent = function() { if (!this.Paragraph) return null; var ContentPos = this.Paragraph.Get_PosByElement(this); if (null == ContentPos || undefined == ContentPos || ContentPos.Get_Depth() < 0) return null; ContentPos.Decrease_Depth(1); return this.Paragraph.Get_ElementByPos(ContentPos); }; ParaRun.prototype.private_GetPosInParent = function(_Parent) { var Parent = (_Parent? _Parent : this.Get_Parent()); if (!Parent) return -1; // Ищем данный элемент в родительском классе var RunPos = -1; for (var Pos = 0, Count = Parent.Content.length; Pos < Count; Pos++) { if (this === Parent.Content[Pos]) { RunPos = Pos; break; } } return RunPos; }; ParaRun.prototype.Make_ThisElementCurrent = function() { if (this.Paragraph && true === this.Paragraph.Is_UseInDocument() && true === this.Is_UseInParagraph()) { var ContentPos = this.Paragraph.Get_PosByElement(this); ContentPos.Add(this.State.ContentPos); this.Paragraph.Set_ParaContentPos(ContentPos, true, -1, -1); this.Paragraph.Document_SetThisElementCurrent(false); } }; ParaRun.prototype.Get_AllParagraphs = function(Props, ParaArray) { var ContentLen = this.Content.length; for (var CurPos = 0; CurPos < ContentLen; CurPos++) { if (para_Drawing == this.Content[CurPos].Type) this.Content[CurPos].Get_AllParagraphs(Props, ParaArray); } }; ParaRun.prototype.Check_RevisionsChanges = function(Checker, ContentPos, Depth) { if (this.Is_Empty()) return; if (true !== Checker.Is_ParaEndRun()) { var ReviewType = this.Get_ReviewType(); if (ReviewType !== Checker.Get_AddRemoveType()) { Checker.Flush_AddRemoveChange(); ContentPos.Update(0, Depth); if (reviewtype_Add === ReviewType || reviewtype_Remove === ReviewType) Checker.Start_AddRemove(ReviewType, ContentPos); } if (reviewtype_Add === ReviewType || reviewtype_Remove === ReviewType) { var Text = ""; var ContentLen = this.Content.length; for (var CurPos = 0; CurPos < ContentLen; CurPos++) { var Item = this.Content[CurPos]; var ItemType = Item.Type; switch (ItemType) { case para_Text : Text += String.fromCharCode(Item.Value); break; case para_Space: case para_Tab : Text += " "; break; } } Checker.Add_Text(Text); ContentPos.Update(this.Content.length, Depth); Checker.Set_AddRemoveEndPos(ContentPos); Checker.Update_AddRemoveReviewInfo(this.ReviewInfo); } } var HavePrChange = this.Have_PrChange(); var DiffPr = this.Get_DiffPrChange(); if (HavePrChange !== Checker.Have_PrChange() || true !== Checker.Compare_PrChange(DiffPr)) { Checker.Flush_TextPrChange(); ContentPos.Update(0, Depth); if (true === HavePrChange) { Checker.Start_PrChange(DiffPr, ContentPos); } } if (true === HavePrChange) { ContentPos.Update(this.Content.length, Depth); Checker.Set_PrChangeEndPos(ContentPos); Checker.Update_PrChangeReviewInfo(this.Pr.ReviewInfo); } }; ParaRun.prototype.private_UpdateTrackRevisionOnChangeContent = function(bUpdateInfo) { if (reviewtype_Common !== this.Get_ReviewType()) { this.private_UpdateTrackRevisions(); if (true === bUpdateInfo && this.Paragraph && this.Paragraph.LogicDocument && true === this.Paragraph.LogicDocument.Is_TrackRevisions()) { var OldReviewInfo = this.ReviewInfo.Copy(); this.ReviewInfo.Update(); History.Add(this, {Type : historyitem_ParaRun_ContentReviewInfo, Old : OldReviewInfo, New : this.ReviewInfo.Copy()}); } } }; ParaRun.prototype.private_UpdateTrackRevisionOnChangeTextPr = function(bUpdateInfo) { if (true === this.Have_PrChange()) { this.private_UpdateTrackRevisions(); if (true === bUpdateInfo && this.Paragraph && this.Paragraph.LogicDocument && true === this.Paragraph.LogicDocument.Is_TrackRevisions()) { var OldReviewInfo = this.Pr.ReviewInfo.Copy(); this.Pr.ReviewInfo.Update(); History.Add(this, {Type : historyitem_ParaRun_PrReviewInfo, Old : OldReviewInfo, New : this.Pr.ReviewInfo.Copy()}); } } }; ParaRun.prototype.private_UpdateTrackRevisions = function() { if (this.Paragraph && this.Paragraph.LogicDocument && this.Paragraph.LogicDocument.Get_TrackRevisionsManager) { var RevisionsManager = this.Paragraph.LogicDocument.Get_TrackRevisionsManager(); RevisionsManager.Check_Paragraph(this.Paragraph); } }; ParaRun.prototype.Accept_RevisionChanges = function(Type, bAll) { var Parent = this.Get_Parent(); var RunPos = this.private_GetPosInParent(); var ReviewType = this.Get_ReviewType(); var HavePrChange = this.Have_PrChange(); // Нет изменений в данном ране if (reviewtype_Common === ReviewType && true !== HavePrChange) return; if (true === this.Selection.Use || true === bAll) { var StartPos = this.Selection.StartPos; var EndPos = this.Selection.EndPos; if (StartPos > EndPos) { StartPos = this.Selection.EndPos; EndPos = this.Selection.StartPos; } if (true === bAll) { StartPos = 0; EndPos = this.Content.length; } var CenterRun = null, CenterRunPos = RunPos; if (0 === StartPos && this.Content.length === EndPos) { CenterRun = this; } else if (StartPos > 0 && this.Content.length === EndPos) { CenterRun = this.Split2(StartPos, Parent, RunPos); CenterRunPos = RunPos + 1; } else if (0 === StartPos && this.Content.length > EndPos) { CenterRun = this; this.Split2(EndPos, Parent, RunPos); } else { this.Split2(EndPos, Parent, RunPos); CenterRun = this.Split2(StartPos, Parent, RunPos); CenterRunPos = RunPos + 1; } if (true === HavePrChange && (undefined === Type || c_oAscRevisionsChangeType.TextPr === Type)) { CenterRun.Remove_PrChange(); } if (reviewtype_Add === ReviewType && (undefined === Type || c_oAscRevisionsChangeType.TextAdd === Type)) { CenterRun.Set_ReviewType(reviewtype_Common); } else if (reviewtype_Remove === ReviewType && (undefined === Type || c_oAscRevisionsChangeType.TextRem === Type)) { Parent.Remove_FromContent(CenterRunPos, 1); if (Parent.Get_ContentLength() <= 0) { Parent.Selection_Remove(); Parent.Add_ToContent(0, new ParaRun()); Parent.Cursor_MoveToStartPos(); } } } }; ParaRun.prototype.Reject_RevisionChanges = function(Type, bAll) { var Parent = this.Get_Parent(); var RunPos = this.private_GetPosInParent(); var ReviewType = this.Get_ReviewType(); var HavePrChange = this.Have_PrChange(); // Нет изменений в данном ране if (reviewtype_Common === ReviewType && true !== HavePrChange) return; if (true === this.Selection.Use || true === bAll) { var StartPos = this.Selection.StartPos; var EndPos = this.Selection.EndPos; if (StartPos > EndPos) { StartPos = this.Selection.EndPos; EndPos = this.Selection.StartPos; } if (true === bAll) { StartPos = 0; EndPos = this.Content.length; } var CenterRun = null, CenterRunPos = RunPos; if (0 === StartPos && this.Content.length === EndPos) { CenterRun = this; } else if (StartPos > 0 && this.Content.length === EndPos) { CenterRun = this.Split2(StartPos, Parent, RunPos); CenterRunPos = RunPos + 1; } else if (0 === StartPos && this.Content.length > EndPos) { CenterRun = this; this.Split2(EndPos, Parent, RunPos); } else { this.Split2(EndPos, Parent, RunPos); CenterRun = this.Split2(StartPos, Parent, RunPos); CenterRunPos = RunPos + 1; } if (true === HavePrChange && (undefined === Type || c_oAscRevisionsChangeType.TextPr === Type)) { CenterRun.Set_Pr(CenterRun.Pr.PrChange); } if (reviewtype_Add === ReviewType && (undefined === Type || c_oAscRevisionsChangeType.TextAdd === Type)) { Parent.Remove_FromContent(CenterRunPos, 1); if (Parent.Get_ContentLength() <= 0) { Parent.Selection_Remove(); Parent.Add_ToContent(0, new ParaRun()); Parent.Cursor_MoveToStartPos(); } } else if (reviewtype_Remove === ReviewType && (undefined === Type || c_oAscRevisionsChangeType.TextRem === Type)) { CenterRun.Set_ReviewType(reviewtype_Common); } } }; ParaRun.prototype.Is_InHyperlink = function() { if (!this.Paragraph) return false; var ContentPos = this.Paragraph.Get_PosByElement(this); var Classes = this.Paragraph.Get_ClassesByPos(ContentPos); var bHyper = false; var bRun = false; for (var Index = 0, Count = Classes.length; Index < Count; Index++) { var Item = Classes[Index]; if (Item === this) { bRun = true; break; } else if (Item instanceof ParaHyperlink) { bHyper = true; } } return (bHyper && bRun); }; ParaRun.prototype.Get_ClassesByPos = function(Classes, ContentPos, Depth) { Classes.push(this); }; ParaRun.prototype.Get_DocumentPositionFromObject = function(PosArray) { if (!PosArray) PosArray = []; if (this.Paragraph) { var ParaContentPos = this.Paragraph.Get_PosByElement(this); if (null !== ParaContentPos) { var Depth = ParaContentPos.Get_Depth(); while (Depth > 0) { var Pos = ParaContentPos.Get(Depth); var Class = this.Get_ElementByPos(ParaContentPos); ParaContentPos.Decrease_Depth(1); Depth--; PosArray.splice(0, 0, {Class : Class, Position : Pos}); } PosArray.splice(0, 0, {Class : this.Paragraph, Position : ParaContentPos.Get(0)}); } this.Paragraph.Get_DocumentPositionFromObject(PosArray); } return PosArray; }; ParaRun.prototype.Is_UseInParagraph = function() { if (!this.Paragraph) return false; var ContentPos = this.Paragraph.Get_PosByElement(this); if (!ContentPos) return false; return true; }; function CParaRunStartState(Run) { this.Paragraph = Run.Paragraph; this.Pr = Run.Pr.Copy(); this.Content = []; for(var i = 0; i < Run.Content.length; ++i) { this.Content.push(Run.Content[i]); } } function CReviewInfo() { this.Editor = editor; this.UserId = ""; this.UserName = ""; this.DateTime = ""; } CReviewInfo.prototype.Update = function() { if (this.Editor && this.Editor.DocInfo) { this.UserId = this.Editor.DocInfo.get_UserId(); this.UserName = this.Editor.DocInfo.get_UserName(); this.DateTime = (new Date()).getTime(); } }; CReviewInfo.prototype.Copy = function() { var Info = new CReviewInfo(); Info.UserId = this.UserId; Info.UserName = this.UserName; Info.DateTime = this.DateTime; return Info; }; CReviewInfo.prototype.Get_UserId = function() { return this.UserId; }; CReviewInfo.prototype.Get_UserName = function() { return this.UserName; }; CReviewInfo.prototype.Get_DateTime = function() { return this.DateTime; }; CReviewInfo.prototype.Write_ToBinary = function(Writer) { Writer.WriteString2(this.UserId); Writer.WriteString2(this.UserName); Writer.WriteString2(this.DateTime); }; CReviewInfo.prototype.Read_FromBinary = function(Reader) { this.UserId = Reader.GetString2(); this.UserName = Reader.GetString2(); this.DateTime = parseInt(Reader.GetString2()); };