private bool IsAtCaretUnitBoundaryFromDcpCompositeLines( int dcp, ITextPointer position, ref PTS.FSTEXTDETAILSFULL textDetails) { ErrorHandler.Assert(!PTS.ToBoolean(textDetails.fDropCapPresent), ErrorHandler.NotSupportedDropCap); // Get list of lines PTS.FSLINEDESCRIPTIONCOMPOSITE[] arrayLineDesc; PtsHelper.LineListCompositeFromTextPara(PtsContext, _paraHandle.Value, ref textDetails, out arrayLineDesc); bool isAtCaretUnitBoundary = false; // First iterate through lines for (int index = 0; index < arrayLineDesc.Length; index++) { PTS.FSLINEDESCRIPTIONCOMPOSITE lineDesc = arrayLineDesc[index]; if (lineDesc.cElements == 0) { continue; } // Get list of line elements. PTS.FSLINEELEMENT[] arrayLineElement; PtsHelper.LineElementListFromCompositeLine(PtsContext, ref lineDesc, out arrayLineElement); for (int elIndex = 0; elIndex < arrayLineElement.Length; elIndex++) { PTS.FSLINEELEMENT element = arrayLineElement[elIndex]; // 'dcp' needs to be within line range. If position points to dcpLim, // it means that the next line starts from such position, hence go to the next line. if (((element.dcpFirst <= dcp) && (element.dcpLim > dcp)) || ((element.dcpLim == dcp) && (elIndex == arrayLineElement.Length - 1) && (index == arrayLineDesc.Length - 1))) { CharacterHit charHit = new CharacterHit(); if (dcp >= element.dcpLim - 1 && elIndex == arrayLineElement.Length - 1 && index == arrayLineDesc.Length - 1) { // Special case: at the end of the last line there is a special character that // does not belong to the line. Return true for this case return true; } if (position.LogicalDirection == LogicalDirection.Backward) { // Beginning of element. if (dcp == element.dcpFirst) { if (elIndex > 0) { // Beginning of element, but not of line. Create char hit at last dcp of previous element, trailing edge. --elIndex; element = arrayLineElement[elIndex]; charHit = new CharacterHit(dcp - 1, 1); } else { // Beginning of line if (index == 0) { // Backward context at start position of first line is not considered a unit boundary return false; } else { // Go to previous line --index; lineDesc = arrayLineDesc[index]; if (lineDesc.cElements == 0) { return false; } else { // Get list of line elements. PtsHelper.LineElementListFromCompositeLine(PtsContext, ref lineDesc, out arrayLineElement); element = arrayLineElement[arrayLineElement.Length - 1]; charHit = new CharacterHit(dcp - 1, 1); } } } } else { // Get trailing edge of previous dcp Invariant.Assert(dcp > 0); charHit = new CharacterHit(dcp - 1, 1); } } else if (position.LogicalDirection == LogicalDirection.Forward) { // Create character hit at leading edge charHit = new CharacterHit(dcp, 0); } // Create and format line Line line = new Line(Paragraph.StructuralCache.TextFormatterHost, this, Paragraph.ParagraphStartCharacterPosition); Line.FormattingContext ctx = new Line.FormattingContext(false, PTS.ToBoolean(element.fClearOnLeft), PTS.ToBoolean(element.fClearOnRight), TextParagraph.TextRunCache); if(IsOptimalParagraph) { ctx.LineFormatLengthTarget = element.dcpLim - element.dcpFirst; } TextParagraph.FormatLineCore(line, element.pfsbreakreclineclient, ctx, element.dcpFirst, element.dur, PTS.ToBoolean(lineDesc.fTreatedAsFirst), element.dcpFirst); // Assert that number of characters in Text line is the same as our expected length Invariant.Assert(line.SafeLength == element.dcpLim - element.dcpFirst, "Line length is out of [....]"); isAtCaretUnitBoundary = line.IsAtCaretCharacterHit(charHit); // Dispose the line line.Dispose(); return isAtCaretUnitBoundary; } } } return isAtCaretUnitBoundary; }
private bool IsAtCaretUnitBoundaryFromDcpSimpleLines( int dcp, ITextPointer position, ref PTS.FSTEXTDETAILSFULL textDetails) { ErrorHandler.Assert(!PTS.ToBoolean(textDetails.fDropCapPresent), ErrorHandler.NotSupportedDropCap); // Get list of lines PTS.FSLINEDESCRIPTIONSINGLE[] arrayLineDesc; PtsHelper.LineListSimpleFromTextPara(PtsContext, _paraHandle.Value, ref textDetails, out arrayLineDesc); bool isAtCaretUnitBoundary = false; // First iterate through lines for (int index = 0; index < arrayLineDesc.Length; index++) { PTS.FSLINEDESCRIPTIONSINGLE lineDesc = arrayLineDesc[index]; // 'dcp' needs to be within line range. If position points to dcpLim, // it means that the next line starts from such position, hence go to the next line. if (((lineDesc.dcpFirst <= dcp) && (lineDesc.dcpLim > dcp)) || ((lineDesc.dcpLim == dcp) && (index == arrayLineDesc.Length - 1))) { CharacterHit charHit = new CharacterHit(); if (dcp >= lineDesc.dcpLim - 1 && index == arrayLineDesc.Length - 1) { // Special case: last line has additional character to mark the end of paragraph. // We should not try and check for next source character index // But just return true in this case return true; } if (position.LogicalDirection == LogicalDirection.Backward) { if (lineDesc.dcpFirst == dcp) { if (index == 0) { // First position of first line does not have a trailing edge. Return false. return false; } else { // Get the trailing edge of the last character on the previous line, at dcp - 1 index--; lineDesc = arrayLineDesc[index]; Invariant.Assert(dcp > 0); charHit = new CharacterHit(dcp - 1, 1); } } else { // Get CharacterHit at trailing edge of previous position Invariant.Assert(dcp > 0); charHit = new CharacterHit(dcp - 1, 1); } } else if (position.LogicalDirection == LogicalDirection.Forward) { // Get character hit at leading edge charHit = new CharacterHit(dcp, 0); } // Create and format line Line line = new Line(Paragraph.StructuralCache.TextFormatterHost, this, Paragraph.ParagraphStartCharacterPosition); Line.FormattingContext ctx = new Line.FormattingContext(false, PTS.ToBoolean(lineDesc.fClearOnLeft), PTS.ToBoolean(lineDesc.fClearOnRight), TextParagraph.TextRunCache); if(IsOptimalParagraph) { ctx.LineFormatLengthTarget = lineDesc.dcpLim - lineDesc.dcpFirst; } TextParagraph.FormatLineCore(line, lineDesc.pfsbreakreclineclient, ctx, lineDesc.dcpFirst, lineDesc.dur, PTS.ToBoolean(lineDesc.fTreatedAsFirst), lineDesc.dcpFirst); // Assert that number of characters in Text line is the same as our expected length Invariant.Assert(line.SafeLength == lineDesc.dcpLim - lineDesc.dcpFirst, "Line length is out of [....]"); isAtCaretUnitBoundary = line.IsAtCaretCharacterHit(charHit); // Dispose the line line.Dispose(); break; } } return isAtCaretUnitBoundary; }