"use strict";

/// TODO

//  1.  Пересмотреть схему для findDisposition(base.js), т.к. если нажали за границами элемента, то происходит селект, т.к. теперь на mouseDown и mouseDown одни и те же функции
//  2.  поправить центр для delimiters (когда оператор текст)
//  3.  поправить accent расположение глифов в случае небольшого размера шрифта (н-р, 14)
//  5.  сделать gaps для мат. объектов, +, - в зависимости от расположения в контенте
//  6.  Размер разделительной черты для линейной дроби ограничить также как и для наклонной дроби
//  7.  баг с отрисовкой кругового интеграла
//  8.  cursor_Up, cursor_Down (+ c зажитым shift)
//  9.  Merge textPrp и mathTextPrp (bold, italic)
//  10. Поправить баги для CAccent с точками : смещение, когда идут подряд с одной точкой, двумя и тремя они перекрываются
//  11. Для управляющих символов запрашивать не getCtrPrp, getPrpToControlLetter (реализована, нужно только протащить для всех управляющих элементов)
//  12. объединение формул на remove и add
//  13. Для N-арных операторов в случае со степенью : итераторы занимают не 2/3 от основание, а примерно половину (когда один итератор сверху или снизу)
//  14. Для дробей, n-арных операторов и пр. считать расстояние исходя из shiftCenter
//  15. Для числителя/знаменателя сделать меньшие расстояния для внутренних дробей, меньшие по размеру n-арные операторы, значок радикала


//  TODO Refactoring
//  1. CAccent ~> COperator
//  2. COperator : объединить все классы связанные с отрисовкой и пересчетом операторов в один


/// TODO

// 1. Посмотреть стрелки и прочее для delimiters (которые используются для accent), при необходимости привести к одному типу

// 3. Проверить что будет, если какие-то настройки убрать/добавить из ctrPrp, влияют ли они на отрисовку управляющих элементов (например, Italic, Bold)
// 4. Протестировать n-арные операторы, когда добавляется текст вместо оператора (mouseDown не работает, выравнено как alignTop)

function CRPI()
{
    this.NeedResize      = true;
    this.bDecreasedComp  = false;
    this.bInline         = false;
    this.bChangeInline   = false;
    this.bNaryInline     = false; /*для CDegreeSupSub внутри N-арного оператора, этот флаг необходим, чтобы итераторы максимально близко друг к другу расположить*/
    this.bEqqArray       = false; /*для амперсанда*/
    this.bMathFunc       = false;
    this.PRS             = null;
}
CRPI.prototype.Copy = function()
{
    var RPI = new CRPI();

    RPI.NeedResize      = this.NeedResize;
    RPI.bInline         = this.bInline;
    RPI.bDecreasedComp  = this.bDecreasedComp;
    RPI.bChangeInline   = this.bChangeInline;
    RPI.bNaryInline     = this.bNaryInline;
    RPI.bEqqArray       = this.bEqqArray;
    RPI.bMathFunc       = this.bMathFunc;
    RPI.PRS             = this.PRS;

    return RPI;
}

function CMathPointInfo()
{
    this.x    = 0;
    this.y    = 0;

    this.bEven      = true;
    this.CurrPoint  = 0;

    this.InfoPoints = {};
}
CMathPointInfo.prototype.SetInfoPoints = function(InfoPoints)
{
    this.InfoPoints.GWidths       = InfoPoints.GWidths;
    this.InfoPoints.GPoints       = InfoPoints.GPoints;
    this.InfoPoints.ContentPoints = InfoPoints.ContentPoints.Widths;
    this.InfoPoints.GMaxDimWidths = InfoPoints.GMaxDimWidths;
}
CMathPointInfo.prototype.NextAlignRange = function()
{
    if(this.bEven)
        this.bEven = false;
    else
    {
        this.CurrPoint++;
        this.bEven = true;
    }
}
CMathPointInfo.prototype.GetAlign = function()
{
    var align = 0;

    if(this.bEven)
    {
        var alignEven, alignGeneral, alignOdd;

        var Len   = this.InfoPoints.ContentPoints.length,
            Point = this.InfoPoints.ContentPoints[this.CurrPoint];

        var GWidth = this.InfoPoints.GWidths[this.CurrPoint],
            GPoint = this.InfoPoints.GPoints[this.CurrPoint];

        if(this.CurrPoint == Len - 1 && Point.odd == -1) // то есть последняя точка четная, выравнивание по центру
        {
            var GMaxDimWidth = this.InfoPoints.GMaxDimWidths[this.CurrPoint];

            alignGeneral = (GMaxDimWidth - Point.even)/2;
            alignEven = 0;
        }
        else
        {
            alignGeneral = (GWidth - GPoint.even - GPoint.odd)/2;
            alignEven = GPoint.even - Point.even;
        }

        if(this.CurrPoint > 0)
        {
            var PrevGenPoint = this.InfoPoints.GPoints[this.CurrPoint-1],
                PrevGenWidth = this.InfoPoints.GWidths[this.CurrPoint-1],
                PrevPoint    = this.InfoPoints.ContentPoints[this.CurrPoint-1];

            var alignPrevGen = (PrevGenWidth - PrevGenPoint.even - PrevGenPoint.odd)/2;
            alignOdd = alignPrevGen +  PrevGenPoint.odd - PrevPoint.odd;
        }
        else
            alignOdd = 0;

        align = alignGeneral + alignEven + alignOdd;
    }

    return align;
}

function CInfoPoints()
{
    this.GWidths       = null;
    this.GPoints       = null;
    this.GMaxDimWidths = null;
    this.ContentPoints = new AmperWidths();
}
CInfoPoints.prototype.SetDefault = function()
{
    this.GWidths       = null;
    this.GPoints       = null;
    this.GMaxDimWidths = null;
    this.ContentPoints.SetDefault();
}


function CMathPosition()
{
    this.x  = 0;
    this.y  = 0;
}
function AmperWidths()
{
    this.bEven     = true; // является ли текущая точка нечетной
    this.Widths    = [];
}
AmperWidths.prototype.UpdatePoint = function(value)
{
    var len = this.Widths.length;

    if(len == 0)
    {
        // дефолтное значение bEven true, для случая если первый элемент в контенте будет Ampersand
        var NewPoint = new CMathPoint();
        NewPoint.even = value;
        this.Widths.push(NewPoint);
        this.bEven = true;
    }
    else
    {
        if(this.bEven)
            this.Widths[len-1].even += value;
        else
            this.Widths[len-1].odd += value;
    }

}
AmperWidths.prototype.AddNewAlignRange = function()
{
    var len = this.Widths.length;

    if(!this.bEven || len == 0)
    {
        var NewPoint = new CMathPoint();
        NewPoint.even = 0;
        this.Widths.push(NewPoint);
    }

    if(this.bEven)
    {
        len = this.Widths.length;
        this.Widths[len-1].odd = 0;
    }


    this.bEven = !this.bEven;

}
AmperWidths.prototype.SetDefault = function()
{
    this.bEven         = true;
    this.Widths.length = 0;
}


function CGaps(oSign, oEqual, oZeroOper, oLett)
{
    this.sign = oSign;
    this.equal = oEqual;
    this.zeroOper = oZeroOper;
    this.letters = oLett;
}

function CCoeffGaps()
{
    this.Sign =
    {
        left:   new CGaps(0.52, 0.26, 0, 0.52),
        right:  new CGaps(0.49, 0, 0, 0.49)
    };

    this.Mult =
    {
        left:   new CGaps(0, 0, 0, 0.46),
        right:  new CGaps(0, 0, 0, 0.49)
    };

    /*this.Equal =
    {
        left:   new CGaps(0.35, 0, 0, 0.7),
        right:  new CGaps(0.25, 0, 0, 0.5)
    };*/

    this.Equal =
    {
        left:   new CGaps(0, 0, 0, 0.7),
        right:  new CGaps(0, 0, 0, 0.5)
    };

    this.Default =
    {
        left:   new CGaps(0, 0, 0, 0),
        right:  new CGaps(0, 0, 0, 0)
    };
}
CCoeffGaps.prototype =
{
    getCoeff: function(codeCurr, codeLR , direct) // obj - либо codeChar, либо мат объект
    {
        var operator = null;

        if(this.checkEqualSign(codeCurr))
            operator = this.Equal;
        else if(this.checkOperSign(codeCurr))
            operator = this.Sign;
        else if(codeCurr == 0x2A)
            operator = this.Mult;
        else
            operator = this.Default;

        var part = direct == -1 ? operator.left : operator.right;

        var coeff = 0;
        if(codeLR == -1) // мат объект
            coeff = part.letters;
        else if(this.checkOperSign(codeLR))
            coeff = part.sign;
        else if(this.checkEqualSign(codeLR))
            coeff = part.equal;
        else if(this.checkZeroSign(codeLR, direct))
            coeff = part.zeroOper;
        else
            coeff = part.letters;

        return coeff;
    },
    checkOperSign: function(code) // "+", "-", "±"
    {
        var PLUS       = 0x2B,
            MINUS      = 0x2D,
            PLUS_MINUS = 0xB1;

        return code == PLUS || code == MINUS || code == PLUS_MINUS;
    },
    checkEqualSign: function(code)
    {
        var COMPARE       = code == 0x3C || code == 0x3E; // LESS, GREATER
        var ARROWS        = (code >= 0x2190 && code <= 0x21B3) || (code == 0x21B6) || (code == 0x21B7) || (code >= 0x21BA && code <= 0x21E9) || (code >=0x21F4 && code <= 0x21FF);
        var INTERSECTION  = code >= 0x2223 && code <= 0x222A;
        var EQUALS        = code == 0x3D || (code >= 0x2234 && code <= 0x22BD) || (code >= 0x22C4 && code <= 0x22FF);
        var ARR_FISHES    = (code >= 0x27DA && code <= 0x27E5) || (code >= 0x27EC && code <= 0x297F);
        var TRIANGLE_SYMB = code >= 0x29CE && code <= 0x29D7;
        var OTH_SYMB      = code == 0x29DF || (code >= 0x29E1 && code <= 0x29E7) || (code >= 0x29F4 && code <= 0x29F8) || (code >= 0x2A22 && code <= 0x2AF0) || (code >= 0x2AF2 && code <= 0x2AFB) || code == 0x2AFD || code == 0x2AFE;


        return COMPARE || ARROWS || INTERSECTION || EQUALS || ARR_FISHES || TRIANGLE_SYMB || OTH_SYMB;
    },
    checkZeroSign: function(code, direct) // "*", "/", "\"
    {
        var MULT     = 0x2A,
            DIVISION = 0x2F,
            B_SLASH  = 0x5C;

        var bOper = code == MULT || code == DIVISION || code == B_SLASH;
        var bLeftBracket = direct == -1 && (code == 0x28 || code == 0x5B || code == 0x7B);
        var bRightBracket = direct == 1 && (code == 0x29 || code == 0x5D || code == 0x7D);


        return bOper || bLeftBracket || bRightBracket;
    }
}

var COEFF_GAPS = new CCoeffGaps();

function CMathArgSize()
{
    this.value       = undefined;
}
CMathArgSize.prototype =
{
    decrease: function()
    {
        if(this.value == undefined)
            this.value = 0;

        if( this.value > -2 )
            this.value--;
    },
    increase: function()
    {
        if(this.value == undefined)
            this.value = 0;

        if(this.value < 2)
            this.value++;
    },
    Set: function(ArgSize)
    {
        this.value = ArgSize.value;
    },
    SetValue: function(val)
    {
        if(val < - 2)
            this.value = -2;
        else if(val > 2)
            this.value = 2;
        else
            this.value = val;

    },
    Copy: function()
    {
        var ArgSize = new CMathArgSize();
        ArgSize.value = this.value;

        return ArgSize;
    },
    Merge: function(ArgSize)
    {
        if(this.value == undefined)
            this.value = 0;

        if(ArgSize.value == undefined)
            ArgSize.value = 0;

        this.SetValue(this.value + ArgSize.value);
    }
}

function CMathGapsInfo(argSize)
{
    //this.measure = oMeasure;

    //this.Parent   = Parent;
    //this.ParaMath = this.Parent.ParaMath; // для Para_Run

    this.argSize = argSize; // argSize выставляем один раз для всего контента
    //this.leftRunPrp = null; // Run_Prp левого элемента
    //this.currRunPrp = null;

    this.Left    = null;    // элемент слева
    this.Current = null;    // текущий элемент

    this.LeftFontSize    = null;
    this.CurrentFontSize = null;

}
CMathGapsInfo.prototype =
{
    setGaps: function(Current, CurrentFontSize)
    {
        this.Left = this.Current;
        this.LeftFontSize = this.CurrentFontSize;

        this.Current = Current;
        this.CurrentFontSize = CurrentFontSize;

        if(this.argSize < 0)
        {
            this.Current.GapLeft = 0;

            if(this.Left !== null)
                this.Left.GapRight = 0;
        }
        else
        {
            var leftCoeff = 0,  /// for Current Object
                rightCoeff = 0; /// for Left Object

            var leftCode;


            if(this.Current.IsText())
            {
                var currCode = this.Current.getCodeChr();

                if(this.Left !== null)
                {
                    if(this.Left.Type == para_Math_Composition)
                    {
                        rightCoeff = this.getGapsMComp(this.Left, 1);
                        leftCoeff = COEFF_GAPS.getCoeff(currCode, -1, -1);

                        if(leftCoeff > rightCoeff)
                            leftCoeff -= rightCoeff;
                    }
                    else if(this.Left.IsText())
                    {
                        leftCode = this.Left.getCodeChr();
                        leftCoeff = COEFF_GAPS.getCoeff(currCode, leftCode, -1);
                        rightCoeff = COEFF_GAPS.getCoeff(leftCode, currCode, 1);
                    }

                }
                else
                    this.Current.GapLeft = 0;
            }
            else if(this.Current.Type == para_Math_Composition)
            {
                leftCoeff = this.getGapsMComp(this.Current, -1);

                if(this.Left != null)
                {
                    if(this.Left.Type == para_Math_Composition)
                    {
                        rightCoeff = this.getGapsMComp(this.Left, 1);

                        if(rightCoeff/2 > leftCoeff)
                            rightCoeff -= leftCoeff;
                        else
                            rightCoeff /= 2;

                        if(leftCoeff < rightCoeff/2)
                            leftCoeff = rightCoeff/2;
                        else
                            leftCoeff -= rightCoeff/2;
                    }
                    else if(this.Left.IsText())
                    {
                        leftCode = this.Left.getCodeChr();
                        rightCoeff = COEFF_GAPS.getCoeff(leftCode, -1, 1);
                        if(rightCoeff > leftCoeff)
                            rightCoeff -= leftCoeff;
                    }
                }
                else
                    leftCoeff = 0;
            }

            leftCoeff = Math.ceil(leftCoeff*10)/10;
            rightCoeff = Math.ceil(rightCoeff*10)/10;

            var LGapSign = 0.1513*this.CurrentFontSize;
            this.Current.GapLeft = Math.ceil(leftCoeff*LGapSign*10)/10; // если ни один случай не выполнился, выставляем "нулевые" gaps (default): необходимо, если что-то удалили и объект стал первый или последним в контенте

            if(this.Left != null)
            {
                var RGapSign = 0.1513*this.LeftFontSize;
                this.Left.GapRight = Math.ceil(rightCoeff*RGapSign*10)/10;
            }
        }
    },
    getGapsMComp: function(MComp, direct)
    {
        var kind = MComp.kind;
        var checkGap = this.checkGapKind(kind);

        var bNeedGap = !checkGap.bEmptyGaps && !checkGap.bChildGaps;

        var coeffLeft  = 0.001,
            coeffRight = 0; // for checkGap.bEmptyGaps

        //var bDegree = kind == MATH_DEGREE || kind == MATH_DEGREESubSup;
        var bDegree = kind == MATH_DEGREE;

        if(checkGap.bChildGaps)
        {
            if(bDegree)
            {
                coeffLeft  = 0.03;

                if(MComp.IsPlhIterator())
                    coeffRight = 0.12;
                else
                    coeffRight = 0.16;
            }

            var gapsChild = MComp.getGapsInside(this);

            coeffLeft  = coeffLeft  < gapsChild.left  ? gapsChild.left  : coeffLeft;
            coeffRight = coeffRight < gapsChild.right ? gapsChild.right : coeffRight;
        }
        else if(bNeedGap)
        {
            coeffLeft = 0.4;
            coeffRight = 0.3;
        }


        return direct == -1 ? coeffLeft : coeffRight;
    },
    checkGapKind: function(kind)
    {
        var bEmptyGaps = kind == MATH_DELIMITER || kind == MATH_MATRIX,
            bChildGaps = kind == MATH_DEGREE || kind == MATH_DEGREESubSup || kind == MATH_ACCENT || kind == MATH_RADICAL|| kind == MATH_BOX || kind == MATH_BORDER_BOX || (kind == MATH_DELIMITER);

        return  {bEmptyGaps: bEmptyGaps, bChildGaps: bChildGaps};
    }

}

function CMPrp()
{
    this.sty      = undefined;
    this.scr      = undefined;
    this.nor      = undefined;

    this.aln      = undefined;
    this.brk      = undefined;
    this.lit      = undefined;

    // Default
    /*this.sty      = STY_ITALIC;
    this.scr      = TXT_ROMAN;

    this.nor      = false;

    this.aln      = false;
    this.brk      = false;
    this.lit      = false;*/

    // TXT_NORMAL
    // если normal == false, то берем TextPrp отсюда (в wRunPrp bold/italic не учитываем, выставляем отсюда)
    // если normal == true, то их Word не учитывает и берет TextPr из wRunPrp

    // TXT_PLAIN
    // если plain == true
    // буквы берутся обычные, не специальные для Cambria Math : то есть как для TXT_NORMAL
    // отличие от TXT_NORMAL w:rPrp в этом случае не учитываются !

}
CMPrp.prototype =
{
    getPropsForWrite: function()
    {
        var props =
        {
            aln:    this.aln,
            brk:    this.brk,
            lit:    this.lit,
            nor:    this.nor,
            sty:    this.sty,
            scr:    this.scr
        };

        return props;
    },
    GetTxtPrp: function()
    {
        var textPrp = new CTextPr();

        if(this.sty == undefined)
        {
            textPrp.Italic = true;
            textPrp.Bold   = false;
        }
        else
        {
            textPrp.Italic = this.sty == STY_BI || this.sty == STY_ITALIC;
            textPrp.Bold   = this.sty == STY_BI || this.sty == STY_BOLD;
        }


        return textPrp;
    },
    Copy: function()
    {
        var NewMPrp = new CMPrp();
        
        NewMPrp.aln      = this.aln;
        NewMPrp.lit      = this.lit;
        NewMPrp.nor      = this.nor;
        NewMPrp.sty      = this.sty;
        NewMPrp.scr      = this.scr;

        if(this.brk !== undefined)
            NewMPrp.brk = this.brk.Copy();
        
        return NewMPrp;
    },
    GetCompiled_ScrStyles : function()
    {
        var nor = this.nor == undefined ? false : this.nor;
        var scr = this.scr == undefined ? TXT_ROMAN : this.scr;
        var sty = this.sty == undefined ? STY_ITALIC : this.sty;

        return {nor: nor, scr: scr, sty: sty};
    },
    SetStyle: function(Bold, Italic) /// из ctrPrp получить style для MathPrp
    {
        if(Bold == true && Italic == true)
            this.sty = STY_BI;
        else if(Italic == true)
            this.sty = STY_ITALIC;
        else if(Bold == true)
            this.sty = STY_BOLD;
        else if(Bold == false && Italic == false)
            this.sty = STY_PLAIN;
        else
            this.sty = undefined;
    }
}


//TODO
//пересмотреть this.dW и this.dH


function CMathContent()
{
	this.Id = g_oIdCounter.Get_NewId();		

    this.Content = []; // array of mathElem

    this.CurPos = 0;
    this.WidthToElement = [];
    this.pos = new CMathPosition();   // относительная позиция

    //  Properties
    this.ParaMath       = null;
    this.ArgSize        = new CMathArgSize();
    this.Compiled_ArgSz = new CMathArgSize();

    // for EqqArray
    this.InfoPoints = new CInfoPoints();
    ///////////////

    this.plhHide    = false;
    this.bRoot      = false;
    //////////////////

    this.Selection =
    {
        Start:  0,
        End:    0,
        Use:    false
    };

    this.RecalcInfo =
    {
        TextPr:             true,
        bEqqArray:          false,
        bChangeInfoPoints:  false
    };

    this.NearPosArray = [];
    this.ParentElement = null;

    this.size = new CMathSize();
	
	// Добавляем данный класс в таблицу Id (обязательно в конце конструктора)
	g_oTableId.Add( this, this.Id );
}
CMathContent.prototype =
{
    constructor: CMathContent,
    init: function()
    {

    },
    addElementToContent: function(obj)   //for "read"
    {
        this.Internal_Content_Add(this.Content.length, obj, false);
        this.CurPos = this.Content.length-1;
    },
    fillPlaceholders: function()
    {
        this.Content.length = 0;

        var oMRun = new ParaRun(null, true);
        oMRun.fillPlaceholders();
        this.addElementToContent(oMRun);

        /*var placeholder = new CMathText(false);
        //placeholder.relate(this);
        placeholder.fillPlaceholders();

        this.Content.push( placeholder );*/
    },
    //////////////////////////////////////
    /*recalculateSize: function()
    {
        var width      =   0 ;
        var ascent     =   0 ;
        var descent    =   0 ;

        var oSize;

        this.WidthToElement.length = 0;

        for(var i = 0; i < this.Content.length; i++)
        {
            if(this.Content[i].Type == para_Math_Composition)
                this.Content[i].ApplyGaps();
            else if(this.Content[i].Type == para_Math_Run)
                this.Content[i].Math_ApplyGaps();

            this.WidthToElement[i] = width;

            oSize = this.Content[i].size;
            width += oSize.width;

            ascent = ascent > oSize.ascent ? ascent : oSize.ascent;
            var oDescent = oSize.height - oSize.ascent;
            descent =  descent < oDescent ? oDescent : descent;
        }

        this.size = {width: width, height: ascent + descent, ascent: ascent};
    },*/
    PreRecalc: function(Parent, ParaMath, ArgSize, RPI)
    {
        if(ArgSize !== null && ArgSize !== undefined)
        {
            this.Compiled_ArgSz.value = this.ArgSize.value;
            this.Compiled_ArgSz.Merge(ArgSize);
        }

        this.ParaMath = ParaMath;
        if(Parent !== null)
        {
            this.bRoot = false;
            this.Parent = Parent;
        }

        if(ArgSize !== null && ArgSize !== undefined)
        {
            this.Compiled_ArgSz.value = this.ArgSize.value;
            this.Compiled_ArgSz.Merge(ArgSize);
        }

        var lng = this.Content.length;

        var GapsInfo = new CMathGapsInfo(this.Compiled_ArgSz.value);

        for(var pos = 0; pos < lng; pos++)
        {
            if(this.Content[pos].Type == para_Math_Composition)
            {
                this.Content[pos].PreRecalc(this, ParaMath, this.Compiled_ArgSz, RPI, GapsInfo);
            }
            else if(this.Content[pos].Type == para_Math_Run)
                this.Content[pos].Math_PreRecalc(this, ParaMath, this.Compiled_ArgSz, RPI, GapsInfo);
        }

        if(GapsInfo.Current !== null)
            GapsInfo.Current.GapRight = 0;

    },
    Resize: function(oMeasure, RPI)      // пересчитываем всю формулу
    {
        this.WidthToElement.length = 0;
        this.RecalcInfo.bEqqArray = RPI.bEqqArray;

        var lng = this.Content.length;

        this.size.SetZero();
        this.InfoPoints.SetDefault();

        for(var pos = 0; pos < lng; pos++)
        {
            if(this.Content[pos].Type == para_Math_Composition)
            {
                var NewRPI = RPI.Copy();
                NewRPI.bEqqArray    = false;

                this.Content[pos].Resize(oMeasure, NewRPI);

                if(RPI.bEqqArray)
                    this.InfoPoints.ContentPoints.UpdatePoint(this.Content[pos].size.width);
            }
            else if(this.Content[pos].Type == para_Math_Run)
            {
                //this.Content[pos].Recalculate_Range();
                this.Content[pos].Math_Recalculate(oMeasure, RPI, this.InfoPoints.ContentPoints);
            }

            this.WidthToElement[pos] = this.size.width;

            var oSize = this.Content[pos].size;
            this.size.width += oSize.width;

            var oDescent = oSize.height - oSize.ascent,
                SizeDescent = this.size.height - this.size.ascent;

            this.size.ascent = this.size.ascent > oSize.ascent ? this.size.ascent : oSize.ascent;

            this.size.height = SizeDescent < oDescent ? oDescent + this.size.ascent : SizeDescent + this.size.ascent;
        }
    },
    // особый случай: вызываем, когда пересчет всей формулы не нужен, а нужно выставить только Lines (Реализована, чтобы не править Resize у каждого элемента)
    Resize_2: function(oMeasure, Parent, ParaMath, RPI, ArgSize)
    {
        var lng = this.Content.length;
        for(var i = 0; i < lng; i++)
        {
            if(this.Content[i].Type == para_Math_Composition)
                this.Content[i].Resize_2(oMeasure, this, ParaMath, RPI, ArgSize);
            else
                this.Content[i].Math_Recalculate(oMeasure, RPI, null);
        }
    },
    getWidthsPoints: function()
    {
        return this.InfoPoints.ContentPoints.Widths;
    },
    IsEqqArray: function()
    {
        return this.Parent.IsEqqArray();
    },
    Get_CompiledArgSize: function()
    {
        return this.Compiled_ArgSz;
    },
    getGapsInside: function(GapsInfo) // учитываем gaps внутренних объектов
    {
        var gaps = {left: 0, right: 0};
        var bFirstComp = false,
            bLastComp = false;

        var len = this.Content.length;

        if(len > 1)
        {
            var bFRunEmpty = this.Content[0].Is_Empty();
            bFirstComp = bFRunEmpty && this.Content[1].Type == para_Math_Composition; // первый всегда идет Run

            var bLastRunEmpty = this.Content[len - 1].Is_Empty(); // т.к. после мат. объекта стоит пустой Run
            bLastComp = bLastRunEmpty && this.Content[len - 2].Type == para_Math_Composition;
        }

        var checkGap;

        if(bFirstComp)
        {
            checkGap = GapsInfo.checkGapKind(this.Content[1].kind);

            if(!checkGap.bChildGaps)
            {
                gaps.left = GapsInfo.getGapsMComp(this.Content[1], -1);
                //gaps.left = gapsMComp.left;
            }
        }

        if(bLastComp)
        {
            checkGap = GapsInfo.checkGapKind(this.Content[len - 1].kind);

            if(!checkGap.bChildGaps)
            {
                gaps.right = GapsInfo.getGapsMComp(this.Content[len - 1], 1);
                //gaps.right = gapsMComp.right;
            }
        }

        return gaps;
    },
    IsOneLineText: function()   // for degree
    {
        var bOneLineText = true;

        for(var i = 0; i < this.Content.length; i++)
        {
            if(this.Content[i].Type == para_Math_Composition)
            {
                if(!this.Content[i].IsOneLineText())
                {
                    bOneLineText = false;
                    break;
                }
            }
        }

        return bOneLineText;
    },
    draw: function(x, y, pGraphics, PDSE)
    {
        var bHidePlh = this.plhHide && this.IsPlaceholder();

        if( !bHidePlh )
        {
            for(var i=0; i < this.Content.length;i++)
            {
                if(this.Content[i].Type == para_Math_Composition)
                {
                    this.Content[i].draw(x, y, pGraphics, PDSE);
                }
                else
                    this.Content[i].Draw_Elements(PDSE);
                    //this.Content[i].Math_Draw(x, y, pGraphics);
            }
        }
    },
    update_Cursor: function(CurPage, UpdateTarget)
    {
        var result;
        if(this.Content[this.CurPos].Type == para_Math_Composition)
        {
            result = this.Content[this.CurPos].update_Cursor(CurPage, UpdateTarget);
        }
        else
        {
            var X = this.pos.x + this.ParaMath.X + this.WidthToElement[this.CurPos],
                Y = this.pos.y + this.ParaMath.Y + this.size.ascent;

            result = this.Content[this.CurPos].Math_Update_Cursor(X, Y, CurPage, UpdateTarget);
        }

        return result;
    },
    setCtrPrp: function()
    {

    },
    getInfoLetter: function(Info)
    {
        if(this.Content.length == 1)
            this.Content[0].Math_GetInfoLetter(Info);
        else
            Info.Result = false;
    },
    IsPlaceholder: function()
    {
        var flag = false;
        if(!this.bRoot && this.Content.length == 1)
            flag  = this.Content[0].IsPlaceholder();

        return flag;
    },
    IsJustDraw: function()
    {
        return false;
    },
    ApplyPoints: function(WidthsPoints, Points, MaxDimWidths)
    {
        this.InfoPoints.GWidths       = WidthsPoints;
        this.InfoPoints.GPoints       = Points;
        this.InfoPoints.GMaxDimWidths = MaxDimWidths;
        // точки выравнивания данного контента содержатся в ContentPoints

        var PosInfo = new CMathPointInfo();
        PosInfo.SetInfoPoints(this.InfoPoints);

        this.size.width = 0;

        for(var i = 0 ; i < this.Content.length; i++)
        {
            if(this.Content[i].Type === para_Math_Run)
            {
                this.Content[i].ApplyPoints(PosInfo);
            }

            this.size.width += this.Content[i].size.width;
        }

    },
    setPosition: function(pos)
    {
        this.pos.x = pos.x;
        this.pos.y = pos.y;

        var w = 0;
        if(this.RecalcInfo.bEqqArray)
        {
            var PosInfo = new CMathPointInfo();
            PosInfo.SetInfoPoints(this.InfoPoints);

            this.pos.x += PosInfo.GetAlign();
        }

        for(var i=0; i < this.Content.length; i++)
        {
            var NewPos = new CMathPosition();
            NewPos.x = this.pos.x + w;
            NewPos.y = this.pos.y + this.size.ascent;

            if(this.Content[i].Type == para_Math_Run)
                this.Content[i].Math_SetPosition(NewPos);
            else
                this.Content[i].setPosition(NewPos);

            w += this.Content[i].size.width;
        }

    },
    SetParent: function(Parent, ParaMath)
    {
        this.Parent   = Parent;
        this.ParaMath = ParaMath;
    },
    ///// properties /////
    hidePlaceholder: function(flag)
    {
        this.plhHide = flag;
    },
    ///////// RunPrp, CtrPrp
    getFirstRPrp:    function(ParaMath)
    {
        return this.Content[0].Get_CompiledPr(true);
    },
    GetCtrPrp: function()       // for placeholder
    {
        var ctrPrp = new CTextPr();
        if(!this.bRoot)
            ctrPrp.Merge( this.Parent.Get_CompiledCtrPrp_2() );

        return ctrPrp;
    },
    IsAccent: function()
    {
        var result = false;

        if(!this.bRoot)
            result = this.Parent.IsAccent();

        return result;
    },
    ////////////////////////
    /// For Para Math
    GetParent: function()
    {
        return this.Parent.GetParent();
    },
    SetArgSize: function(val)
    {
        this.ArgSize.SetValue(val);
    },
    GetArgSize: function()
    {
        return this.ArgSize.value;
    },
    /////////   Перемещение     ////////////

    // Поиск позиции, селект
    Is_SelectedAll: function(Props)
    {
        var bFirst = false, bEnd = false;

        if(this.Selection.Start == 0 && this.Selection.End == this.Content.length - 1)
        {
            if(this.Content[this.Selection.Start].Type == para_Math_Run)
                bFirst = this.Content[this.Selection.Start].Is_SelectedAll(Props);
            else
                bFirst = true;

            if(this.Content[this.Selection.End].Type == para_Math_Run)
                bEnd = this.Content[this.Selection.End].Is_SelectedAll(Props);
            else
                bEnd = true;
        }

        return bFirst && bEnd;
    },

    ///////////////////////

    Get_Id : function()
    {
        return this.GetId();
    },
    GetId : function()
    {
        return this.Id;
    },

    private_CorrectContent : function()
    {
        var len = this.Content.length;

        var current = null;
        var emptyRun, ctrPrp, mathPrp;

        var currPos = 0;

        while(currPos < len)
        {
            current = this.Content[currPos];

            var bLeftRun  = currPos > 0 ? this.Content[currPos-1].Type == para_Math_Run : false,
                bRightRun = currPos < len - 1 ? this.Content[currPos + 1].Type === para_Math_Run : false;

            var bCurrComp = current.Type == para_Math_Composition,
                bCurrEmptyRun = current.Type == para_Math_Run && current.Is_Empty();

            var bDeleteEmptyRun = bCurrEmptyRun && (bLeftRun || bRightRun);

            if(bCurrComp && !bLeftRun) // добавление пустого Run перед мат объектом
            {
                emptyRun = new ParaRun(null, true);

                ctrPrp = current.Get_CtrPrp();

                mathPrp = new CMPrp();

                mathPrp.SetStyle(ctrPrp.Bold, ctrPrp.Italic);

                emptyRun.Set_MathPr(mathPrp);

                ctrPrp.Bold   = undefined;
                ctrPrp.Italic = undefined;

                emptyRun.Set_Pr(ctrPrp);

                this.Internal_Content_Add(currPos, emptyRun);
                currPos += 2;
            }
            else if(bDeleteEmptyRun)
            {
                this.Remove_FromContent(currPos, 1);

                if (this.CurPos === currPos)
                {
                    if (bLeftRun)
                    {
                        this.CurPos = currPos - 1;
                        this.Content[this.CurPos].Cursor_MoveToEndPos(false);
                    }
                    else //if (bRightRun)
                    {
                        this.CurPos = currPos;
                        this.Content[this.CurPos].Cursor_MoveToStartPos();
                    }
                }
            }
            else
                currPos++;

            len = this.Content.length;
        }


        if(len > 0 && this.Content[len - 1].Type == para_Math_Composition)
        {
            emptyRun = new ParaRun(null, true);

            ctrPrp = current.Get_CtrPrp();

            mathPrp = new CMPrp();
            mathPrp.SetStyle(ctrPrp.Bold, ctrPrp.Italic);

            emptyRun.Set_MathPr(mathPrp);

            ctrPrp.Bold   = undefined;
            ctrPrp.Italic = undefined;

            emptyRun.Set_Pr(ctrPrp);

            this.Internal_Content_Add(len, emptyRun);
        }
    },

    Correct_Content : function(bInnerCorrection)
    {
        if (true === bInnerCorrection)
        {
            for (var nPos = 0, nCount = this.Content.length; nPos < nCount; nPos++)
            {
                if (para_Math_Composition === this.Content[nPos].Type)
                    this.Content[nPos].Correct_Content(true);
            }
        }

        this.private_CorrectContent();

        // Удаляем лишние пустые раны
        for (var nPos = 0, nLen = this.Content.length; nPos < nLen - 1; nPos++)
        {
            var oCurrElement = this.Content[nPos];
            var oNextElement = this.Content[nPos + 1];
            if (para_Math_Run === oCurrElement.Type && para_Math_Run === oNextElement.Type)
            {
                if (oCurrElement.Is_Empty())
                {
                    this.Remove_FromContent(nPos);
                    nPos--;
                    nLen--;
                }
                else if (oNextElement.Is_Empty())
                {
                    this.Remove_FromContent(nPos + 1);
                    nPos--;
                    nLen--;
                }
            }

            if(para_Math_Run === oCurrElement.Type)
                oCurrElement.Math_Correct_Content();
        }

        // Если в контенте ничего нет, тогда добавляем пустой ран
        if (this.Content.length < 1)
        {
            this.Add_ToContent(0, new ParaRun(null, true));
        }

        for (var nPos = 0, nCount = this.Content.length; nPos < nCount; nPos++)
        {
            if(para_Math_Run === this.Content[nPos].Type)
                this.Content[nPos].Math_Correct_Content();
        }

        if (this.Content.length == 1)
        {
            if(this.Content[0].Is_Empty())
                this.Content[0].fillPlaceholders();
        }
    },

    Correct_ContentPos : function(nDirection)
    {
        var nCurPos = this.CurPos;

        if (nCurPos < 0)
        {
            this.CurPos = 0;
            this.Content[0].Cursor_MoveToStartPos();
        }
        else if (nCurPos > this.Content.length - 1)
        {
            this.CurPos = this.Content.length - 1;
            this.Content[this.CurPos].Cursor_MoveToEndPos();
        }
        else if (para_Math_Run !== this.Content[nCurPos].Type)
        {
            if (nDirection > 0)
            {
                this.CurPos = nCurPos + 1;
                this.Content[this.CurPos].Cursor_MoveToStartPos();
            }
            else
            {
                this.CurPos = nCurPos - 1;
                this.Content[this.CurPos].Cursor_MoveToEndPos();
            }
        }
    },

    /// функции для работы с курсором
    Cursor_Is_Start: function()
    {
        var result = false;

        if( !this.Is_Empty() )
        {
            if(this.CurPos == 0)
                result = this.Content[0].Cursor_Is_Start();
        }

        return result;
    },
    Cursor_Is_End: function()
    {
        var result = false;

        if(!this.Is_Empty())
        {
            var len = this.Content.length - 1;
            if(this.CurPos == len)
            {
                result = this.Content[len].Cursor_Is_End();
            }
        }

        return result;
    },
    //////////////////////////////////////

    /////////////////////////
    //  Text Properties
    ///////////////
    Get_TextPr: function(ContentPos, Depth)
    {
        var pos = ContentPos.Get(Depth);

        var TextPr;

        if(this.IsPlaceholder())
            TextPr = this.Parent.Get_CtrPrp();
        else
            TextPr = this.Content[pos].Get_TextPr(ContentPos, Depth + 1);

        return TextPr;
    },
    Get_CompiledTextPr : function(Copy, bAll)
    {
        var TextPr = null;

        if(this.IsPlaceholder())
        {
            TextPr = this.Parent.Get_CompiledCtrPrp_2();
        }
        else if (this.Selection.Use || bAll == true)
        {
            var StartPos, EndPos;

            if(bAll == true)
            {
                StartPos = 0;
                EndPos = this.Content.length - 1;
            }
            else
            {
                StartPos = this.Selection.Start;
                EndPos   = this.Selection.End;

                if ( StartPos > EndPos )
                {
                    StartPos = this.Selection.End;
                    EndPos   = this.Selection.Start;
                }
            }


            // пропускаем пустые рана только для случая, когда есть селект

            while ( null === TextPr && StartPos <= EndPos )
            {
                var bComp = this.Content[StartPos].Type == para_Math_Composition,
                    bEmptyRun = this.Content[StartPos].Type == para_Math_Run && true === this.Content[StartPos].Selection_IsEmpty();

                if(bComp || !bEmptyRun || bAll)    //пропускаем пустые Run
                    TextPr = this.Content[StartPos].Get_CompiledTextPr(true);

                StartPos++;
            }

            while(this.Content[EndPos].Type == para_Math_Run && true === this.Content[EndPos].Selection_IsEmpty() && StartPos < EndPos + 1 && bAll == false) //пропускаем пустые Run
            {
                EndPos--;
            }


            for ( var CurPos = StartPos; CurPos < EndPos + 1; CurPos++ )
            {
                //var CurTextPr = this.Content[CurPos].Get_CompiledPr(false);
                var CurTextPr = this.Content[CurPos].Get_CompiledTextPr(false);

                if ( null !== CurTextPr )
                    TextPr = TextPr.Compare( CurTextPr );
            }
        }
        else
        {
            var CurPos = this.CurPos;

            if ( CurPos >= 0 && CurPos < this.Content.length )
                TextPr = this.Content[CurPos].Get_CompiledTextPr(Copy);
        }

        return TextPr;
    },
    GetMathTextPr: function(ContentPos, Depth)
    {
        var pos = ContentPos.Get(Depth);

        return this.Content[pos].GetMathTextPr(ContentPos, Depth + 1);
    },
    Apply_TextPr: function(TextPr, IncFontSize, ApplyToAll)
    {
        if ( true === ApplyToAll )
        {
            for ( var i = 0; i < this.Content.length; i++ )
                this.Content[i].Apply_TextPr( TextPr, IncFontSize, true );
        }
        else
        {
            var StartPos = this.Selection.Start;
            var EndPos   = this.Selection.End;

            var NewRuns;
            var LRun, CRun, RRun;

            var bSelectOneElement = this.Selection.Use && StartPos == EndPos;

            var FirstPos = this.Selection.Use ? Math.min(StartPos, EndPos) : this.CurPos;

            if(FirstPos == 0)
                this.ParaMath.NeedCompiledCtrPr();

            if( !this.Selection.Use || (bSelectOneElement && this.Content[StartPos].Type == para_Math_Run) ) // TextPr меняем только в одном Run
            {
                var Pos = !this.Selection.Use ? this.CurPos :  StartPos;

                NewRuns = this.Content[Pos].Apply_TextPr(TextPr, IncFontSize, false);

                LRun = NewRuns[0];
                CRun = NewRuns[1];
                RRun = NewRuns[2];

                var CRunPos = Pos;

                if(LRun !== null)
                {
                    this.Internal_Content_Add(Pos+1, CRun);
                    CRunPos = Pos + 1;
                }

                if(RRun !== null)
                {
                    this.Internal_Content_Add(CRunPos+1, RRun);
                }

                this.CurPos         = CRunPos;
                this.Selection.Start = CRunPos;
                this.Selection.End   = CRunPos;

            }
            else if(bSelectOneElement && this.Content[StartPos].Type == para_Math_Composition)
            {
                this.Content[StartPos].Apply_TextPr(TextPr, IncFontSize, true);
            }
            else
            {

                if(StartPos > EndPos)
                {
                    var temp = StartPos;
                    StartPos = EndPos;
                    EndPos = temp;
                }


                for(var i = StartPos + 1; i < EndPos; i++)
                    this.Content[i].Apply_TextPr(TextPr, IncFontSize, true );


                if(this.Content[EndPos].Type == para_Math_Run)
                {
                    NewRuns = this.Content[EndPos].Apply_TextPr(TextPr, IncFontSize, false);

                    // LRun - null
                    CRun = NewRuns[1];
                    RRun = NewRuns[2];

                    if(RRun !== null)
                    {
                        this.Internal_Content_Add(EndPos+1, RRun);
                    }

                }
                else
                    this.Content[EndPos].Apply_TextPr(TextPr, IncFontSize, true);


                if(this.Content[StartPos].Type == para_Math_Run)
                {
                    NewRuns = this.Content[StartPos].Apply_TextPr(TextPr, IncFontSize, false);

                    LRun = NewRuns[0];
                    CRun = NewRuns[1];
                    // RRun - null


                    if(LRun !== null)
                    {
                        this.Internal_Content_Add(StartPos+1, CRun);
                    }

                }
                else
                    this.Content[StartPos].Apply_TextPr(TextPr, IncFontSize, true);


                var bStartComposition = this.Content[StartPos].Type == para_Math_Composition || (this.Content[StartPos].Is_Empty() && this.Content[StartPos + 1].Type == para_Math_Composition);
                var bEndCompostion    = this.Content[EndPos].Type == para_Math_Composition || (this.Content[EndPos].Is_Empty()   && this.Content[EndPos - 1].Type == para_Math_Composition);

                if(!bStartComposition)
                {
                    if(this.Selection.Start < this.Selection.End && true === this.Content[this.Selection.Start].Selection_IsEmpty(true) )
                        this.Selection.Start++;
                    else if (this.Selection.End < this.Selection.Start && true === this.Content[this.Selection.End].Selection_IsEmpty(true) )
                        this.Selection.End++;
                }


                if(!bEndCompostion)
                {
                    if(this.Selection.Start < this.Selection.End && true === this.Content[this.Selection.End].Selection_IsEmpty(true) )
                        this.Selection.End--;
                    else if (this.Selection.End < this.Selection.Start && true === this.Content[this.Selection.Start].Selection_IsEmpty(true) )
                        this.Selection.Start--;
                }

            }
        }

    },
    Set_MathTextPr2: function(TextPr, MathPr, bAll, StartPos, Count)
    {
        if(bAll)
        {
            StartPos = 0;
            Count = this.Content.length - 1;
        }

        if(Count < 0 || StartPos + Count > this.Content.length - 1)
            return;

        for(var pos = StartPos; pos <= StartPos + Count; pos++)
            this.Content[pos].Set_MathTextPr2(TextPr, MathPr, true);

    },
    IsNormalTextInRuns: function()
    {
        var flag = true;

        if(this.Selection.Use)
        {
            var StartPos = this.Selection.Start,
                EndPos   = this.Selection.End;

                if ( StartPos > EndPos )
                {
                    StartPos = this.Selection.End;
                    EndPos   = this.Selection.Start;
                }

            for(var i = StartPos; i < EndPos+1; i++)
            {
                var curr = this.Content[i],
                    currType = curr.Type;
                if(currType == para_Math_Composition || (currType == para_Math_Run && false == curr.IsNormalText()))
                {
                    flag = false;
                    break;
                }
            }
        }
        else
            flag = false;

        return flag;
    },
    Internal_Content_Add : function(Pos, Item, bUpdatePosition)
    {
        Item.Set_ParaMath(this.ParaMath);
        Item.Parent = this;

        History.Add( this, { Type : historyitem_Math_AddItem, Pos : Pos, EndPos : Pos, Items : [ Item ] } );
        this.Content.splice( Pos, 0, Item );

        this.private_UpdatePosOnAdd(Pos, bUpdatePosition);
    },

    private_UpdatePosOnAdd: function(Pos, bUpdatePosition)
    {
        if(bUpdatePosition !== false)
        {
            if ( this.CurPos >= Pos )
                this.CurPos++;

            if ( this.Selection.Start >= Pos )
                this.Selection.Start++;

            if ( this.Selection.End >= Pos )
                this.Selection.End++;

            this.private_CorrectSelectionPos();
            this.private_CorrectCurPos();
        }

        // Обновляем позиции в NearestPos
        var NearPosLen = this.NearPosArray.length;
        for ( var Index = 0; Index < NearPosLen; Index++ )
        {
            var HyperNearPos = this.NearPosArray[Index];
            var ContentPos = HyperNearPos.NearPos.ContentPos;
            var Depth      = HyperNearPos.Depth;

            if (ContentPos.Data[Depth] >= Pos)
                ContentPos.Data[Depth]++;
        }
    },
    NeedCompiledCtrPr: function()
    {
        for(var i = 0; i < this.Content.length; i++)
            if(this.Content[i].Type == para_Math_Composition)
                this.Content[i].NeedCompiledCtrPr();

    },
    private_CorrectSelectionPos : function()
    {
        this.Selection.Start = Math.max(0, Math.min(this.Content.length - 1, this.Selection.Start));
        this.Selection.End   = Math.max(0, Math.min(this.Content.length - 1, this.Selection.End));
    },

    private_CorrectCurPos : function()
    {
        if (this.CurPos > this.Content.length - 1)
        {
            this.CurPos = this.Content.length - 1;

            if (para_Math_Run === this.Content[this.CurPos].Type)
                this.Content[this.CurPos].Cursor_MoveToEndPos(false);
        }

        if (this.CurPos < 0)
        {
            this.CurPos = this.Content.length - 1;

            if (para_Math_Run === this.Content[this.CurPos].Type)
                this.Content[this.CurPos].Cursor_MoveToStartPos();
        }
    },

    SplitContent: function(NewContent, ContentPos, Depth)
    {
        var Pos = ContentPos.Get(Depth);

        if(para_Math_Run === this.Content[Pos].Type)
        {
            var NewRun = this.Content[Pos].Split(ContentPos, Depth+1);
            NewContent.Add_ToContent(0, NewRun);

            var len = this.Content.length;
            if(Pos < len - 1)
            {
                NewContent.Concat_ToContent( this.Content.slice(Pos + 1) );
                this.Remove_FromContent(Pos+1, len - Pos - 1);
            }
        }

        this.private_SetNeedResize();
    },
    Add_ToContent : function(Pos, Item)
    {
        this.Internal_Content_Add(Pos, Item);
    },
    Concat_ToContent: function(NewItems)
    {
        var StartPos = this.Content.length;
        this.Content = this.Content.concat( NewItems );

        History.Add( this, { Type : historyitem_Math_AddItem, Pos : StartPos, EndPos : this.Content.length - 1, Items : NewItems } );
    },

    Remove_FromContent : function(Pos, Count)
    {
        var DeletedItems = this.Content.splice(Pos, Count);
        History.Add( this, { Type : historyitem_Math_RemoveItem, Pos : Pos, EndPos : Pos + Count - 1, Items : DeletedItems } );

        // Обновим текущую позицию
        if (this.CurPos > Pos + Count)
            this.CurPos -= Count;
        else if (this.CurPos > Pos )
            this.CurPos = Pos;

        this.private_CorrectCurPos();
        this.private_UpdatePosOnRemove(Pos, Count);
    },

    private_UpdatePosOnRemove : function(Pos, Count)
    {
        // Обновим начало и конец селекта
        if (true === this.Selection.Use)
        {
            if (this.Selection.Start <= this.Selection.End)
            {
                if (this.Selection.Start > Pos + Count)
                    this.Selection.Start -= Count;
                else if (this.Selection.Start > Pos)
                    this.Selection.Start = Pos;

                if (this.Selection.End >= Pos + Count)
                    this.Selection.End -= Count;
                else if (this.Selection.End >= Pos)
                    this.Selection.End = Math.max(0, Pos - 1);
            }
            else
            {
                if (this.Selection.Start >= Pos + Count)
                    this.Selection.Start -= Count;
                else if (this.Selection.Start >= Pos)
                    this.Selection.Start = Math.max(0, Pos - 1);

                if (this.Selection.End > Pos + Count)
                    this.Selection.End -= Count;
                else if (this.Selection.End > Pos)
                    this.Selection.End = Pos;
            }
        }

        // Обновляем позиции в NearestPos
        var NearPosLen = this.NearPosArray.length;
        for (var Index = 0; Index < NearPosLen; Index++)
        {
            var HyperNearPos = this.NearPosArray[Index];
            var ContentPos = HyperNearPos.NearPos.ContentPos;
            var Depth      = HyperNearPos.Depth;

            if (ContentPos.Data[Depth] > Pos + Count)
                ContentPos.Data[Depth] -= Count;
            else if (ContentPos.Data[Depth] > Pos)
                ContentPos.Data[Depth] = Math.max(0 , Pos);
        }
    },

    Get_Default_TPrp: function()
    {
        return this.ParaMath.Get_Default_TPrp();
    },

    /////////////////////////
    Is_Empty:    function()
    {
        return this.Content.length == 0;
    },

    Copy: function(Selected)
    {
        var NewContent = new CMathContent();
        this.CopyTo(NewContent, Selected);
        return NewContent;
    },

    CopyTo : function(OtherContent, Selected)
    {
        var nStartPos, nEndPos;

        if(true === Selected)
        {
            if(this.Selection.Start < this.Selection.End)
            {
                nStartPos = this.Selection.Start;
                nEndPos   = this.Selection.End;
            }
            else
            {
                nStartPos = this.Selection.End;
                nEndPos   = this.Selection.Start;
            }
        }
        else
        {
            nStartPos = 0;
            nEndPos   = this.Content.length - 1;
        }

        OtherContent.plHid = this.plhHide;

        for(var nPos = nStartPos; nPos <= nEndPos; nPos++)
        {
            var oElement;
            if(this.Content[nPos].Type == para_Math_Run)
                oElement = this.Content[nPos].Copy(Selected);
            else
                oElement = this.Content[nPos].Copy(false);

            OtherContent.Internal_Content_Add(OtherContent.Content.length, oElement);
        }
    },

    getElem: function(nNum)
    {
        return this.Content[nNum];
    },
    Is_FirstComposition: function()
    {
        var result = false;
        if(this.Content.length > 1)
        {
            var bEmptyRun = this.Content[0].Is_Empty(),
                bMathComp    = this.Content[1].Type == para_Math_Composition;

            if(bEmptyRun && bMathComp)
                result = true;
        }

        return result;
    },

    ////////////////////////////////////////////////////////////////

    Undo: function(Data)
    {
        var type = Data.Type;

        switch(type)
        {
            case historyitem_Math_AddItem:
            {
                this.Content.splice(Data.Pos, Data.EndPos - Data.Pos + 1);

                if (null !== this.ParaMath)
                    this.ParaMath.SetNeedResize();

                break;
            }
            case historyitem_Math_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);

                if (null !== this.ParaMath)
                    this.ParaMath.SetNeedResize();

                break;
            }
        }
    },
    Redo: function(Data)
    {
        var type = Data.Type;

        switch(type)
        {
            case historyitem_Math_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);

                if (null !== this.ParaMath)
                    this.ParaMath.SetNeedResize();

                break;
            }
            case historyitem_Math_RemoveItem:
            {
                this.Content.splice(Data.Pos, Data.EndPos - Data.Pos + 1);

                if (null !== this.ParaMath)
                    this.ParaMath.SetNeedResize();

                break;
            }
        }
    },	
    Save_Changes: function(Data, Writer)
    {
        Writer.WriteLong(historyitem_type_MathContent);

        var Type = Data.Type;
        // Пишем тип
        Writer.WriteLong(Type);

        switch (Type)
        {
            case historyitem_Math_AddItem:
            {
                // Long     : Количество элементов
                // Array of :
                //  {
                //    Long     : Позиция
                //    Variable : Id элемента
                //  }

                var Count = Data.Items.length;

                Writer.WriteLong(Count);

                for (var Index = 0; Index < Count; Index++)
                {
                    Writer.WriteLong(Data.Pos + Index);
                    Writer.WriteString2(Data.Items[Index].Get_Id());
                }

                break;
            }
            case historyitem_Math_RemoveItem:
            {
                // Long          : Количество удаляемых элементов
                // Array of Long : позиции удаляемых элементов

                var Count = Data.Items.length;

                Writer.WriteLong(Count);
                for (var Index = 0; Index < Count; Index++)
                {
                    Writer.WriteLong(Data.Pos);
                }

                break;
            }
        }
    },
    Load_Changes : function(Reader)
    {
        // Сохраняем изменения из тех, которые используются для Undo/Redo в бинарный файл.
        // Long : тип класса
        // Long : тип изменений

        var ClassType = Reader.GetLong();
        if ( historyitem_type_MathContent != ClassType )
            return;

        var Type = Reader.GetLong();

        switch ( Type )
        {
            case  historyitem_Math_AddItem:
            {
                // Long     : Количество элементов
                // Array of :
                //  {
                //    Long     : Позиция
                //    Variable : Id Элемента
                //  }

                var Count = Reader.GetLong();

                for ( var Index = 0; Index < Count; Index++ )
                {
                    var Pos     = Reader.GetLong();
                    var Element = g_oTableId.Get_ById( Reader.GetString2() );

                    if ( null != Element )
                        this.Content.splice(Pos, 0, Element);
                }

                this.private_SetNeedResize();

                break;
            }
			case historyitem_Math_RemoveItem:
            {
                // Long          : Количество удаляемых элементов
                // Array of Long : позиции удаляемых элементов

                var Count = Reader.GetLong();

                for ( var Index = 0; Index < Count; Index++ )
                {
                    var ChangesPos = Reader.GetLong();
                    this.Content.splice(ChangesPos, 1);
                }

                this.private_SetNeedResize();

                break;
            }
        }
    },
    Write_ToBinary2 : function(Writer)
    {
        Writer.WriteLong(historyitem_type_MathContent);

        // Long : Id
        Writer.WriteString2(this.Id);
    },
    Read_FromBinary2 : function(Reader)
    {
        // Long : Id
        this.Id = Reader.GetString2();
    },
    Refresh_RecalcData: function()
    {
        if(this.ParaMath !== null)
            this.ParaMath.Refresh_RecalcData(); // Refresh_RecalcData сообщает родительскому классу, что у него произошли изменения, нужно пересчитать
    },

    Insert_MathContent : function(oMathContent, Pos, bSelect)
    {
        if (null === this.ParaMath || null === this.ParaMath.Paragraph)
            bSelect = false;

        if (undefined === Pos)
            Pos = this.CurPos;

        var nCount = oMathContent.Content.length;
        for (var nIndex = 0; nIndex < nCount; nIndex++)
        {
            this.Internal_Content_Add(Pos + nIndex, oMathContent.Content[nIndex], false);

            if (true === bSelect)
            {
                oMathContent.Content[nIndex].Select_All();
            }
        }

        if (null !== this.ParaMath)
            this.ParaMath.SetNeedResize();

        this.CurPos = Pos + nCount;

        if (true === bSelect)
        {
            this.Selection.Use = true;
            this.Selection.Start = Pos;
            this.Selection.End   = Pos + nCount - 1;

            if (!this.bRoot)
                this.ParentElement.Select_MathContent(this);
            else
                this.ParaMath.bSelectionUse = true;

            this.ParaMath.Paragraph.Select_Math(this.ParaMath);
        }

        this.Correct_Content(true);
        this.Correct_ContentPos(-1);
    }
};
CMathContent.prototype.Set_Paragraph    = ParaHyperlink.prototype.Set_Paragraph;
CMathContent.prototype.Get_ElementByPos = ParaHyperlink.prototype.Get_ElementByPos;
CMathContent.prototype.Set_ParaMath = function(ParaMath)
{
    this.ParaMath = ParaMath;

    for (var Index = 0, Count = this.Content.length; Index < Count; Index++)
    {
        this.Content[Index].Set_ParaMath(ParaMath);
    }
};
CMathContent.prototype.Load_FromMenu = function(Type, Paragraph)
{
    this.Paragraph = Paragraph;

    var Pr = {ctrPrp: new CTextPr()};

    var MainType = Type >> 24;

    if (MainType === c_oAscMathMainType.Symbol)
        this.private_LoadFromMenuSymbol(Type, Pr);
    else if (MainType === c_oAscMathMainType.Fraction)
        this.private_LoadFromMenuFraction(Type, Pr);
    else if (MainType === c_oAscMathMainType.Script)
        this.private_LoadFromMenuScript(Type, Pr);
    else if (MainType === c_oAscMathMainType.Radical)
        this.private_LoadFromMenuRadical(Type, Pr);
    else if (MainType === c_oAscMathMainType.Integral)
        this.private_LoadFromMenuIntegral(Type, Pr);
    else if (MainType === c_oAscMathMainType.LargeOperator)
        this.private_LoadFromMenuLargeOperator(Type, Pr);
    else if (MainType === c_oAscMathMainType.Bracket)
        this.private_LoadFromMenuBracket(Type, Pr);
    else if (MainType === c_oAscMathMainType.Function)
        this.private_LoadFromMenuFunction(Type, Pr);
    else if (MainType === c_oAscMathMainType.Accent)
        this.private_LoadFromMenuAccent(Type, Pr);
    else if (MainType === c_oAscMathMainType.LimitLog)
        this.private_LoadFromMenuLimitLog(Type, Pr);
    else if (MainType === c_oAscMathMainType.Operator)
        this.private_LoadFromMenuOperator(Type, Pr);
    else if (MainType === c_oAscMathMainType.Matrix)
        this.private_LoadFromMenuMatrix(Type, Pr);
};
CMathContent.prototype.private_LoadFromMenuSymbol = function(Type, Pr)
{
    var Code = -1;

    switch (Type)
    {
        case c_oAscMathType.Symbol_pm            : Code = 0x00B1; break;
        case c_oAscMathType.Symbol_infinity      : Code = 0x221E; break;
        case c_oAscMathType.Symbol_equals        : Code = 0x003D; break;
        case c_oAscMathType.Symbol_neq           : Code = 0x2260; break;
        case c_oAscMathType.Symbol_about         : Code = 0x007E; break;
        case c_oAscMathType.Symbol_times         : Code = 0x00D7; break;
        case c_oAscMathType.Symbol_div           : Code = 0x00F7; break;
        case c_oAscMathType.Symbol_factorial     : Code = 0x0021; break;
        case c_oAscMathType.Symbol_propto        : Code = 0x221D; break;
        case c_oAscMathType.Symbol_less          : Code = 0x003C; break;
        case c_oAscMathType.Symbol_ll            : Code = 0x226A; break;
        case c_oAscMathType.Symbol_greater       : Code = 0x003E; break;
        case c_oAscMathType.Symbol_gg            : Code = 0x226B; break;
        case c_oAscMathType.Symbol_leq           : Code = 0x2264; break;
        case c_oAscMathType.Symbol_geq           : Code = 0x2265; break;
        case c_oAscMathType.Symbol_mp            : Code = 0x2213; break;
        case c_oAscMathType.Symbol_cong          : Code = 0x2245; break;
        case c_oAscMathType.Symbol_approx        : Code = 0x2248; break;
        case c_oAscMathType.Symbol_equiv         : Code = 0x2261; break;
        case c_oAscMathType.Symbol_forall        : Code = 0x2200; break;
        case c_oAscMathType.Symbol_additional    : Code = 0x2201; break;
        case c_oAscMathType.Symbol_partial       : Code = 0x1D715; break;
        case c_oAscMathType.Symbol_sqrt          : this.Add_Radical(Pr, null, null); break;
        case c_oAscMathType.Symbol_cbrt          : this.Add_Radical({ctrPrp : Pr.ctrPrp, type : DEGREE_RADICAL}, null, "3"); break;
        case c_oAscMathType.Symbol_qdrt          : this.Add_Radical({ctrPrp : Pr.ctrPrp, type : DEGREE_RADICAL}, null, "4"); break;
        case c_oAscMathType.Symbol_cup           : Code = 0x222A; break;
        case c_oAscMathType.Symbol_cap           : Code = 0x2229; break;
        case c_oAscMathType.Symbol_emptyset      : Code = 0x2205; break;
        case c_oAscMathType.Symbol_percent       : Code = 0x0025; break;
        case c_oAscMathType.Symbol_degree        : Code = 0x00B0; break;
        case c_oAscMathType.Symbol_fahrenheit    : Code = 0x2109; break;
        case c_oAscMathType.Symbol_celsius       : Code = 0x2103; break;
        case c_oAscMathType.Symbol_inc           : Code = 0x2206; break;
        case c_oAscMathType.Symbol_nabla         : Code = 0x2207; break;
        case c_oAscMathType.Symbol_exists        : Code = 0x2203; break;
        case c_oAscMathType.Symbol_notexists     : Code = 0x2204; break;
        case c_oAscMathType.Symbol_in            : Code = 0x2208; break;
        case c_oAscMathType.Symbol_ni            : Code = 0x220B; break;
        case c_oAscMathType.Symbol_leftarrow     : Code = 0x2190; break;
        case c_oAscMathType.Symbol_uparrow       : Code = 0x2191; break;
        case c_oAscMathType.Symbol_rightarrow    : Code = 0x2192; break;
        case c_oAscMathType.Symbol_downarrow     : Code = 0x2193; break;
        case c_oAscMathType.Symbol_leftrightarrow: Code = 0x2194; break;
        case c_oAscMathType.Symbol_therefore     : Code = 0x2234; break;
        case c_oAscMathType.Symbol_plus          : Code = 0x002B; break;
        case c_oAscMathType.Symbol_minus         : Code = 0x2212; break;
        case c_oAscMathType.Symbol_not           : Code = 0x00AC; break;
        case c_oAscMathType.Symbol_ast           : Code = 0x2217; break;
        case c_oAscMathType.Symbol_bullet        : Code = 0x2219; break;
        case c_oAscMathType.Symbol_vdots         : Code = 0x22EE; break;
        case c_oAscMathType.Symbol_cdots         : Code = 0x22EF; break;
        case c_oAscMathType.Symbol_rddots        : Code = 0x22F0; break;
        case c_oAscMathType.Symbol_ddots         : Code = 0x22F1; break;
        case c_oAscMathType.Symbol_aleph         : Code = 0x2135; break;
        case c_oAscMathType.Symbol_beth          : Code = 0x2136; break;
        case c_oAscMathType.Symbol_QED           : Code = 0x220E; break;
        case c_oAscMathType.Symbol_alpha         : Code = 0x1D6FC; break;
        case c_oAscMathType.Symbol_beta          : Code = 0x1D6FD; break;
        case c_oAscMathType.Symbol_gamma         : Code = 0x1D6FE; break;
        case c_oAscMathType.Symbol_delta         : Code = 0x1D6FF; break;
        case c_oAscMathType.Symbol_varepsilon    : Code = 0x1D700; break;
        case c_oAscMathType.Symbol_epsilon       : Code = 0x1D716; break;
        case c_oAscMathType.Symbol_zeta          : Code = 0x1D701; break;
        case c_oAscMathType.Symbol_eta           : Code = 0x1D702; break;
        case c_oAscMathType.Symbol_theta         : Code = 0x1D703; break;
        case c_oAscMathType.Symbol_vartheta      : Code = 0x1D717; break;
        case c_oAscMathType.Symbol_iota          : Code = 0x1D704; break;
        case c_oAscMathType.Symbol_kappa         : Code = 0x1D705; break;
        case c_oAscMathType.Symbol_lambda        : Code = 0x1D706; break;
        case c_oAscMathType.Symbol_mu            : Code = 0x1D707; break;
        case c_oAscMathType.Symbol_nu            : Code = 0x1D708; break;
        case c_oAscMathType.Symbol_xsi           : Code = 0x1D709; break;
        case c_oAscMathType.Symbol_o             : Code = 0x1D70A; break;
        case c_oAscMathType.Symbol_pi            : Code = 0x1D70B; break;
        case c_oAscMathType.Symbol_varpi         : Code = 0x1D71B; break;
        case c_oAscMathType.Symbol_rho           : Code = 0x1D70C; break;
        case c_oAscMathType.Symbol_varrho        : Code = 0x1D71A; break;
        case c_oAscMathType.Symbol_sigma         : Code = 0x1D70E; break;
        case c_oAscMathType.Symbol_varsigma      : Code = 0x1D70D; break;
        case c_oAscMathType.Symbol_tau           : Code = 0x1D70F; break;
        case c_oAscMathType.Symbol_upsilon       : Code = 0x1D710; break;
        case c_oAscMathType.Symbol_varphi        : Code = 0x1D711; break;
        case c_oAscMathType.Symbol_phi           : Code = 0x1D719; break;
        case c_oAscMathType.Symbol_chi           : Code = 0x1D712; break;
        case c_oAscMathType.Symbol_psi           : Code = 0x1D713; break;
        case c_oAscMathType.Symbol_omega         : Code = 0x1D714; break;
        case c_oAscMathType.Symbol_Alpha         : Code = 0x0391; break;
        case c_oAscMathType.Symbol_Beta          : Code = 0x0392; break;
        case c_oAscMathType.Symbol_Gamma         : Code = 0x0393; break;
        case c_oAscMathType.Symbol_Delta         : Code = 0x0394; break;
        case c_oAscMathType.Symbol_Epsilon       : Code = 0x0395; break;
        case c_oAscMathType.Symbol_Zeta          : Code = 0x0396; break;
        case c_oAscMathType.Symbol_Eta           : Code = 0x0397; break;
        case c_oAscMathType.Symbol_Theta         : Code = 0x0398; break;
        case c_oAscMathType.Symbol_Iota          : Code = 0x0399; break;
        case c_oAscMathType.Symbol_Kappa         : Code = 0x039A; break;
        case c_oAscMathType.Symbol_Lambda        : Code = 0x039B; break;
        case c_oAscMathType.Symbol_Mu            : Code = 0x039C; break;
        case c_oAscMathType.Symbol_Nu            : Code = 0x039D; break;
        case c_oAscMathType.Symbol_Xsi           : Code = 0x039E; break;
        case c_oAscMathType.Symbol_O             : Code = 0x039F; break;
        case c_oAscMathType.Symbol_Pi            : Code = 0x03A0; break;
        case c_oAscMathType.Symbol_Rho           : Code = 0x03A1; break;
        case c_oAscMathType.Symbol_Sigma         : Code = 0x03A3; break;
        case c_oAscMathType.Symbol_Tau           : Code = 0x03A4; break;
        case c_oAscMathType.Symbol_Upsilon       : Code = 0x03A5; break;
        case c_oAscMathType.Symbol_Phi           : Code = 0x03A6; break;
        case c_oAscMathType.Symbol_Chi           : Code = 0x03A7; break;
        case c_oAscMathType.Symbol_Psi           : Code = 0x03A8; break;
        case c_oAscMathType.Symbol_Omega         : Code = 0x03A9; break;
    }

    if (-1 !== Code)
        this.Add_Symbol(Code);
};
CMathContent.prototype.private_LoadFromMenuFraction = function(Type, Pr)
{
    switch (Type)
    {
        case c_oAscMathType.FractionVertical   : this.Add_Fraction(Pr, null, null); break;
        case c_oAscMathType.FractionDiagonal   : this.Add_Fraction({ctrPrp : Pr.ctrPrp, type : SKEWED_FRACTION}, null, null); break;
        case c_oAscMathType.FractionHorizontal : this.Add_Fraction({ctrPrp : Pr.ctrPrp, type : LINEAR_FRACTION}, null, null); break;
        case c_oAscMathType.FractionSmall:
            var oBox = new CBox(Pr);
            this.Add_Element(oBox)
            var BoxMathContent = oBox.getBase();
            BoxMathContent.Add_Fraction(Pr, null, null);
            break;

        case c_oAscMathType.FractionDifferential_1: this.Add_Fraction(Pr, "dx", "dy"); break;
        case c_oAscMathType.FractionDifferential_2: this.Add_Fraction(Pr, String.fromCharCode(916) + "y", String.fromCharCode(916) + "x"); break;
        case c_oAscMathType.FractionDifferential_3: this.Add_Fraction(Pr, String.fromCharCode(8706) + "y", String.fromCharCode(8706) + "x"); break;
        case c_oAscMathType.FractionDifferential_4: this.Add_Fraction(Pr, String.fromCharCode(948) + "y", String.fromCharCode(948) + "x"); break;
        case c_oAscMathType.FractionPi_2          : this.Add_Fraction(Pr, String.fromCharCode(960), "2"); break;
    }
};
CMathContent.prototype.private_LoadFromMenuScript = function(Type, Pr)
{
    switch (Type)
    {
        case c_oAscMathType.ScriptSup: this.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, null, null, null); break;
        case c_oAscMathType.ScriptSub: this.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUBSCRIPT}, null, null, null); break;
        case c_oAscMathType.ScriptSubSup: this.Add_Script(true, {ctrPrp : Pr.ctrPrp, type : DEGREE_SubSup}, null, null, null); break;
        case c_oAscMathType.ScriptSubSupLeft:this.Add_Script(true, {ctrPrp : Pr.ctrPrp, type : DEGREE_PreSubSup}, null, null, null); break;
        case c_oAscMathType.ScriptCustom_1:
            Pr.type = DEGREE_SUBSCRIPT;
            var Script = this.Add_Script(false, Pr, "x", null, null);
            var SubMathContent = Script.getLowerIterator();
            Pr.type = DEGREE_SUPERSCRIPT;
            SubMathContent.Add_Script(false, Pr, "y", "2", null);
            break;

        case c_oAscMathType.ScriptCustom_2: this.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "e", "-i" + String.fromCharCode(969) + "t", null); break;
        case c_oAscMathType.ScriptCustom_3: this.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "x", "2", null); break;
        case c_oAscMathType.ScriptCustom_4: this.Add_Script(true, {ctrPrp : Pr.ctrPrp, type : DEGREE_PreSubSup}, "Y", "n", "1"); break;
    }
};
CMathContent.prototype.private_LoadFromMenuRadical = function(Type, Pr)
{
    switch (Type)
    {
        case c_oAscMathType.RadicalSqrt:
            Pr.type    = SQUARE_RADICAL;
            Pr.degHide = true;
            this.Add_Radical(Pr, null, null);
            break;

        case c_oAscMathType.RadicalRoot_n:
            Pr.type = DEGREE_RADICAL;
            this.Add_Radical(Pr, null, null);
            break;

        case c_oAscMathType.RadicalRoot_2:
            Pr.type = DEGREE_RADICAL;
            this.Add_Radical(Pr, null, "2");
            break;

        case c_oAscMathType.RadicalRoot_3:
            Pr.type = DEGREE_RADICAL;
            this.Add_Radical(Pr, null, "3");
            break;

        case c_oAscMathType.RadicalCustom_1:
            var Fraction = this.Add_Fraction(Pr, null, null);
            var NumMathContent = Fraction.getNumeratorMathContent();
            var DenMathContent = Fraction.getDenominatorMathContent();

            NumMathContent.Add_Text("-b" + String.fromCharCode(177));
            Pr.type    = SQUARE_RADICAL;
            Pr.degHide = true;
            var Radical = NumMathContent.Add_Radical(Pr, null, null);
            var RadicalBaseMathContent = Radical.getBase();
            RadicalBaseMathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "b", "2", null);
            RadicalBaseMathContent.Add_Text("-4ac");

            DenMathContent.Add_Text("2a");

            break;
        case c_oAscMathType.RadicalCustom_2:
            Pr.type    = SQUARE_RADICAL;
            Pr.degHide = true;
            var Radical = this.Add_Radical(Pr, null, null);
            var BaseMathContent = Radical.getBase();

            var ScriptPr = {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT};
            BaseMathContent.Add_Script(false, ScriptPr, "a", "2", null);
            BaseMathContent.Add_Text("+");
            BaseMathContent.Add_Script(false, ScriptPr, "b", "2", null);
            break;
    }
};
CMathContent.prototype.private_LoadFromMenuIntegral = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.Integral:                           this.Add_Integral(1, false, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralSubSup:                     this.Add_Integral(1, false, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralCenterSubSup:               this.Add_Integral(1, false, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralDouble:                     this.Add_Integral(2, false, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralDoubleSubSup:               this.Add_Integral(2, false, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralDoubleCenterSubSup:         this.Add_Integral(2, false, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralTriple:                     this.Add_Integral(3, false, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralTripleSubSup:               this.Add_Integral(3, false, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralTripleCenterSubSup:         this.Add_Integral(3, false, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOriented:                   this.Add_Integral(1,  true, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedSubSup:             this.Add_Integral(1,  true, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedCenterSubSup:       this.Add_Integral(1,  true, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedDouble:             this.Add_Integral(2,  true, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedDoubleSubSup:       this.Add_Integral(2,  true, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedDoubleCenterSubSup: this.Add_Integral(2,  true, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedTriple:             this.Add_Integral(3,  true, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedTripleSubSup:       this.Add_Integral(3,  true, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.IntegralOrientedTripleCenterSubSup: this.Add_Integral(3,  true, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.Integral_dx:     Pr.diff = 1; this.Add_Box(Pr, "dx"); break;
        case c_oAscMathType.Integral_dy:     Pr.diff = 1; this.Add_Box(Pr, "dy"); break;
        case c_oAscMathType.Integral_dtheta: Pr.diff = 1; this.Add_Box(Pr, "d" + String.fromCharCode(952)); break;
    }
};
CMathContent.prototype.private_LoadFromMenuLargeOperator = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.LargeOperator_Sum:              this.Add_LargeOperator(1, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Sum_CenterSubSup: this.Add_LargeOperator(1, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Sum_SubSup:       this.Add_LargeOperator(1, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Sum_CenterSub:    this.Add_LargeOperator(1, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Sum_Sub:          this.Add_LargeOperator(1, NARY_SubSup,  true, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.LargeOperator_Prod:              this.Add_LargeOperator(2, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Prod_CenterSubSup: this.Add_LargeOperator(2, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Prod_SubSup:       this.Add_LargeOperator(2, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Prod_CenterSub:    this.Add_LargeOperator(2, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Prod_Sub:          this.Add_LargeOperator(2, NARY_SubSup,  true, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.LargeOperator_CoProd:              this.Add_LargeOperator(3, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_CoProd_CenterSubSup: this.Add_LargeOperator(3, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_CoProd_SubSup:       this.Add_LargeOperator(3, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_CoProd_CenterSub:    this.Add_LargeOperator(3, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_CoProd_Sub:          this.Add_LargeOperator(3, NARY_SubSup,  true, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.LargeOperator_Union:              this.Add_LargeOperator(4, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Union_CenterSubSup: this.Add_LargeOperator(4, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Union_SubSup:       this.Add_LargeOperator(4, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Union_CenterSub:    this.Add_LargeOperator(4, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Union_Sub:          this.Add_LargeOperator(4, NARY_SubSup,  true, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.LargeOperator_Intersection:              this.Add_LargeOperator(5, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Intersection_CenterSubSup: this.Add_LargeOperator(5, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Intersection_SubSup:       this.Add_LargeOperator(5, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Intersection_CenterSub:    this.Add_LargeOperator(5, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Intersection_Sub:          this.Add_LargeOperator(5, NARY_SubSup,  true, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.LargeOperator_Disjunction:              this.Add_LargeOperator(6, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Disjunction_CenterSubSup: this.Add_LargeOperator(6, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Disjunction_SubSup:       this.Add_LargeOperator(6, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Disjunction_CenterSub:    this.Add_LargeOperator(6, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Disjunction_Sub:          this.Add_LargeOperator(6, NARY_SubSup,  true, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.LargeOperator_Conjunction:              this.Add_LargeOperator(7, NARY_UndOvr,  true,  true, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Conjunction_CenterSubSup: this.Add_LargeOperator(7, NARY_UndOvr, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Conjunction_SubSup:       this.Add_LargeOperator(7, NARY_SubSup, false, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Conjunction_CenterSub:    this.Add_LargeOperator(7, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null); break;
        case c_oAscMathType.LargeOperator_Conjunction_Sub:          this.Add_LargeOperator(7, NARY_SubSup,  true, false, Pr.ctrPrp, null, null, null); break;

        case c_oAscMathType.LargeOperator_Custom_1:
            var Sum = this.Add_LargeOperator(1, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, "k");
            var BaseMathContent = Sum.getBaseMathContent();
            var Delimiter = BaseMathContent.Add_Delimiter({ctrPrp : Pr.ctrPrp, column : 1}, 1, [null]);
            var DelimiterMathContent = Delimiter.getElementMathContent(0);
            DelimiterMathContent.Add_Fraction({ctrPrp: Pr.ctrPrp, type : NO_BAR_FRACTION}, "n", "k");
            break;

        case c_oAscMathType.LargeOperator_Custom_2:
            this.Add_LargeOperator(1, NARY_UndOvr, false, false, Pr.ctrPrp, null, "n", "i=0");
            break;

        case c_oAscMathType.LargeOperator_Custom_3:
            var Sum = this.Add_LargeOperator(1, NARY_UndOvr,  true, false, Pr.ctrPrp, null, null, null);
            var SubMathContent = Sum.getSubMathContent();
            SubMathContent.Add_EqArray({ctrPrp: Pr.ctrPrp, row : 2}, 2, ["0≤ i ≤ m", "0< j < n"]);
            var BaseMathContent = Sum.getBaseMathContent();
            BaseMathContent.Add_Text("P");
            BaseMathContent.Add_Delimiter({ctrPrp : Pr.ctrPrp, column : 1}, 1, ["i, j"]);
            break;

        case c_oAscMathType.LargeOperator_Custom_4:
            var Prod = this.Add_LargeOperator(2, NARY_UndOvr, false, false, Pr.ctrPrp, null, "n", "k=1");
            var BaseMathContent = Prod.getBaseMathContent();
            BaseMathContent.Add_Script(false, {ctrPrp: Pr.ctrPrp, type : DEGREE_SUBSCRIPT}, "A", null, "k");
            break;

        case c_oAscMathType.LargeOperator_Custom_5:
            var Union = this.Add_LargeOperator(4, NARY_UndOvr, false, false, Pr.ctrPrp, null, "m", "n=1");
            var BaseMathContent = Union.getBaseMathContent();
            var Delimiter = BaseMathContent.Add_Delimiter({ctrPrp : Pr.ctrPrp, column : 1}, 1, [null]);
            BaseMathContent = Delimiter.getElementMathContent(0);
            BaseMathContent.Add_Script(false, {ctrPrp: Pr.ctrPrp, type : DEGREE_SUBSCRIPT}, "X", null, "n");
            BaseMathContent.Add_Text(String.fromCharCode(8898));
            BaseMathContent.Add_Script(false, {ctrPrp: Pr.ctrPrp, type : DEGREE_SUBSCRIPT}, "Y", null, "n");
            break;
    }
};
CMathContent.prototype.private_LoadFromMenuBracket = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.Bracket_Round                 : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],  null,  null); break;
        case c_oAscMathType.Bracket_Square                : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    91,    93); break;
        case c_oAscMathType.Bracket_Curve                 : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],   123,   125); break;
        case c_oAscMathType.Bracket_Angle                 : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 10216, 10217); break;
        case c_oAscMathType.Bracket_LowLim                : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 0x230A, 0x230B); break;
        case c_oAscMathType.Bracket_UppLim                : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 0x2308, 0x2309); break;
        case c_oAscMathType.Bracket_Line                  : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],   124,   124); break;
        case c_oAscMathType.Bracket_LineDouble            : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],  8214,  8214); break;
        case c_oAscMathType.Bracket_Square_OpenOpen       : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    91,    91); break;
        case c_oAscMathType.Bracket_Square_CloseClose     : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    93,    93); break;
        case c_oAscMathType.Bracket_Square_CloseOpen      : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    93,    91); break;
        case c_oAscMathType.Bracket_SquareDouble          : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 10214, 10215); break;

        case c_oAscMathType.Bracket_Round_Delimiter_2     : this.Add_DelimiterEx(Pr.ctrPrp, 2, [null, null], null, null); break;
        case c_oAscMathType.Bracket_Curve_Delimiter_2     : this.Add_DelimiterEx(Pr.ctrPrp, 2, [null, null], 123, 125); break;
        case c_oAscMathType.Bracket_Angle_Delimiter_2     : this.Add_DelimiterEx(Pr.ctrPrp, 2, [null, null], 10216, 10217); break;
        case c_oAscMathType.Bracket_Angle_Delimiter_3     : this.Add_DelimiterEx(Pr.ctrPrp, 3, [null, null, null], 10216, 10217); break;

        case c_oAscMathType.Bracket_Round_OpenNone        : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],  null,    -1); break;
        case c_oAscMathType.Bracket_Round_NoneOpen        : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1,  null); break;
        case c_oAscMathType.Bracket_Square_OpenNone       : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    91,    -1); break;
        case c_oAscMathType.Bracket_Square_NoneOpen       : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1,    93); break;
        case c_oAscMathType.Bracket_Curve_OpenNone        : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],   123,    -1); break;
        case c_oAscMathType.Bracket_Curve_NoneOpen        : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1,   125); break;
        case c_oAscMathType.Bracket_Angle_OpenNone        : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 10216,    -1); break;
        case c_oAscMathType.Bracket_Angle_NoneOpen        : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1, 10217); break;
        case c_oAscMathType.Bracket_LowLim_OpenNone       : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 0x230A,    -1); break;
        case c_oAscMathType.Bracket_LowLim_NoneNone       : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1,  0x230B); break;
        case c_oAscMathType.Bracket_UppLim_OpenNone       : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 0x2308,    -1); break;
        case c_oAscMathType.Bracket_UppLim_NoneOpen       : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1,  0x2309); break;
        case c_oAscMathType.Bracket_Line_OpenNone         : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],   124,    -1); break;
        case c_oAscMathType.Bracket_Line_NoneOpen         : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1,   124); break;
        case c_oAscMathType.Bracket_LineDouble_OpenNone   : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],  8214,    -1); break;
        case c_oAscMathType.Bracket_LineDouble_NoneOpen   : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1,  8214); break;
        case c_oAscMathType.Bracket_SquareDouble_OpenNone : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null], 10214,    -1); break;
        case c_oAscMathType.Bracket_SquareDouble_NoneOpen : this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],    -1, 10215); break;

        case c_oAscMathType.Bracket_Custom_1:
            var Delimiter = this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],   123,    -1);
            var BaseMathContent = Delimiter.getElementMathContent(0);
            BaseMathContent.Add_EqArray({ctrPrp : Pr.ctrPrp, row : 2}, 2, [null, null]);
            break;

        case c_oAscMathType.Bracket_Custom_2:
            var Delimiter = this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],   123,    -1);
            var BaseMathContent = Delimiter.getElementMathContent(0);
            BaseMathContent.Add_EqArray({ctrPrp : Pr.ctrPrp, row : 3}, 3, [null, null, null]);
            break;

        case c_oAscMathType.Bracket_Custom_3:
            this.Add_Fraction({ctrPrp : Pr.ctrPrp, type : NO_BAR_FRACTION}, null, null);
            break;

        case c_oAscMathType.Bracket_Custom_4:
            var Delimiter = this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],  null,  null);
            var BaseMathContent = Delimiter.getElementMathContent(0);
            BaseMathContent.Add_Fraction({ctrPrp : Pr.ctrPrp, type : NO_BAR_FRACTION}, null, null);
            break;

        case c_oAscMathType.Bracket_Custom_5:
            this.Add_Text("f");
            this.Add_DelimiterEx(Pr.ctrPrp, 1, ["x"],  null,  null);
            this.Add_Text("=");
            var Delimiter = this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],   123,    -1);
            var BaseMathContent = Delimiter.getElementMathContent(0);
            BaseMathContent.Add_EqArray({ctrPrp : Pr.ctrPrp, row : 2}, 2, ["-x,  &x<0", "x,  &x" + String.fromCharCode(8805) + "0"]);
            break;

        case c_oAscMathType.Bracket_Custom_6:
            var Delimiter = this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],  null,  null);
            var BaseMathContent = Delimiter.getElementMathContent(0);
            BaseMathContent.Add_Fraction({ctrPrp : Pr.ctrPrp, type : NO_BAR_FRACTION}, "n", "k");
            break;

        case c_oAscMathType.Bracket_Custom_7:
            var Delimiter = this.Add_DelimiterEx(Pr.ctrPrp, 1, [null],  10216,  10217);
            var BaseMathContent = Delimiter.getElementMathContent(0);
            BaseMathContent.Add_Fraction({ctrPrp : Pr.ctrPrp, type : NO_BAR_FRACTION}, "n", "k");
            break;
    }
};
CMathContent.prototype.private_LoadFromMenuFunction = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.Function_Sin : this.Add_Function(Pr, "sin", null); break;
        case c_oAscMathType.Function_Cos : this.Add_Function(Pr, "cos", null); break;
        case c_oAscMathType.Function_Tan : this.Add_Function(Pr, "tan", null); break;
        case c_oAscMathType.Function_Csc : this.Add_Function(Pr, "csc", null); break;
        case c_oAscMathType.Function_Sec : this.Add_Function(Pr, "sec", null); break;
        case c_oAscMathType.Function_Cot : this.Add_Function(Pr, "cot", null); break;

        case c_oAscMathType.Function_1_Sin : this.Add_Function_1(Pr, "sin", null); break;
        case c_oAscMathType.Function_1_Cos : this.Add_Function_1(Pr, "cos", null); break;
        case c_oAscMathType.Function_1_Tan : this.Add_Function_1(Pr, "tan", null); break;
        case c_oAscMathType.Function_1_Csc : this.Add_Function_1(Pr, "csc", null); break;
        case c_oAscMathType.Function_1_Sec : this.Add_Function_1(Pr, "sec", null); break;
        case c_oAscMathType.Function_1_Cot : this.Add_Function_1(Pr, "cot", null); break;

        case c_oAscMathType.Function_Sinh : this.Add_Function(Pr, "sinh", null); break;
        case c_oAscMathType.Function_Cosh : this.Add_Function(Pr, "cosh", null); break;
        case c_oAscMathType.Function_Tanh : this.Add_Function(Pr, "tanh", null); break;
        case c_oAscMathType.Function_Csch : this.Add_Function(Pr, "csch", null); break;
        case c_oAscMathType.Function_Sech : this.Add_Function(Pr, "sech", null); break;
        case c_oAscMathType.Function_Coth : this.Add_Function(Pr, "coth", null); break;

        case c_oAscMathType.Function_1_Sinh : this.Add_Function_1(Pr, "sinh", null); break;
        case c_oAscMathType.Function_1_Cosh : this.Add_Function_1(Pr, "cosh", null); break;
        case c_oAscMathType.Function_1_Tanh : this.Add_Function_1(Pr, "tanh", null); break;
        case c_oAscMathType.Function_1_Csch : this.Add_Function_1(Pr, "csch", null); break;
        case c_oAscMathType.Function_1_Sech : this.Add_Function_1(Pr, "sech", null); break;
        case c_oAscMathType.Function_1_Coth : this.Add_Function_1(Pr, "coth", null); break;

        case c_oAscMathType.Function_Custom_1 : this.Add_Function(Pr, "sin", String.fromCharCode(952)); break;
        case c_oAscMathType.Function_Custom_2 : this.Add_Function(Pr, "cos", "2x"); break;
        case c_oAscMathType.Function_Custom_3 :
            var Theta = String.fromCharCode(952);
            this.Add_Function(Pr, "tan", Theta);
            this.Add_Text("=");
            var Fraction = this.Add_Fraction(Pr, null, null);
            var NumMathContent = Fraction.getNumeratorMathContent();
            var DenMathContent = Fraction.getDenominatorMathContent();
            NumMathContent.Add_Function(Pr, "sin", Theta);
            DenMathContent.Add_Function(Pr, "cos", Theta);
            break;
    }
};
CMathContent.prototype.private_LoadFromMenuAccent = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.Accent_Dot       : this.Add_Accent(Pr.ctrPrp, 775, null); break;
        case c_oAscMathType.Accent_DDot      : this.Add_Accent(Pr.ctrPrp, 776, null); break;
        case c_oAscMathType.Accent_DDDot     : this.Add_Accent(Pr.ctrPrp, 8411, null); break;
        case c_oAscMathType.Accent_Hat       : this.Add_Accent(Pr.ctrPrp, null, null); break;
        case c_oAscMathType.Accent_Check     : this.Add_Accent(Pr.ctrPrp, 780, null); break;
        case c_oAscMathType.Accent_Accent    : this.Add_Accent(Pr.ctrPrp, 769, null); break;
        case c_oAscMathType.Accent_Grave     : this.Add_Accent(Pr.ctrPrp, 768, null); break;
        case c_oAscMathType.Accent_Smile     : this.Add_Accent(Pr.ctrPrp, 774, null); break;
        case c_oAscMathType.Accent_Tilde     : this.Add_Accent(Pr.ctrPrp, 771, null); break;
        case c_oAscMathType.Accent_Bar       : this.Add_Accent(Pr.ctrPrp, 773, null); break;
        case c_oAscMathType.Accent_DoubleBar : this.Add_Accent(Pr.ctrPrp, 831, null); break;

        case c_oAscMathType.Accent_CurveBracketTop : this.Add_GroupCharacter({ctrPrp : Pr.ctrPrp, chr : 9182, pos : VJUST_TOP, vertJc : VJUST_BOT}, null ); break;
        case c_oAscMathType.Accent_CurveBracketBot : this.Add_GroupCharacter({ctrPrp : Pr.ctrPrp}, null ); break;
        case c_oAscMathType.Accent_GroupTop:
            var Limit = this.Add_Limit({ctrPrp : Pr.ctrPrp, type : LIMIT_UP}, null, null);
            var MathContent = Limit.getFName();
            MathContent.Add_GroupCharacter({ctrPrp : Pr.ctrPrp, chr : 9182, pos : VJUST_TOP, vertJc : VJUST_BOT}, null );
            break;

        case c_oAscMathType.Accent_GroupBot:
            var Limit = this.Add_Limit({ctrPrp : Pr.ctrPrp, type : LIMIT_LOW}, null, null);
            var MathContent = Limit.getFName();
            MathContent.Add_GroupCharacter({ctrPrp : Pr.ctrPrp}, null );
            break;

        case c_oAscMathType.Accent_ArrowL  : this.Add_Accent(Pr.ctrPrp, 8406, null); break;
        case c_oAscMathType.Accent_ArrowR  : this.Add_Accent(Pr.ctrPrp, 8407, null); break;
        case c_oAscMathType.Accent_ArrowD  : this.Add_Accent(Pr.ctrPrp, 8417, null); break;
        case c_oAscMathType.Accent_HarpoonL: this.Add_Accent(Pr.ctrPrp, 8400, null); break;
        case c_oAscMathType.Accent_HarpoonR: this.Add_Accent(Pr.ctrPrp, 8401, null); break;

        case c_oAscMathType.Accent_BorderBox :
            this.Add_BorderBox(Pr, null);
            break;

        case c_oAscMathType.Accent_BorderBoxCustom :
            var BorderBox = this.Add_BorderBox(Pr, null);
            var MathContent = BorderBox.getBase();
            MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "a", "2", null);
            MathContent.Add_Text("=");
            MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "b", "2", null);
            MathContent.Add_Text("+");
            MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "c", "2", null);
            break;

        case c_oAscMathType.Accent_BarTop : this.Add_Bar({ctrPrp : Pr.ctrPrp, pos : LOCATION_TOP}, null); break;
        case c_oAscMathType.Accent_BarBot : this.Add_Bar({ctrPrp : Pr.ctrPrp, pos : LOCATION_BOT}, null); break;

        case c_oAscMathType.Accent_Custom_1 :
            this.Add_Bar({ctrPrp : Pr.ctrPrp, pos : LOCATION_TOP}, "A");
            break;

        case c_oAscMathType.Accent_Custom_2 :
            this.Add_Bar({ctrPrp : Pr.ctrPrp, pos : LOCATION_TOP}, "ABC");
            break;

        case c_oAscMathType.Accent_Custom_3 :
            this.Add_Bar({ctrPrp : Pr.ctrPrp, pos : LOCATION_TOP}, "x" + String.fromCharCode(8853) + "y");
            break;
    }
};
CMathContent.prototype.private_LoadFromMenuLimitLog = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.LimitLog_LogBase:
            var Function = this.Add_Function(Pr, null, null);
            var MathContent = Function.getFName();
            var Script = MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUBSCRIPT}, null, null, null);
            MathContent = Script.getBase();
            MathContent.Add_Text("log", STY_PLAIN);
            break;

        case c_oAscMathType.LimitLog_Log: this.Add_Function(Pr, "log", null); break;
        case c_oAscMathType.LimitLog_Lim: this.Add_FunctionWithLimit(Pr, "lim", null, null); break;
        case c_oAscMathType.LimitLog_Min: this.Add_FunctionWithLimit(Pr, "min", null, null); break;
        case c_oAscMathType.LimitLog_Max: this.Add_FunctionWithLimit(Pr, "max", null, null); break;
        case c_oAscMathType.LimitLog_Ln : this.Add_Function(Pr, "ln", null); break;

        case c_oAscMathType.LimitLog_Custom_1:
            var Function = this.Add_FunctionWithLimit(Pr, "lim", "n" + String.fromCharCode(8594,8734), null);
            var MathContent = Function.getArgument();
            var Script = MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, null, "n", null);
            MathContent = Script.getBase();
            var Delimiter = MathContent.Add_Delimiter({ctrPrp : Pr.ctrPrp, column : 1}, 1, [null]);
            MathContent = Delimiter.getElementMathContent(0);
            MathContent.Add_Text("1+");
            MathContent.Add_Fraction({ctrPrp : Pr.ctrPrp}, "1", "n");
            break;

        case c_oAscMathType.LimitLog_Custom_2:
            var Function = this.Add_FunctionWithLimit(Pr, "max", "0" + String.fromCharCode(8804) + "x" + String.fromCharCode(8804) + "1", null);
            var MathContent = Function.getArgument();
            MathContent.Add_Text("x");
            var Script = MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "e", null, null);
            MathContent = Script.getUpperIterator();
            MathContent.Add_Text("-");
            MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, "x", "2", null);
            break;
    }
};
CMathContent.prototype.private_LoadFromMenuOperator = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.Operator_ColonEquals     : this.Add_Box({ctrPrp : Pr.ctrPrp, opEmu : 1}, String.fromCharCode(0x2254)); break;
        case c_oAscMathType.Operator_EqualsEquals    : this.Add_Box({ctrPrp : Pr.ctrPrp, opEmu : 1}, "=="); break;
        case c_oAscMathType.Operator_PlusEquals      : this.Add_Box({ctrPrp : Pr.ctrPrp, opEmu : 1}, "+="); break;
        case c_oAscMathType.Operator_MinusEquals     : this.Add_Box({ctrPrp : Pr.ctrPrp, opEmu : 1}, "-="); break;
        case c_oAscMathType.Operator_Definition      : this.Add_Box({ctrPrp : Pr.ctrPrp, opEmu : 1}, String.fromCharCode(8797)); break;
        case c_oAscMathType.Operator_UnitOfMeasure   : this.Add_Box({ctrPrp : Pr.ctrPrp, opEmu : 1}, String.fromCharCode(8798)); break;
        case c_oAscMathType.Operator_DeltaEquals     : this.Add_Box({ctrPrp : Pr.ctrPrp, opEmu : 1}, String.fromCharCode(8796)); break;
        case c_oAscMathType.Operator_ArrowL_Top      : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_TOP, 8592, null); break;
        case c_oAscMathType.Operator_ArrowR_Top      : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_TOP, 8594, null); break;
        case c_oAscMathType.Operator_ArrowL_Bot      : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8592, null); break;
        case c_oAscMathType.Operator_ArrowR_Bot      : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8594, null); break;
        case c_oAscMathType.Operator_DoubleArrowL_Top: this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_TOP, 8656, null); break;
        case c_oAscMathType.Operator_DoubleArrowR_Top: this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_TOP, 8658, null); break;
        case c_oAscMathType.Operator_DoubleArrowL_Bot: this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8656, null); break;
        case c_oAscMathType.Operator_DoubleArrowR_Bot: this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8658, null); break;
        case c_oAscMathType.Operator_ArrowD_Top      : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_TOP, 8596, null); break;
        case c_oAscMathType.Operator_ArrowD_Bot      : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8596, null); break;
        case c_oAscMathType.Operator_DoubleArrowD_Top: this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_TOP, 8660, null); break;
        case c_oAscMathType.Operator_DoubleArrowD_Bot: this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8660, null); break;
        case c_oAscMathType.Operator_Custom_1        : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8594, "yields"); break;
        case c_oAscMathType.Operator_Custom_2        : this.Add_BoxWithGroupChar({ctrPrp : Pr.ctrPrp, opEmu : 1}, VJUST_BOT, 8594, String.fromCharCode(8710)); break;
    }
};
CMathContent.prototype.private_LoadFromMenuMatrix = function(Type, Pr)
{
    switch(Type)
    {
        case c_oAscMathType.Matrix_1_2: this.Add_Matrix(Pr.ctrPrp, 1, 2, false, []); break;
        case c_oAscMathType.Matrix_2_1: this.Add_Matrix(Pr.ctrPrp, 2, 1, false, []); break;
        case c_oAscMathType.Matrix_1_3: this.Add_Matrix(Pr.ctrPrp, 1, 3, false, []); break;
        case c_oAscMathType.Matrix_3_1: this.Add_Matrix(Pr.ctrPrp, 3, 1, false, []); break;
        case c_oAscMathType.Matrix_2_2: this.Add_Matrix(Pr.ctrPrp, 2, 2, false, []); break;
        case c_oAscMathType.Matrix_2_3: this.Add_Matrix(Pr.ctrPrp, 2, 3, false, []); break;
        case c_oAscMathType.Matrix_3_2: this.Add_Matrix(Pr.ctrPrp, 3, 2, false, []); break;
        case c_oAscMathType.Matrix_3_3: this.Add_Matrix(Pr.ctrPrp, 3, 3, false, []); break;

        case c_oAscMathType.Matrix_Dots_Center   : this.Add_Text(String.fromCharCode(8943)); break;
        case c_oAscMathType.Matrix_Dots_Baseline : this.Add_Text(String.fromCharCode(8230)); break;
        case c_oAscMathType.Matrix_Dots_Vertical : this.Add_Text(String.fromCharCode(8942)); break;
        case c_oAscMathType.Matrix_Dots_Diagonal : this.Add_Text(String.fromCharCode(8945)); break;

        case c_oAscMathType.Matrix_Identity_2         : this.Add_Matrix(Pr.ctrPrp, 2, 2, false, ["1", "0", "0", "1"]); break;
        case c_oAscMathType.Matrix_Identity_2_NoZeros : this.Add_Matrix(Pr.ctrPrp, 2, 2, true, ["1", null, null, "1"]); break;
        case c_oAscMathType.Matrix_Identity_3         : this.Add_Matrix(Pr.ctrPrp, 3, 3, false, ["1", "0", "0", "0", "1", "0", "0", "0", "1"]); break;
        case c_oAscMathType.Matrix_Identity_3_NoZeros : this.Add_Matrix(Pr.ctrPrp, 3, 3, true, ["1", null, null, null, "1", null, null, null, "1"]); break;

        case c_oAscMathType.Matrix_2_2_RoundBracket  : this.Add_MatrixWithBrackets(null, null, Pr.ctrPrp, 2, 2, false, []); break;
        case c_oAscMathType.Matrix_2_2_SquareBracket : this.Add_MatrixWithBrackets(  91,   93, Pr.ctrPrp, 2, 2, false, []); break;
        case c_oAscMathType.Matrix_2_2_LineBracket   : this.Add_MatrixWithBrackets( 124,  124, Pr.ctrPrp, 2, 2, false, []); break;
        case c_oAscMathType.Matrix_2_2_DLineBracket  : this.Add_MatrixWithBrackets(8214, 8214, Pr.ctrPrp, 2, 2, false, []); break;

        case c_oAscMathType.Matrix_Flat_Round  : this.Add_MatrixWithBrackets(null, null, Pr.ctrPrp, 3, 3, false, [null, String.fromCharCode(8943), null, String.fromCharCode(8942), String.fromCharCode(8945), String.fromCharCode(8942), null, String.fromCharCode(8943), null]); break;
        case c_oAscMathType.Matrix_Flat_Square : this.Add_MatrixWithBrackets(  91,   93, Pr.ctrPrp, 3, 3, false, [null, String.fromCharCode(8943), null, String.fromCharCode(8942), String.fromCharCode(8945), String.fromCharCode(8942), null, String.fromCharCode(8943), null]); break;
    }
};
CMathContent.prototype.Add_Element = function(Element)
{
    this.Internal_Content_Add(this.CurPos, Element, false);
    this.CurPos++;
};
CMathContent.prototype.Add_Text = function(sText, MathStyle)
{
    if (sText)
    {
        var MathRun = new ParaRun(this.Paragraph, true);

        for (var nCharPos = 0, nTextLen = sText.length; nCharPos < nTextLen; nCharPos++)
        {
            var oText = null;
            if (0x0026 == sText.charCodeAt(nCharPos))
                oText = new CMathAmp();
            else
            {
                oText = new CMathText(false);
                oText.addTxt(sText[nCharPos]);
            }
            MathRun.Add(oText, true);
        }

        if (undefined !== MathStyle && null !== MathStyle)
            MathRun.Math_Apply_Style(MathStyle);

        this.Internal_Content_Add(this.CurPos, MathRun, false);
        this.CurPos++;
    }
};
CMathContent.prototype.Add_Symbol = function(Code)
{
    var MathRun = new ParaRun(this.Paragraph, true);

    var Symbol = new CMathText(false);
    Symbol.add(Code);
    MathRun.Add(Symbol, true);

    this.Internal_Content_Add(this.CurPos, MathRun, false);
    this.CurPos++;
};
CMathContent.prototype.Add_Fraction = function(Pr, NumText, DenText)
{
    var Fraction = new CFraction(Pr);
    this.Add_Element(Fraction);

    var DenMathContent = Fraction.getDenominatorMathContent();
    DenMathContent.Add_Text(DenText);

    var NumMathContent = Fraction.getNumeratorMathContent();
    NumMathContent.Add_Text(NumText);

    return Fraction;
};
CMathContent.prototype.Add_Script = function(bSubSup, Pr, BaseText, SupText, SubText)
{
    var Script = null
    if (bSubSup)
        Script = new CDegreeSubSup(Pr);
    else
        Script = new CDegree(Pr);

    this.Add_Element(Script);

    var MathContent = Script.getBase();
    MathContent.Add_Text(BaseText);

    MathContent = Script.getUpperIterator();
    MathContent.Add_Text(SupText);

    MathContent = Script.getLowerIterator();
    MathContent.Add_Text(SubText);

    return Script;
};
CMathContent.prototype.Add_Radical = function(Pr, BaseText, DegreeText)
{
    var Radical = new CRadical(Pr);
    this.Add_Element(Radical);

    var MathContent = Radical.getBase();
    MathContent.Add_Text(BaseText);

    MathContent = Radical.getDegree();
    MathContent.Add_Text(DegreeText);

    return Radical;
};
CMathContent.prototype.Add_NAry = function(Pr, BaseText, SupText, SubText)
{
    var NAry = new CNary(Pr);
    this.Add_Element(NAry);

    var MathContent = NAry.getBase();
    MathContent.Add_Text(BaseText);

    MathContent = NAry.getSubMathContent();
    MathContent.Add_Text(SubText);

    MathContent = NAry.getSupMathContent();
    MathContent.Add_Text(SupText);

    return NAry;
};
CMathContent.prototype.Add_Integral = function(Dim, bOriented, limLoc, supHide, subHide, ctrPr, BaseText, SupText, SubText)
{
    var Pr = {ctrPrp : ctrPr};

    if (null !== limLoc)
        Pr.limLoc = limLoc;

    if (null !== supHide)
        Pr.supHide = supHide;

    if (null !== subHide)
        Pr.subHide = subHide;

    var chr = null;
    switch(Dim)
    {
        case 3: chr = (bOriented ? 8752 : 8749); break;
        case 2: chr = (bOriented ? 8751 : 8748); break;
        default:
        case 1: chr = (bOriented ? 8750 : null); break;
    }

    if (null !== chr)
        Pr.chr = chr;

    return this.Add_NAry(Pr, BaseText, SupText, SubText);
};
CMathContent.prototype.Add_LargeOperator = function(Type, limLoc, supHide, subHide, ctrPr, BaseText, SupText, SubText)
{
    var Pr = {ctrPrp : ctrPr};

    if (null !== limLoc)
        Pr.limLoc = limLoc;

    if (null !== supHide)
        Pr.supHide = supHide;

    if (null !== subHide)
        Pr.subHide = subHide;

    var chr = null;
    switch(Type)
    {
        default:
        case 1: chr = 8721; break;
        case 2: chr = 8719; break;
        case 3: chr = 8720; break;
        case 4: chr = 8899; break;
        case 5: chr = 8898; break;
        case 6: chr = 8897; break;
        case 7: chr = 8896; break;
    }

    if (null !== chr)
        Pr.chr = chr;

    return this.Add_NAry(Pr, BaseText, SupText, SubText);
};
CMathContent.prototype.Add_Delimiter = function(Pr, Count, aText)
{
    var Del = new CDelimiter(Pr);

    this.Add_Element(Del);

    for (var Index = 0; Index < Count; Index++)
    {
        var MathContent = Del.getElementMathContent(Index);
        MathContent.Add_Text(aText[Index]);
    }

    return Del;
};
CMathContent.prototype.Add_DelimiterEx = function(ctrPr, Count, aText, begChr, endChr)
{
    var Pr =
    {
        ctrPrp : ctrPr,
        column : Count,
        begChr : begChr,
        endChr : endChr
    };

    return this.Add_Delimiter(Pr, Count, aText);
};
CMathContent.prototype.Add_EqArray = function(Pr, Count, aText)
{
    var EqArray = new CEqArray(Pr);

    this.Add_Element(EqArray);

    for (var Index = 0; Index < Count; Index++)
    {
        var MathContent = EqArray.getElementMathContent(Index);
        MathContent.Add_Text(aText[Index]);
    }

    return EqArray;
};
CMathContent.prototype.Add_Box = function(Pr, BaseText)
{
    var Box = new CBox(Pr);
    this.Add_Element(Box);

    var MathContent = Box.getBase();
    MathContent.Add_Text(BaseText);

    return Box;
};
CMathContent.prototype.Add_BoxWithGroupChar = function(BoxPr, GroupPos, GroupChr, BaseText)
{
    var Box = this.Add_Box(BoxPr, null);
    var MathContent = Box.getBase();

    if (GroupPos === VJUST_TOP)
        MathContent.Add_GroupCharacter({ctrPrp : BoxPr.ctrPrp, pos : GroupPos, chr : GroupChr}, BaseText);
    else
        MathContent.Add_GroupCharacter({ctrPrp : BoxPr.ctrPrp, vertJc : GroupPos, chr : GroupChr}, BaseText);

    return Box;
};
CMathContent.prototype.Add_BorderBox = function(Pr, BaseText)
{
    var Box = new CBorderBox(Pr);
    this.Add_Element(Box);

    var MathContent = Box.getBase();
    MathContent.Add_Text(BaseText);

    return Box;
};
CMathContent.prototype.Add_Bar = function(Pr, BaseText)
{
    var Bar = new CBar(Pr);
    this.Add_Element(Bar);

    var MathContent = Bar.getBase();
    MathContent.Add_Text(BaseText);

    return Bar;
};
CMathContent.prototype.Add_Function = function(Pr, FName, BaseText)
{
    var MathFunc = new CMathFunc(Pr);
    this.Add_Element(MathFunc);

    var MathContent = MathFunc.getFName();
    MathContent.Add_Text(FName, STY_PLAIN);

    MathContent = MathFunc.getArgument();
    MathContent.Add_Text(BaseText);

    return MathFunc;
};
CMathContent.prototype.Add_Function_1 = function(Pr, FName, BaseText)
{
    var MathFunc = new CMathFunc(Pr);
    this.Add_Element(MathFunc);

    var MathContent = MathFunc.getFName();
    var Script = MathContent.Add_Script(false, {ctrPrp : Pr.ctrPrp, type : DEGREE_SUPERSCRIPT}, null, "-1", null);
    MathContent = Script.getBase();
    MathContent.Add_Text(FName, STY_PLAIN);

    MathContent = MathFunc.getArgument();
    MathContent.Add_Text(BaseText);

    return MathFunc;
};
CMathContent.prototype.Add_FunctionWithLimit = function(Pr, FName, LimitText, BaseText)
{
    var MathFunc = new CMathFunc(Pr);
    this.Add_Element(MathFunc);

    var MathContent = MathFunc.getFName();
    var Limit = MathContent.Add_Limit({ctrPrp : Pr.ctrPrp, type : LIMIT_LOW}, null, LimitText);
    MathContent = Limit.getFName();
    MathContent.Add_Text(FName, STY_PLAIN);

    MathContent = MathFunc.getArgument();
    MathContent.Add_Text(BaseText);

    return MathFunc;
};
CMathContent.prototype.Add_Accent = function(ctrPr, chr, BaseText)
{
    var Pr =
    {
        ctrPrp : ctrPr,
        chr    : chr
    };
    var Accent = new CAccent(Pr);
    this.Add_Element(Accent);

    var MathContent = Accent.getBase();
    MathContent.Add_Text(BaseText);

    return Accent;
};
CMathContent.prototype.Add_GroupCharacter = function(Pr, BaseText)
{
    var Group = new CGroupCharacter(Pr);
    this.Add_Element(Group);

    var MathContent = Group.getBase();
    MathContent.Add_Text(BaseText);

    return Group;
};
CMathContent.prototype.Add_Limit = function(Pr, BaseText, LimitText)
{
    var Limit = new CLimit(Pr);
    this.Add_Element(Limit);

    var MathContent = Limit.getFName();
    MathContent.Add_Text(BaseText);

    MathContent = Limit.getIterator();
    MathContent.Add_Text(LimitText);

    return Limit;
};
CMathContent.prototype.Add_Matrix = function(ctrPr, RowsCount, ColsCount, plcHide, aText)
{
    var Pr =
    {
        ctrPrp  : ctrPr,
        row     : RowsCount,
        mcs     : [{count : ColsCount, mcJc : MCJC_CENTER}],
        plcHide : plcHide
    };

    var Matrix = new CMathMatrix(Pr);
    this.Add_Element(Matrix)

    for (var RowIndex = 0; RowIndex < RowsCount; RowIndex++)
    {
        for (var ColIndex = 0; ColIndex < ColsCount; ColIndex++)
        {
            var MathContent = Matrix.getContentElement(RowIndex, ColIndex);
            MathContent.Add_Text(aText[RowIndex * ColsCount + ColIndex]);
        }
    }

    return Matrix;
};
CMathContent.prototype.Add_MatrixWithBrackets = function(begChr, endChr, ctrPr, RowsCount, ColsCount, plcHide, aText)
{
    var Delimiter = this.Add_DelimiterEx(ctrPr, 1, [null], begChr, endChr);
    var MathContent = Delimiter.getElementMathContent(0);
    return MathContent.Add_Matrix(ctrPr, RowsCount, ColsCount, plcHide, aText);
};
CMathContent.prototype.Recalculate_Reset = function(StartRange, StartLine)
{
    for(var nPos = 0, nCount = this.Content.length; nPos < nCount; nPos++)
    {
        this.Content[nPos].Recalculate_Reset(StartRange, StartLine);
    }
};
CMathContent.prototype.Get_Bounds = function()
{
    var X = 0, Y = 0, W = 0, H = 0;
    if (null !== this.ParaMath)
    {

        X = this.ParaMath.X + this.pos.x;
        Y = this.ParaMath.Y + this.pos.y;
        W = this.size.width;
        H = this.size.height;
    }

    return {X : X, Y : Y, W : W, H : H};
};
CMathContent.prototype.Recalculate_CurPos = function(_X, _Y, CurrentRun, _CurRange, _CurLine, _CurPage, UpdateCurPos, UpdateTarget, ReturnTarget)
{
    var X = this.pos.x + this.ParaMath.X;
    var Y = this.pos.y + this.ParaMath.Y + this.size.ascent;

    if(this.RecalcInfo.bEqqArray)
    {
        for(var nPos = 0; nPos < this.CurPos; nPos++)
        {
            if(para_Math_Run === this.Content[nPos].Type)
                X = this.Content[nPos].Recalculate_CurPos(X, Y, false, _CurRange, _CurLine, _CurPage, UpdateCurPos, UpdateTarget, ReturnTarget).X;
            else
                X += this.Content[nPos].size.width;
        }
    }
    else
        X += this.WidthToElement[this.CurPos];

    return this.Content[this.CurPos].Recalculate_CurPos(X, Y, CurrentRun, _CurRange, _CurLine, _CurPage, UpdateCurPos, UpdateTarget, ReturnTarget);
};
CMathContent.prototype.Get_ParaContentPosByXY = function(SearchPos, Depth, _CurLine, _CurRange, StepEnd)
{
    var nLength = this.Content.length;

    if (nLength <= 0)
        return false;

    var bResult = false;
    for (var nPos = 0; nPos < nLength; nPos++)
    {
        var CurX = SearchPos.CurX;

        if(true === this.Content[nPos].Get_ParaContentPosByXY(SearchPos, Depth + 1, _CurLine, _CurRange, StepEnd))
        {
            SearchPos.Pos.Update2(nPos, Depth);
            bResult = true;
        }

        SearchPos.CurX = CurX + this.Content[nPos].size.width;
    }

    return bResult;
};
CMathContent.prototype.Get_ParaContentPos = function(bSelection, bStart, ContentPos)
{
    var nPos = (true !== bSelection ? this.CurPos : (false !== bStart ? this.Selection.Start : this.Selection.End));
    ContentPos.Add(nPos);

    if (undefined !== this.Content[nPos])
        this.Content[nPos].Get_ParaContentPos(bSelection, bStart, ContentPos);
};
CMathContent.prototype.Set_ParaContentPos = function(ContentPos, Depth)
{
    var CurPos = ContentPos.Get(Depth);

    // Делаем такие проверки, потому что после совместного редактирования, позиция может остаться старой, а
    // контент измениться.
    if (undefined === CurPos || CurPos < 0)
    {
        this.CurPos = 0;
        this.Content[this.CurPos].Cursor_MoveToStartPos();
    }
    else if (CurPos > this.Content.length - 1)
    {
        this.CurPos = this.Content.length - 1;
        this.Content[this.CurPos].Cursor_MoveToEndPos(false);
    }
    else
    {
        this.CurPos = ContentPos.Get(Depth);
        this.Content[this.CurPos].Set_ParaContentPos(ContentPos, Depth + 1);
    }
};
CMathContent.prototype.Set_SelectionContentPos = function(StartContentPos, EndContentPos, Depth, StartFlag, EndFlag)
{
    var OldStartPos = this.Selection.Start;
    var OldEndPos   = this.Selection.End;

    if (OldStartPos > OldEndPos)
    {
        OldStartPos = this.Selection.End;
        OldEndPos   = this.Selection.Start;
    }

    var StartPos = 0;
    switch(StartFlag)
    {
        case  1: StartPos = 0; break;
        case -1: StartPos = this.Content.length - 1; break;
        case  0: StartPos = StartContentPos.Get(Depth); break;
    }

    var EndPos = 0;
    switch(EndFlag)
    {
        case  1: EndPos = 0; break;
        case -1: EndPos = this.Content.length - 1; break;
        case  0: EndPos = EndContentPos.Get(Depth); break;
    }

    // Удалим отметки о старом селекте
    if (OldStartPos < StartPos && OldStartPos < EndPos)
    {
        var TempLimit = Math.min(StartPos, EndPos);
        for (var CurPos = OldStartPos; CurPos < TempLimit; CurPos++)
        {
            this.Content[CurPos].Selection_Remove();
        }
    }

    if (OldEndPos > StartPos && OldEndPos > EndPos)
    {
        var TempLimit = Math.max(StartPos, EndPos);
        for (var CurPos = TempLimit + 1; CurPos <= OldEndPos; CurPos++)
        {
            this.Content[CurPos].Selection_Remove();
        }
    }

    // Выставим метки нового селекта
    this.Selection.Use   = true;
    this.Selection.Start = StartPos;
    this.Selection.End   = EndPos;

    if (StartPos !== EndPos)
    {
        this.Content[StartPos].Set_SelectionContentPos(StartContentPos, null, Depth + 1, StartFlag, StartPos > EndPos ? 1 : -1);
        this.Content[EndPos].Set_SelectionContentPos(null, EndContentPos, Depth + 1, StartPos > EndPos ? -1 : 1, EndFlag);

        var _StartPos = StartPos;
        var _EndPos   = EndPos;
        var Direction = 1;

        if ( _StartPos > _EndPos )
        {
            _StartPos = EndPos;
            _EndPos   = StartPos;
            Direction = -1;
        }

        for (var CurPos = _StartPos + 1; CurPos < _EndPos; CurPos++)
        {
            this.Content[CurPos].Select_All( Direction );
        }
    }
    else
    {
        this.Content[StartPos].Set_SelectionContentPos(StartContentPos, EndContentPos, Depth + 1, StartFlag, EndFlag);
    }
};
CMathContent.prototype.Selection_IsEmpty = function()
{
    if (true !== this.Selection.Use)
        return true;

    if (this.Selection.Start === this.Selection.End)
        return this.Content[this.Selection.Start].Selection_IsEmpty();

    return false;
};
CMathContent.prototype.GetSelectContent = function()
{
    if (false === this.Selection.Use)
    {
        if (para_Math_Composition === this.Content[this.CurPos].Type)
            return this.Content[this.CurPos].GetSelectContent();
        else
            return {Content : this, Start : this.CurPos, End : this.CurPos};
    }
    else
    {
        var StartPos = this.Selection.Start;
        var EndPos   = this.Selection.End;

        if (StartPos > EndPos)
        {
            StartPos = this.Selection.End;
            EndPos   = this.Selection.Start;
        }

        if (StartPos === EndPos && para_Math_Composition === this.Content[StartPos].Type && true === this.Content[StartPos].Is_InnerSelection())
            return this.Content[StartPos].GetSelectContent();

        return {Content : this, Start : StartPos, End : EndPos};
    }
};
CMathContent.prototype.Get_LeftPos = function(SearchPos, ContentPos, Depth, UseContentPos)
{
    if (false === UseContentPos && para_Math_Run === this.Content[this.Content.length - 1].Type)
    {
        // При переходе в новый контент встаем в его конец
        var CurPos = this.Content.length - 1;
        this.Content[CurPos].Get_EndPos(false, SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(CurPos, Depth);
        SearchPos.Found = true;

        return true;
    }

    var CurPos = UseContentPos ? ContentPos.Get(Depth) : this.Content.length - 1;

    var bStepStart = false;
    if (CurPos > 0 || !this.Content[0].Cursor_Is_Start())
        bStepStart = true;

    this.Content[CurPos].Get_LeftPos(SearchPos, ContentPos, Depth + 1, UseContentPos);
    SearchPos.Pos.Update(CurPos, Depth);

    if (true === SearchPos.Found)
        return true;

    CurPos--;

    if (true === UseContentPos && para_Math_Composition === this.Content[CurPos + 1].Type)
    {
        // При выходе из формулы встаем в конец рана
        this.Content[CurPos].Get_EndPos(false, SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(CurPos, Depth);
        SearchPos.Found = true;
        return true;
    }

    while (CurPos >= 0)
    {
        this.Content[CurPos].Get_LeftPos(SearchPos, ContentPos, Depth + 1, false);
        SearchPos.Pos.Update( CurPos, Depth );

        if (true === SearchPos.Found)
            return true;

        CurPos--;
    }

    if (true === bStepStart)
    {
        // Перед выходом из контента встаем в его начало
        this.Content[0].Get_StartPos(SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(0, Depth);
        SearchPos.Found = true;

        return true;
    }

    return false;
};
CMathContent.prototype.Get_RightPos = function(SearchPos, ContentPos, Depth, UseContentPos, StepEnd)
{
    if (false === UseContentPos && para_Math_Run === this.Content[0].Type)
    {
        // При переходе в новый контент встаем в его начало
        this.Content[0].Get_StartPos(SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(0, Depth);
        SearchPos.Found = true;

        return true;
    }

    var CurPos = true === UseContentPos ? ContentPos.Get(Depth) : 0;

    var Count = this.Content.length;
    var bStepEnd = false;
    if (CurPos < Count - 1 || !this.Content[Count - 1].Cursor_Is_End())
        bStepEnd = true;

    this.Content[CurPos].Get_RightPos(SearchPos, ContentPos, Depth + 1, UseContentPos, StepEnd);
    SearchPos.Pos.Update( CurPos, Depth );

    if (true === SearchPos.Found)
        return true;

    CurPos++;

    if (true === UseContentPos && para_Math_Composition === this.Content[CurPos - 1].Type)
    {
        // При выходе из формулы встаем в начало рана
        this.Content[CurPos].Get_StartPos(SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(CurPos, Depth);
        SearchPos.Found = true;
        return true;
    }

    while (CurPos < Count)
    {
        this.Content[CurPos].Get_RightPos(SearchPos, ContentPos, Depth + 1, false, StepEnd);
        SearchPos.Pos.Update(CurPos, Depth);

        if (true === SearchPos.Found)
            return true;

        CurPos++;
    }

    if (true === bStepEnd)
    {
        // Перед выходом из контента встаем в его конец
        this.Content[Count - 1].Get_EndPos(false, SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(Count - 1, Depth);
        SearchPos.Found = true;

        return true;
    }

    return false;
};
CMathContent.prototype.Get_WordStartPos = function(SearchPos, ContentPos, Depth, UseContentPos)
{
    if (false === UseContentPos && para_Math_Run === this.Content[this.Content.length - 1].Type)
    {
        // При переходе в новый контент встаем в его конец
        var CurPos = this.Content.length - 1;
        this.Content[CurPos].Get_EndPos(false, SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(CurPos, Depth);
        SearchPos.Found     = true;
        SearchPos.UpdatePos = true;
        return true;
    }

    var CurPos = true === UseContentPos ? ContentPos.Get(Depth) : this.Content.length - 1;

    var bStepStart = false;
    if (CurPos > 0 || !this.Content[0].Cursor_Is_Start())
        bStepStart = true;

    this.Content[CurPos].Get_WordStartPos(SearchPos, ContentPos, Depth + 1, UseContentPos);

    if (true === SearchPos.UpdatePos)
        SearchPos.Pos.Update( CurPos, Depth );

    if (true === SearchPos.Found)
        return;

    CurPos--;

    var bStepStartRun = false;
    if (true === UseContentPos && para_Math_Composition === this.Content[CurPos + 1].Type)
    {
        // При выходе из формулы встаем в конец рана
        this.Content[CurPos].Get_EndPos(false, SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(CurPos, Depth);
        SearchPos.Found     = true;
        SearchPos.UpdatePos = true;
        return true;
    }
    else if (para_Math_Run === this.Content[CurPos + 1].Type && true === SearchPos.Shift)
        bStepStartRun = true;

    while (CurPos >= 0)
    {
        if (true !== bStepStartRun || para_Math_Run === this.Content[CurPos].Type)
        {
            var OldUpdatePos = SearchPos.UpdatePos;

            this.Content[CurPos].Get_WordStartPos(SearchPos, ContentPos, Depth + 1, false);

            if (true === SearchPos.UpdatePos)
                SearchPos.Pos.Update(CurPos, Depth);
            else
                SearchPos.UpdatePos = OldUpdatePos;

            if (true === SearchPos.Found)
                return;

            if (true === SearchPos.Shift)
                bStepStartRun = true;
        }
        else
        {
            // Встаем в начало рана перед формулой
            this.Content[CurPos + 1].Get_StartPos(SearchPos.Pos, Depth + 1);
            SearchPos.Pos.Update(CurPos + 1, Depth);
            SearchPos.Found     = true;
            SearchPos.UpdatePos = true;
            return true;
        }
        CurPos--;
    }

    if (true === bStepStart)
    {
        // Перед выходом из контента встаем в его начало
        this.Content[0].Get_StartPos(SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(0, Depth);
        SearchPos.Found     = true;
        SearchPos.UpdatePos = true;
        return true;
    }
};
CMathContent.prototype.Get_WordEndPos = function(SearchPos, ContentPos, Depth, UseContentPos, StepEnd)
{
    if (false === UseContentPos && para_Math_Run === this.Content[0].Type)
    {
        // При переходе в новый контент встаем в его начало
        this.Content[0].Get_StartPos(SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(0, Depth);
        SearchPos.Found     = true;
        SearchPos.UpdatePos = true;
        return true;
    }

    var CurPos = true === UseContentPos ? ContentPos.Get(Depth) : 0;

    var Count = this.Content.length;
    var bStepEnd = false;
    if (CurPos < Count - 1 || !this.Content[Count - 1].Cursor_Is_End())
        bStepEnd = true;

    this.Content[CurPos].Get_WordEndPos(SearchPos, ContentPos, Depth + 1, UseContentPos, StepEnd);

    if (true === SearchPos.UpdatePos)
        SearchPos.Pos.Update( CurPos, Depth);

    if (true === SearchPos.Found)
        return;

    CurPos++;

    var bStepEndRun = false;
    if (true === UseContentPos && para_Math_Composition === this.Content[CurPos - 1].Type)
    {
        // При выходе из формулы встаем в начало рана
        this.Content[CurPos].Get_StartPos(SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(CurPos, Depth);
        SearchPos.Found     = true;
        SearchPos.UpdatePos = true;
        return true;
    }
    else if (para_Math_Run === this.Content[CurPos - 1].Type && true === SearchPos.Shift)
        bStepEndRun = true;

    while (CurPos < Count)
    {
        if (true !== bStepEndRun || para_Math_Run === this.Content[CurPos].Type)
        {
            var OldUpdatePos = SearchPos.UpdatePos;

            this.Content[CurPos].Get_WordEndPos(SearchPos, ContentPos, Depth + 1, false, StepEnd);

            if (true === SearchPos.UpdatePos)
                SearchPos.Pos.Update(CurPos, Depth);
            else
                SearchPos.UpdatePos = OldUpdatePos;

            if (true === SearchPos.Found)
                return;

            if (true === SearchPos.Shift)
                bStepEndRun = true;
        }
        else
        {
            // Встаем в конец рана перед формулой
            this.Content[CurPos - 1].Get_EndPos(false, SearchPos.Pos, Depth + 1);
            SearchPos.Pos.Update(CurPos - 1, Depth);
            SearchPos.Found     = true;
            SearchPos.UpdatePos = true;
            return true;
        }

        CurPos++;
    }

    if (true === bStepEnd)
    {
        // Перед выходом из контента встаем в его конец
        this.Content[Count - 1].Get_EndPos(false, SearchPos.Pos, Depth + 1);
        SearchPos.Pos.Update(Count - 1, Depth);
        SearchPos.Found     = true;
        SearchPos.UpdatePos = true;
        return true;
    }
};
CMathContent.prototype.Get_StartPos = function(ContentPos, Depth)
{
    ContentPos.Update(0, Depth);
    this.Content[0].Get_StartPos(ContentPos, Depth + 1);
};
CMathContent.prototype.Get_EndPos = function(BehindEnd, ContentPos, Depth)
{
    var nLastPos = this.Content.length - 1;

    ContentPos.Update(nLastPos, Depth);
    if(undefined !== this.Content[nLastPos])
        this.Content[nLastPos].Get_EndPos(BehindEnd, ContentPos, Depth + 1);
};
CMathContent.prototype.Draw_HighLights = function(PDSH, bAll)
{
    PDSH.X = this.ParaMath.X + this.pos.x;

    var len = this.Content.length;

    for ( var CurPos = 0; CurPos < len; CurPos++ )
    {
        PDSH.Y0 = this.ParaMath.Y + this.pos.y;
        PDSH.Y1 = this.ParaMath.Y + this.pos.y + this.size.height;


        if(bAll && this.Content[CurPos].Type == para_Math_Run)
            this.Content[CurPos].Select_All();

        this.Content[CurPos].Draw_HighLights(PDSH, bAll);
    }

};
CMathContent.prototype.Draw_Lines = function(PDSL)
{

};
CMathContent.prototype.Selection_Remove = function()
{
    var StartPos = this.Selection.Start;
    var EndPos   = this.Selection.End;

    if (StartPos > EndPos)
    {
        StartPos = this.Selection.End;
        EndPos   = this.Selection.Start;
    }

    StartPos = Math.max(0, StartPos);
    EndPos   = Math.min(this.Content.length - 1, EndPos);

    for (var nPos = StartPos; nPos <= EndPos; nPos++)
    {
        this.Content[nPos].Selection_Remove();
    }

    this.Selection.Use   = false;
    this.Selection.Start = 0;
    this.Selection.End   = 0;
};
CMathContent.prototype.Select_All = function(Direction)
{
    this.Selection.Use   = true;
    this.Selection.Start = 0;
    this.Selection.End   = this.Content.length - 1;

    for (var nPos = 0, nCount = this.Content.length; nPos < nCount; nPos++)
    {
        this.Content[nPos].Select_All(Direction);
    }
};
CMathContent.prototype.Selection_DrawRange = function(_CurLine, _CurRange, SelectionDraw)
{
    var Start = this.Selection.Start;
    var End   = this.Selection.End;

    if(Start > End)
    {
        Start = this.Selection.End;
        End   = this.Selection.Start;
    }

    SelectionDraw.StartX += this.pos.x;

    var PointsInfo = new CMathPointInfo();
    PointsInfo.SetInfoPoints(this.InfoPoints);

    var bDrawSelection = false;
    for(var nPos = 0, nCount = this.Content.length; nPos < nCount; nPos++)
    {
        bDrawSelection = nPos >= Start && nPos <= End ? true : false;

        if(para_Math_Run === this.Content[nPos].Type)
            this.Content[nPos].Selection_DrawRange(_CurLine, _CurRange, SelectionDraw, PointsInfo);
        else
        {
            if(true === bDrawSelection)
            {
                SelectionDraw.W += this.Content[nPos].size.width;
                SelectionDraw.FindStart = false;
            }
            else if(true === SelectionDraw.FindStart)
                SelectionDraw.StartX += this.Content[nPos].size.width;
        }
    }

    // Выставляем высоту селекта. В верхнем контенте высота задается параграфом
    if(true !== this.bRoot)
    {
        SelectionDraw.StartY = this.ParaMath.Y + this.pos.y;
        SelectionDraw.H      = this.size.height;
    }
};
CMathContent.prototype.Select_ElementByPos = function(nPos, bWhole)
{
    this.Selection.Use   = true;
    this.Selection.Start = nPos;
    this.Selection.End   = nPos;

    this.Content[nPos].Select_All();

    if (bWhole)
        this.Correct_Selection();

    if (!this.bRoot)
        this.ParentElement.Select_MathContent(this);
    else
        this.ParaMath.bSelectionUse = true;
};
CMathContent.prototype.Select_Element = function(Element, bWhole)
{
    var nPos = -1;
    for (var nCurPos = 0, nCount = this.Content.length; nCurPos < nCount; nCurPos++)
    {
        if (this.Content[nCurPos] === Element)
        {
            nPos = nCurPos;
            break;
        }
    }

    if (-1 !== nPos)
    {
        this.Selection.Use   = true;
        this.Selection.Start = nPos;
        this.Selection.End   = nPos;

        if (bWhole)
            this.Correct_Selection();

        if (!this.bRoot)
            this.ParentElement.Select_MathContent(this);
        else
            this.ParaMath.bSelectionUse = true;
    }
};
CMathContent.prototype.Correct_Selection = function()
{
    if (true !== this.Selection.Use)
        return;

    // Здесь мы делаем так, чтобы селект всегда начинался и заканчивался в ране.
    // Предполагается, что контент скорректирован верно до выполнения данной функции.

    var nContentLen = this.Content.length;
    var nStartPos = Math.max(0, Math.min(this.Selection.Start, nContentLen - 1));
    var nEndPos   = Math.max(0, Math.min(this.Selection.End,   nContentLen - 1));

    if (nStartPos > nEndPos)
    {
        var nTemp = nStartPos;
        nStartPos = nEndPos;
        nEndPos   = nTemp;
    }

    var oStartElement = this.Content[nStartPos];
    if (para_Math_Run !== oStartElement.Type)
    {
        // Предыдущий элемент должен быть раном
        this.Selection.Start = nStartPos - 1;
        this.Content[this.Selection.Start].Set_SelectionAtEndPos();
    }

    var oEndElement = this.Content[nEndPos];
    if (para_Math_Run !== oEndElement.Type)
    {
        // Следующий элемент должен быть раном
        this.Selection.End = nEndPos + 1;
        this.Content[this.Selection.End].Set_SelectionAtStartPos();
    }
};
CMathContent.prototype.Create_FontMap = function(Map)
{
    for (var nIndex = 0, nCount = this.Content.length; nIndex < nCount; nIndex++)
        this.Content[nIndex].Create_FontMap(Map, this.Compiled_ArgSz); // ArgSize компилируется только тогда, когда выставлены все ссылки на родительские классы
};
CMathContent.prototype.Get_AllFontNames = function(AllFonts)
{
    for (var nIndex = 0, nCount = this.Content.length; nIndex < nCount; nIndex++)
        this.Content[nIndex].Get_AllFontNames(AllFonts);
};
CMathContent.prototype.Selection_CheckParaContentPos = function(ContentPos, Depth, bStart, bEnd)
{
    var CurPos = ContentPos.Get(Depth);

    if (this.Selection.Start <= CurPos && CurPos <= this.Selection.End)
        return this.Content[CurPos].Selection_CheckParaContentPos(ContentPos, Depth + 1, bStart && this.Selection.Start === CurPos, bEnd && CurPos === this.Selection.End);
    else if (this.Selection.End <= CurPos && CurPos <= this.Selection.Start)
        return this.Content[CurPos].Selection_CheckParaContentPos(ContentPos, Depth + 1, bStart && this.Selection.End === CurPos, bEnd && CurPos === this.Selection.Start);

    return false;
};
CMathContent.prototype.Check_NearestPos = function(ParaNearPos, Depth)
{
    var HyperNearPos = new CParagraphElementNearPos();
    HyperNearPos.NearPos = ParaNearPos.NearPos;
    HyperNearPos.Depth   = Depth;

    this.NearPosArray.push(HyperNearPos);
    ParaNearPos.Classes.push(this);

    var CurPos = ParaNearPos.NearPos.ContentPos.Get(Depth);
    this.Content[CurPos].Check_NearestPos(ParaNearPos, Depth + 1);
};
CMathContent.prototype.private_SetNeedResize = function()
{
    if (null !== this.ParaMath)
        this.ParaMath.SetNeedResize();
};
CMathContent.prototype.Is_CheckingNearestPos  = ParaHyperlink.prototype.Is_CheckingNearestPos;

CMathContent.prototype.Search                        = ParaHyperlink.prototype.Search;
CMathContent.prototype.Add_SearchResult              = ParaHyperlink.prototype.Add_SearchResult;
CMathContent.prototype.Clear_SearchResults           = ParaHyperlink.prototype.Clear_SearchResults;
CMathContent.prototype.Remove_SearchResult           = ParaHyperlink.prototype.Remove_SearchResult;
CMathContent.prototype.Search_GetId                  = ParaHyperlink.prototype.Search_GetId;
CMathContent.prototype.Recalc_RunsCompiledPr         = ParaHyperlink.prototype.Recalc_RunsCompiledPr;


CMathContent.prototype.Get_SelectionDirection = function()
{
    if (true !== this.Selection.Use)
        return 0;

    if (this.Selection.Start < this.Selection.End)
        return 1;
    else if (this.Selection.Start > this.Selection.End)
        return -1;

    return this.Content[this.Selection.Start].Get_SelectionDirection();
};
CMathContent.prototype.Cursor_MoveToStartPos = function()
{
    this.CurPos = 0;
    this.Content[0].Cursor_MoveToStartPos();
};
CMathContent.prototype.Cursor_MoveToEndPos = function(SelectFromEnd)
{
    this.CurPos = this.Content.length - 1;
    this.Content[this.CurPos].Cursor_MoveToEndPos(SelectFromEnd);
};
CMathContent.prototype.Process_AutoCorrect = function(ActionElement)
{
    if (false === this.private_NeedAutoCorrect(ActionElement))
        return;

    var AutoCorrectEngine = new CMathAutoCorrectEngine(ActionElement);

    var nCount = this.Content.length;
    for (var nPos = 0; nPos < nCount; nPos++)
    {
        var Element = this.Content[nPos];

        if (para_Math_Run === Element.Type)
            Element.Get_TextForAutoCorrect(AutoCorrectEngine, nPos);
        else
            AutoCorrectEngine.Add_Element(Element, nPos);

        if (false === AutoCorrectEngine.CollectText)
            break;
    }

    // Создаем новую точку здесь, потому что если автозамену можно будет сделать классы сразу будут создаваться
    History.Create_NewPoint();

    var bCursorStepRight = false;
    // Смотрим возможно ли выполнить автозамену, если нет, тогда пробуем произвести автозамену пропуская последний символ
    var CanMakeAutoCorrect = this.private_CanAutoCorrectText(AutoCorrectEngine, false);

    if (false === CanMakeAutoCorrect)
    {
        // Пробуем произвести автозамену без последнего добавленного символа
        if (0x20 === ActionElement.value)
            CanMakeAutoCorrect = this.private_CanAutoCorrectText(AutoCorrectEngine, true);
        else
        {
            AutoCorrectEngine.Elements.splice(AutoCorrectEngine.Elements.length - 1, 1);
            CanMakeAutoCorrect = this.private_CanAutoCorrectText(AutoCorrectEngine, false);
            bCursorStepRight = true;
        }
    }

    // Пробуем сделать формульную автозамену
    if (false === CanMakeAutoCorrect)
    {
        CanMakeAutoCorrect = this.private_CanAutoCorrectEquation(AutoCorrectEngine);
    }

    if (true === CanMakeAutoCorrect)
    {
        var ElementsCount = AutoCorrectEngine.Elements.length;
        var LastElement = null;

        var FirstElement    = AutoCorrectEngine.Elements[ElementsCount - 1];
        var FirstElementPos = FirstElement.ElementPos;
        FirstElement.Pos++;
        for (var nPos = 0, nCount = AutoCorrectEngine.RemoveCount; nPos < nCount; nPos++)
        {
            LastElement = AutoCorrectEngine.Elements[ElementsCount - nPos - 1];

            if (undefined !== LastElement.Run)
            {
                if (FirstElement.Run === LastElement.Run)
                    FirstElement.Pos--;

                LastElement.Run.Remove_FromContent(LastElement.Pos, 1);
            }
            else
            {
                this.Remove_FromContent(LastElement.ElementPos, 1);
                FirstElementPos--;
            }
        }

        var NewRun = FirstElement.Run.Split2(FirstElement.Pos);

        this.Internal_Content_Add(FirstElementPos + 1, NewRun, false);

        var NewElementsCount = AutoCorrectEngine.ReplaceContent.length;
        for (var nPos = 0; nPos < NewElementsCount; nPos++)
        {
            this.Internal_Content_Add(nPos + FirstElementPos + 1, AutoCorrectEngine.ReplaceContent[nPos], false);
        }

        this.CurPos = FirstElementPos + NewElementsCount + 1;
        this.Content[this.CurPos].Cursor_MoveToStartPos();

        if (true === bCursorStepRight)
        {
            // TODO: Переделать через функцию в ране
            if (this.Content[this.CurPos].Content.length >= 1)
                this.Content[this.CurPos].State.ContentPos = 1;
        }
    }
    else
    {
        History.Remove_LastPoint();
    }
};

CMathContent.prototype.private_NeedAutoCorrect = function(ActionElement)
{
    var CharCode = ActionElement.value;
    if (1 === g_aMathAutoCorrectTriggerCharCodes[CharCode])
        return true;

    return false;
};

CMathContent.prototype.private_CanAutoCorrectText = function(AutoCorrectionEngine, bSkipLast)
{
    var IndexAdd = (true === bSkipLast ? 1 : 0);

    var ElementsCount = AutoCorrectionEngine.Elements.length;
    if (ElementsCount < 2 + IndexAdd)
        return false;

    var Result = false;

    var RemoveCount  = 0;
    var ReplaceChars = [0x0020];
    var AutoCorrectCount = g_aAutoCorrectMathSymbols.length;
    for (var nIndex = 0; nIndex < AutoCorrectCount; nIndex++)
    {
        var AutoCorrectElement = g_aAutoCorrectMathSymbols[nIndex];
        var CheckString = AutoCorrectElement[0];
        var CheckStringLen = CheckString.length;

        if (ElementsCount < CheckStringLen)
            continue;

        var Found = true;

        // Начинаем проверять с конца строки
        for (var nStringPos = 0; nStringPos < CheckStringLen; nStringPos++)
        {
            var LastElement = AutoCorrectionEngine.Elements[ElementsCount - nStringPos - 1 - IndexAdd];
            if (undefined === LastElement.Text || LastElement.Text !== CheckString.charAt(CheckStringLen - nStringPos - 1))
            {
                Found = false;
                break;
            }
        }

        if (true === Found)
        {
            RemoveCount   = CheckStringLen + IndexAdd;

            if (undefined === AutoCorrectElement[1].length)
                ReplaceChars[0] = AutoCorrectElement[1];
            else
            {
                for (var Index = 0, Len = AutoCorrectElement[1].length; Index < Len; Index++)
                {
                    ReplaceChars[Index] = AutoCorrectElement[1][Index];
                }
            }

        }
    }

    if (RemoveCount > 0)
    {
        var MathRun = new ParaRun(this.ParaMath.Paragraph, true);

        for (var Index = 0, Count = ReplaceChars.length; Index < Count; Index++)
        {
            var ReplaceText = new CMathText();
            ReplaceText.add(ReplaceChars[Index]);
            MathRun.Add(ReplaceText, true);
        }

        AutoCorrectionEngine.RemoveCount = RemoveCount;
        AutoCorrectionEngine.ReplaceContent.push(MathRun);

        Result = true;
    }

    return Result;
};

CMathContent.prototype.private_CanAutoCorrectEquation = function(AutoCorrectionEngine)
{
    var ElementsCount = AutoCorrectionEngine.Elements.length;
    if (ElementsCount < 2)
        return false;

    var TempElements = [];
    var CurPos = ElementsCount - 1;

    // Пробел в начале пропускаем
    var Element = AutoCorrectionEngine.Elements[CurPos];
    if (' ' === Element.Text)
        CurPos--;

    while (CurPos >= 0)
    {
        var Element = AutoCorrectionEngine.Elements[CurPos];
        if (undefined === Element.Text)
            TempElements.splice(0, 0, Element);
		else if ('(' === Element.Text)
			TempElements.splice(0, 0, Element);
		else if (')' === Element.Text)
			TempElements.splice(0, 0, Element);
        else if ('/' === Element.Text)
        {
			AutoCorrectionEngine.Type = MATH_FRACTION;
            CurPos--;
            break;
        }
		else if  ('^' === Element.Text)
		{
			TempElements.Type = DEGREE_SUPERSCRIPT;
			AutoCorrectionEngine.Kind = DEGREE_SUPERSCRIPT;
			AutoCorrectionEngine.Type = MATH_DEGREE;
            CurPos--;
            break;
        }
		else if  ('_' === Element.Text)
		{
			TempElements.Type = DEGREE_SUBSCRIPT;
			AutoCorrectionEngine.Kind = DEGREE_SUBSCRIPT;
			AutoCorrectionEngine.Type = MATH_DEGREE;
            CurPos--;
            break;
        }
        else if (g_aMathAutoCorrectTriggerCharCodes[Element.Text.charCodeAt(0)])
            return false;
        else
            TempElements.splice(0, 0, Element);

        CurPos--;
    }

    var TempElements2 = [];
    while (CurPos >= 0)
    {
        var Element = AutoCorrectionEngine.Elements[CurPos];
        if (undefined === Element.Text)
            TempElements2.splice(0, 0, Element);
		else if ('(' === Element.Text)
			TempElements2.splice(0, 0, Element);
		else if (')' === Element.Text)
			TempElements2.splice(0, 0, Element);
		else if  ('_' === Element.Text)
		{
			if (TempElements2.length == 0)
				break;
			TempElements2.Type = DEGREE_SUBSCRIPT;
			AutoCorrectionEngine.Kind = DEGREE_SubSup;
			AutoCorrectionEngine.Type = MATH_DEGREESubSup;
            CurPos--;
            break;
        }
		else if  ('^' === Element.Text)
		{
			if (TempElements2.length == 0)
				break;
			
			TempElements2.Type = DEGREE_SUPERSCRIPT;
			AutoCorrectionEngine.Kind = DEGREE_SubSup;
			AutoCorrectionEngine.Type = MATH_DEGREESubSup;
            CurPos--;
            break;
        }
        else if (g_aMathAutoCorrectTriggerCharCodes[Element.Text.charCodeAt(0)])
            break;
        else
            TempElements2.splice(0, 0, Element);

        CurPos--;
    }

	var TempElements3 = [];
	if (AutoCorrectionEngine.Type == MATH_DEGREESubSup)
	{
		 while (CurPos >= 0)
		{
			var Element = AutoCorrectionEngine.Elements[CurPos];
			if (undefined === Element.Text)
				TempElements3.splice(0, 0, Element);
			else if (g_aMathAutoCorrectTriggerCharCodes[Element.Text.charCodeAt(0)])
				break;
			else
				TempElements3.splice(0, 0, Element);

			CurPos--;
		}
	}
	
	if (AutoCorrectionEngine.Type == MATH_FRACTION)
	{
		if (TempElements2.length > 0)
		{
			var Fraction = new CFraction(new CMathFractionPr());

			var DenMathContent = Fraction.Content[0];
			var NumMathContent = Fraction.Content[1];

			this.PackTextToContent(DenMathContent, TempElements2);
			this.PackTextToContent(NumMathContent, TempElements);	

			AutoCorrectionEngine.RemoveCount = ElementsCount - CurPos - 1;
			AutoCorrectionEngine.ReplaceContent.push(Fraction);

			return true;
		}
	}
	else if (AutoCorrectionEngine.Type == MATH_DEGREE)
	{
		//if (TempElements2.length > 0)
		//{
			var props = new CMathDegreePr();
			props.type = AutoCorrectionEngine.Kind;
			var oDegree = new CDegree(props)

			var BaseContent = oDegree.Content[0];
			var IterContent = oDegree.Content[1];

			this.PackTextToContent(BaseContent, TempElements2);	
			this.PackTextToContent(IterContent, TempElements);			

			AutoCorrectionEngine.RemoveCount = ElementsCount - CurPos - 1;
			AutoCorrectionEngine.ReplaceContent.push(oDegree);

			return true;
		//}
	}
	else if (AutoCorrectionEngine.Type == MATH_DEGREESubSup)
	{
		if (TempElements2.length > 0 || TempElements3.length > 0)
		{
			var props = new CMathDegreePr();
			props.type = AutoCorrectionEngine.Kind;
			var oDegree = new CDegreeSubSup(props)

			var BaseContent = oDegree.Content[0];
			var IterUpContent = oDegree.Content[1];
			var IterDnContent = oDegree.Content[2];
			
			if (TempElements.Type == DEGREE_SUPERSCRIPT)
			{
				this.PackTextToContent(IterUpContent, TempElements2);
				this.PackTextToContent(IterDnContent, TempElements);
			}
			else if (TempElements.Type == DEGREE_SUBSCRIPT)
			{
				this.PackTextToContent(IterUpContent, TempElements);
				this.PackTextToContent(IterDnContent, TempElements2);
			}
			
			this.PackTextToContent(BaseContent, TempElements3);			
			
			AutoCorrectionEngine.RemoveCount = ElementsCount - CurPos - 1;
			AutoCorrectionEngine.ReplaceContent.push(oDegree);

			return true;
		}
	}

    return false;
};
CMathContent.prototype.PackTextToContent = function(Element, TempElements)
{
	var len = TempElements.length;
	if (len > 1)	
		if (TempElements[0].Text === '(' && TempElements[len-1].Text === ')')
		{
			TempElements.splice(len-1,1);
			TempElements.splice(0,1);
			len -= 2 ;
		}
	
	for (var nPos = 0; nPos < len; nPos++)
	{
		if (undefined === TempElements[nPos].Text)
			Element.Internal_Content_Add(nPos, TempElements[nPos].Element);
		else
		{
			var MathRun = new ParaRun(this.ParaMath.Paragraph, true);
			var MathText = new CMathText();
			MathText.add(TempElements[nPos].Text.charCodeAt(0));
			MathRun.Add_ToContent(nPos, MathText);
			Element.Internal_Content_Add(nPos, MathRun);
		}
	}
};

function CMathAutoCorrectEngine(Element)
{
    this.ActionElement  = Element; // Элемент на которотом срабатывает автодополнение
    this.Elements       = [];

    this.CollectText    = true;
	this.Type			= null;
	this.Kind			= null;

    this.RemoveCount    = 0;
    this.ReplaceContent = [];
}

CMathAutoCorrectEngine.prototype.Add_Element = function(Element, ElementPos)
{
    this.Elements.push({Element : Element, ElementPos : ElementPos});
};

CMathAutoCorrectEngine.prototype.Add_Text = function(Text, Run, Pos, ElementPos)
{
    this.Elements.push({Text : Text, Run : Run, Pos : Pos, ElementPos : ElementPos});
};

CMathAutoCorrectEngine.prototype.Get_ActionElement = function()
{
    return this.ActionElement;
};

CMathAutoCorrectEngine.prototype.Stop_CollectText = function()
{
    this.CollectText = false;
};

var g_aAutoCorrectMathSymbols =
[
        ['!!', 0x203C],
        ['...', 0x2026],
        ['::', 0x2237],
        [':=', 0x2254],
        ['\\above', 0x2534],
        ['\\acute', 0x0301],
        ['\\aleph', 0x2135],
        ['\\alpha', 0x03B1],
        ['\\Alpha', 0x0391],
        ['\\amalg', 0x2210],
        ['\\angle', 0x2220],
        ['\\aoint', 0x2233],
        ['\\approx', 0x2248],
        ['\\asmash', 0x2B06],
        ['\\ast', 0x2217],
        ['\\asymp', 0x224D],
        ['\\atop', 0x00A6],
        ['\\bar', 0x0305],
        ['\\Bar', 0x033F],
        ['\\because', 0x2235],
        ['\\begin', 0x3016],
        ['\\below', 0x252C],
        ['\\bet', 0x2136],
        ['\\beta', 0x03B2],
        ['\\Beta', 0x0392],
        ['\\beth', 0x2136],
        ['\\bigcap', 0x22C2],
        ['\\bigcup', 0x22C3],
        ['\\bigodot', 0x2A00],
        ['\\bigoplus', 0x2A01],
        ['\\bigotimes', 0x2A02],
        ['\\bigsqcup', 0x2A06],
        ['\\biguplus', 0x2A04],
        ['\\bigvee', 0x22C1],
        ['\\bigwedge', 0x22C0],
        ['\\bot', 0x22A5],
        ['\\bowtie', 0x22C8],
        ['\\box', 0x25A1],
        ['\\bra', 0x27E8],
        ['\\breve', 0x0306],
        ['\\bullet', 0x2219],
        ['\\cap', 0x2229],
        ['\\cbrt', 0x221B],
        ['\\cdot', 0x22C5],
        ['\\cdots', 0x22EF],
        ['\\check', 0x030C],
        ['\\chi', 0x03C7],
        ['\\Chi', 0x03A7],
        ['\\circ', 0x2218],
        ['\\close', 0x2524],
        ['\\clubsuit', 0x2663],
        ['\\coint', 0x2232],
        ['\\cong', 0x2245],
        ['\\coprod', 0x2210],
        ['\\cup', 0x222A],
        ['\\dalet', 0x2138],
        ['\\daleth', 0x2138],
        ['\\dashv', 0x22A3],
        ['\\dd', 0x2146],
        ['\\Dd', 0x2145],
        ['\\ddddot', 0x20DC],
        ['\\dddot', 0x20DB],
        ['\\ddot', 0x0308],
        ['\\ddots', 0x22F1],
        ['\\degree', 0x00B0],
        ['\\delta', 0x03B4],
        ['\\Delta', 0x0394],
        ['\\diamond', 0x22C4],
        ['\\diamondsuit', 0x2662],
        ['\\div', 0x00F7],
        ['\\dot', 0x0307],
        ['\\doteq', 0x2250],
        ['\\dots', 0x2026],
        ['\\doublea', 0x1D552],
        ['\\doubleA', 0x1D538],
        ['\\doubleb', 0x1D553],
        ['\\doubleB', 0x1D539],
        ['\\doublec', 0x1D554],
        ['\\doubleC', 0x2102],
        ['\\doubled', 0x1D555],
        ['\\doubleD', 0x1D53B],
        ['\\doublee', 0x1D556],
        ['\\doubleE', 0x1D53C],
        ['\\doublef', 0x1D557],
        ['\\doubleF', 0x1D53D],
        ['\\doubleg', 0x1D558],
        ['\\doubleG', 0x1D53E],
        ['\\doubleh', 0x1D559],
        ['\\doubleH', 0x210D],
        ['\\doublei', 0x1D55A],
        ['\\doubleI', 0x1D540],
        ['\\doublej', 0x1D55B],
        ['\\doubleJ', 0x1D541],
        ['\\doublek', 0x1D55C],
        ['\\doubleK', 0x1D542],
        ['\\doublel', 0x1D55D],
        ['\\doubleL', 0x1D543],
        ['\\doublem', 0x1D55E],
        ['\\doubleM', 0x1D544],
        ['\\doublen', 0x1D55F],
        ['\\doubleN', 0x2115],
        ['\\doubleo', 0x1D560],
        ['\\doubleO', 0x1D546],
        ['\\doublep', 0x1D561],
        ['\\doubleP', 0x2119],
        ['\\doubleq', 0x1D562],
        ['\\doubleQ', 0x211A],
        ['\\doubler', 0x1D563],
        ['\\doubleR', 0x211D],
        ['\\doubles', 0x1D564],
        ['\\doubleS', 0x1D54A],
        ['\\doublet', 0x1D565],
        ['\\doubleT', 0x1D54B],
        ['\\doubleu', 0x1D566],
        ['\\doubleU', 0x1D54C],
        ['\\doublev', 0x1D567],
        ['\\doubleV', 0x1D54D],
        ['\\doublew', 0x1D568],
        ['\\doubleW', 0x1D54E],
        ['\\doublex', 0x1D569],
        ['\\doubleX', 0x1D54F],
        ['\\doubley', 0x1D56A],
        ['\\doubleY', 0x1D550],
        ['\\doublez', 0x1D56B],
        ['\\doubleZ', 0x2124],
        ['\\downarrow', 0x2193],
        ['\\Downarrow', 0x21D3],
        ['\\dsmash', 0x2B07],
        ['\\ee', 0x2147],
        ['\\ell', 0x2113],
        ['\\emptyset', 0x2205],
        ['\\end', 0x3017],
        ['\\ensp', 0x2002],
        ['\\epsilon', 0x03F5],
        ['\\Epsilon', 0x0395],
        ['\\eqarray', 0x2588],
        ['\\equiv', 0x2261],
        ['\\eta', 0x03B7],
        ['\\Eta', 0x0397],
        ['\\exists', 0x2203],
        ['\\forall', 0x2200],
        ['\\fraktura', 0x1D51E],
        ['\\frakturA', 0x1D504],
        ['\\frakturb', 0x1D51F],
        ['\\frakturB', 0x1D505],
        ['\\frakturc', 0x1D520],
        ['\\frakturC', 0x212D],
        ['\\frakturd', 0x1D521],
        ['\\frakturD', 0x1D507],
        ['\\frakture', 0x1D522],
        ['\\frakturE', 0x1D508],
        ['\\frakturf', 0x1D523],
        ['\\frakturF', 0x1D509],
        ['\\frakturg', 0x1D524],
        ['\\frakturG', 0x1D50A],
        ['\\frakturh', 0x1D525],
        ['\\frakturH', 0x210C],
        ['\\frakturi', 0x1D526],
        ['\\frakturI', 0x2111],
        ['\\frakturj', 0x1D527],
        ['\\frakturJ', 0x1D50D],
        ['\\frakturk', 0x1D528],
        ['\\frakturK', 0x1D50E],
        ['\\frakturl', 0x1D529],
        ['\\frakturL', 0x1D50F],
        ['\\frakturm', 0x1D52A],
        ['\\frakturM', 0x1D510],
        ['\\frakturn', 0x1D52B],
        ['\\frakturN', 0x1D511],
        ['\\frakturo', 0x1D52C],
        ['\\frakturO', 0x1D512],
        ['\\frakturp', 0x1D52D],
        ['\\frakturP', 0x1D513],
        ['\\frakturq', 0x1D52E],
        ['\\frakturQ', 0x1D514],
        ['\\frakturr', 0x1D52F],
        ['\\frakturR', 0x211C],
        ['\\frakturs', 0x1D530],
        ['\\frakturS', 0x1D516],
        ['\\frakturt', 0x1D531],
        ['\\frakturT', 0x1D517],
        ['\\frakturu', 0x1D532],
        ['\\frakturU', 0x1D518],
        ['\\frakturv', 0x1D533],
        ['\\frakturV', 0x1D519],
        ['\\frakturw', 0x1D534],
        ['\\frakturW', 0x1D51A],
        ['\\frakturx', 0x1D535],
        ['\\frakturX', 0x1D51B],
        ['\\fraktury', 0x1D536],
        ['\\frakturY', 0x1D51C],
        ['\\frakturz', 0x1D537],
        ['\\frakturZ', 0x2128],
        ['\\funcapply', 0x2061],
        ['\\gamma', 0x03B3],
        ['\\Gamma', 0x0393],
        ['\\ge', 0x2265],
        ['\\geq', 0x2265],
        ['\\gets', 0x2190],
        ['\\gg', 0x226B],
        ['\\gimel', 0x2137],
        ['\\grave', 0x0300],
        ['\\hairsp', 0x200A],
        ['\\hat', 0x0302],
        ['\\hbar', 0x210F],
        ['\\heartsuit', 0x2661],
        ['\\hookleftarrow', 0x21A9],
        ['\\hookrightarrow', 0x21AA],
        ['\\hphantom', 0x2B04],
        ['\\hvec', 0x20D1],
        ['\\ii', 0x2148],
        ['\\iiint', 0x222D],
        ['\\iint', 0x222C],
        ['\\Im', 0x2111],
        ['\\in', 0x2208],
        ['\\inc', 0x2206],
        ['\\infty', 0x221E],
        ['\\int', 0x222B],
        ['\\iota', 0x03B9],
        ['\\Iota', 0x0399],
        ['\\jj', 0x2149],
        ['\\kappa', 0x03BA],
        ['\\Kappa', 0x039A],
        ['\\ket', 0x27E9],
        ['\\lambda', 0x03BB],
        ['\\Lambda', 0x039B],
        ['\\langle', 0x2329],
        ['\\lbrace', 0x007B],
        ['\\lbrack', 0x005B],
        ['\\lceil', 0x2308],
        ['\\ldiv', 0x2215],
        ['\\ldivide', 0x2215],
        ['\\ldots', 0x2026],
        ['\\le', 0x2264],
        ['\\left', 0x251C],
        ['\\leftarrow', 0x2190],
        ['\\Leftarrow', 0x21D0],
        ['\\leftharpoondown', 0x21BD],
        ['\\leftharpoonup', 0x21BC],
        ['\\leftrightarrow', 0x2194],
        ['\\Leftrightarrow', 0x21D4],
        ['\\leq', 0x2264],
        ['\\lfloor', 0x230A],
        ['\\ll', 0x226A],
        ['\\mapsto', 0x21A6],
        ['\\matrix', 0x25A0],
        ['\\medsp', 0x205F],
        ['\\mid', 0x2223],
        ['\\models', 0x22A8],
        ['\\mp', 0x2213],
        ['\\mu', 0x03BC],
        ['\\Mu', 0x039C],
        ['\\nabla', 0x2207],
        ['\\naryand', 0x2592],
        ['\\nbsp', 0x00A0],
        ['\\ne', 0x2260],
        ['\\nearrow', 0x2197],
        ['\\neq', 0x2260],
        ['\\ni', 0x220B],
        ['\\norm', 0x2016],
        ['\\notcontain', 0x220C],
        ['\\notelement', 0x2209],
        ['\\nu', 0x03BD],
        ['\\Nu', 0x039D],
        ['\\nwarrow', 0x2196],
        ['\\o', 0x03BF],
        ['\\O', 0x039F],
        ['\\odot', 0x2299],
        ['\\of', 0x2592],
        ['\\oiiint', 0x2230],
        ['\\oiint', 0x222F],
        ['\\oint', 0x222E],
        ['\\omega', 0x03C9],
        ['\\Omega', 0x03A9],
        ['\\ominus', 0x2296],
        ['\\open', 0x251C],
        ['\\oplus', 0x2295],
        ['\\otimes', 0x2297],
        ['\\over', 0x002F],
        ['\\overbar', 0x00AF],
        ['\\overbrace', 0x23DE],
        ['\\overparen', 0x23DC],
        ['\\parallel', 0x2225],
        ['\\partial', 0x2202],
        ['\\phantom', 0x27E1],
        ['\\phi', 0x03D5],
        ['\\Phi', 0x03A6],
        ['\\pi', 0x03C0],
        ['\\Pi', 0x03A0],
        ['\\pm', 0x00B1],
        ['\\pppprime', 0x2057],
        ['\\ppprime', 0x2034],
        ['\\pprime', 0x2033],
        ['\\prec', 0x227A],
        ['\\preceq', 0x227C],
        ['\\prime', 0x2032],
        ['\\prod', 0x220F],
        ['\\propto', 0x221D],
        ['\\psi', 0x03C8],
        ['\\Psi', 0x03A8],
        ['\\qdrt', 0x221C],
        ['\\quadratic', [0x0078, 0x003d, 0x0028, 0x002d, 0x0062, 0x00B1, 0x221A, 0x0020, 0x0028, 0x0062, 0x005e, 0x0032, 0x002d, 0x0034, 0x0061, 0x0063, 0x0029, 0x0029, 0x002f, 0x0032, 0x0061]],
        ['\\rangle', 0x232A],
        ['\\ratio', 0x2236],
        ['\\rbrace', 0x007D],
        ['\\rbrack', 0x005D],
        ['\\rceil', 0x2309],
        ['\\rddots', 0x22F0],
        ['\\Re', 0x211C],
        ['\\rect', 0x25AD],
        ['\\rfloor', 0x230B],
        ['\\rho', 0x03C1],
        ['\\Rho', 0x03A1],
        ['\\right', 0x2524],
        ['\\rightarrow', 0x2192],
        ['\\Rightarrow', 0x21D2],
        ['\\rightharpoondown', 0x21C1],
        ['\\rightharpoonup', 0x21C0],
        ['\\scripta', 0x1D4B6],
        ['\\scriptA', 0x1D49C],
        ['\\scriptb', 0x1D4B7],
        ['\\scriptB', 0x212C],
        ['\\scriptc', 0x1D4B8],
        ['\\scriptC', 0x1D49E],
        ['\\scriptd', 0x1D4B9],
        ['\\scriptD', 0x1D49F],
        ['\\scripte', 0x212F],
        ['\\scriptE', 0x2130],
        ['\\scriptf', 0x1D4BB],
        ['\\scriptF', 0x2131],
        ['\\scriptg', 0x210A],
        ['\\scriptG', 0x1D4A2],
        ['\\scripth', 0x1D4BD],
        ['\\scriptH', 0x210B],
        ['\\scripti', 0x1D4BE],
        ['\\scriptI', 0x2110],
        ['\\scriptj', 0x1D4BF],
        ['\\scriptJ', 0x1D4A5],
        ['\\scriptk', 0x1D4C0],
        ['\\scriptK', 0x1D4A6],
        ['\\scriptl', 0x2113],
        ['\\scriptL', 0x2112],
        ['\\scriptm', 0x1D4C2],
        ['\\scriptM', 0x2133],
        ['\\scriptn', 0x1D4C3],
        ['\\scriptN', 0x1D4A9],
        ['\\scripto', 0x2134],
        ['\\scriptO', 0x1D4AA],
        ['\\scriptp', 0x1D4C5],
        ['\\scriptP', 0x1D4AB],
        ['\\scriptq', 0x1D4C6],
        ['\\scriptQ', 0x1D4AC],
        ['\\scriptr', 0x1D4C7],
        ['\\scriptR', 0x211B],
        ['\\scripts', 0x1D4C8],
        ['\\scriptS', 0x1D4AE],
        ['\\scriptt', 0x1D4C9],
        ['\\scriptT', 0x1D4AF],
        ['\\scriptu', 0x1D4CA],
        ['\\scriptU', 0x1D4B0],
        ['\\scriptv', 0x1D4CB],
        ['\\scriptV', 0x1D4B1],
        ['\\scriptw', 0x1D4CC],
        ['\\scriptW', 0x1D4B2],
        ['\\scriptx', 0x1D4CD],
        ['\\scriptX', 0x1D4B3],
        ['\\scripty', 0x1D4CE],
        ['\\scriptY', 0x1D4B4],
        ['\\scriptz', 0x1D4CF],
        ['\\scriptZ', 0x1D4B5],
        ['\\sdiv', 0x2044],
        ['\\sdivide', 0x2044],
        ['\\searrow', 0x2198],
        ['\\setminus', 0x2216],
        ['\\sigma', 0x03C3],
        ['\\Sigma', 0x03A3],
        ['\\sim', 0x223C],
        ['\\simeq', 0x2243],
        ['\\smash', 0x2B0D],
        ['\\spadesuit', 0x2660],
        ['\\sqcap', 0x2293],
        ['\\sqcup', 0x2294],
        ['\\sqrt', 0x221A],
        ['\\sqsubseteq', 0x2291],
        ['\\sqsuperseteq', 0x2292],
        ['\\star', 0x22C6],
        ['\\subset', 0x2282],
        ['\\subseteq', 0x2286],
        ['\\succ', 0x227B],
        ['\\succeq', 0x227D],
        ['\\sum', 0x2211],
        ['\\superset', 0x2283],
        ['\\superseteq', 0x2287],
        ['\\swarrow', 0x2199],
        ['\\tau', 0x03C4],
        ['\\Tau', 0x03A4],
        ['\\therefore', 0x2234],
        ['\\theta', 0x03B8],
        ['\\Theta', 0x0398],
        ['\\thicksp', 0x2005],
        ['\\thinsp', 0x2006],
        ['\\tilde', 0x0303],
        ['\\times', 0x00D7],
        ['\\to', 0x2192],
        ['\\top', 0x22A4],
        ['\\tvec', 0x20E1],
        ['\\ubar', 0x0332],
        ['\\Ubar', 0x0333],
        ['\\underbar', 0x2581],
        ['\\underbrace', 0x23DF],
        ['\\underparen', 0x23DD],
        ['\\uparrow', 0x2191],
        ['\\Uparrow', 0x21D1],
        ['\\updownarrow', 0x2195],
        ['\\Updownarrow', 0x21D5],
        ['\\uplus', 0x228E],
        ['\\upsilon', 0x03C5],
        ['\\Upsilon', 0x03A5],
        ['\\varepsilon', 0x03B5],
        ['\\varphi', 0x03C6],
        ['\\varpi', 0x03D6],
        ['\\varrho', 0x03F1],
        ['\\varsigma', 0x03C2],
        ['\\vartheta', 0x03D1],
        ['\\vbar', 0x2502],
        ['\\vdash', 0x22A2],
        ['\\vdots', 0x22EE],
        ['\\vec', 0x20D7],
        ['\\vee', 0x2228],
        ['\\vert', 0x007C],
        ['\\Vert', 0x2016],
        ['\\vphantom', 0x21F3],
        ['\\vthicksp', 0x2004],
        ['\\wedge', 0x2227],
        ['\\wp', 0x2118],
        ['\\wr', 0x2240],
        ['\\xi', 0x03BE],
        ['\\Xi', 0x039E],
        ['\\zeta', 0x03B6],
        ['\\Zeta', 0x0396],
        ['\\zwnj', 0x200C],
        ['\\zwsp', 0x200B],
        ['~=', 0x2245],
        ['-+', 0x2213],
        ['+-', 0x00B1],
        ['<<', 0x226A],
        ['<=', 0x2264],
        ['->', 0x2192],
        ['>=', 0x2265],
        ['>>', 0x226B]
];

var g_aMathAutoCorrectTriggerCharCodes =
{
    0x20 : 1, 0x21 : 1, 0x22 : 1, 0x23 : 1, 0x24 : 1, 0x25 : 1, 0x26 : 1,
    0x27 : 1, 0x28 : 1, 0x29 : 1, 0x2A : 1, 0x2B : 1, 0x2C : 1, 0x2D : 1,
    0x2E : 1, 0x2F : 1, 0x3A : 1, 0x3B : 1, 0x3C : 1, 0x3D : 1, 0x3E : 1,
    0x3F : 1, 0x40 : 1, 0x5B : 1, 0x5C : 1, 0x5D : 1, 0x5E : 1, 0x5F : 1,
    0x60 : 1, 0x7B : 1, 0x7C : 1, 0x7D : 1, 0x7E : 1
};