private void EnsureListAndListItem(FormatState formatState, DocumentNodeArray dna, MarkerList mlHave, MarkerList mlWant, int nMatch)
        {
            int nInsertAt;

            bool added = false;

            int nLists = mlHave.Count;
            int nLevel = mlWant.Count;

            // Close any open lists that don't match the ones we want.
            bool bInField = dna.FindUnmatched(DocumentNodeType.dnFieldBegin) >= 0;
            if (nLists > nMatch)
            {
                DocumentNode documentNodePara = dna.Pop();
                while (nLists > nMatch)
                {
                    int nOpen = dna.FindPending(DocumentNodeType.dnList);
                    if (nOpen >= 0)
                    {
                        dna.CloseAt(nOpen);

                        // Only coalesce if this is a top-level list.  Otherwise I want to get
                        // the full structure to use for margin fixups so I delay coalescing.
                        // No, don't coalesce since a later list may need to get merged with this one.
                        // if (!bInField && dna.FindPending(DocumentNodeType.dnList) < 0)
                        //    dna.CoalesceChildren(_converterState, nOpen);
                    }
                    nLists--;
                    mlHave.RemoveRange(mlHave.Count - 1, 1);
                }
                dna.Push(documentNodePara);
            }

            if (nLists < nLevel)
            {
                // Multiple immediately nested lists are handled poorly in Avalon and are usually an indication
                // of bad input from Word (or some other word processor).  Clip the number of lists we'll create here.
                if (nLevel != nLists + 1)
                {
                    // I'm going to truncate, but make the list I create here of the specific type at this level.
                    if (nLevel <= mlWant.Count)
                    {
                        mlWant[nLists] = mlWant[mlWant.Count - 1];
                    }
                    nLevel = nLists + 1;
                }

                // Ensure sufficient lists are open - this may be our first indication
                // Insert the list nodes right before the current paragraph
                nInsertAt = dna.Count - 1;

                while (nLists < nLevel)
                {
                    added = true;

                    DocumentNode dnList = new DocumentNode(DocumentNodeType.dnList);
                    DocumentNode dnLI = new DocumentNode(DocumentNodeType.dnListItem);

                    dna.InsertNode(nInsertAt, dnLI);
                    dna.InsertNode(nInsertAt, dnList);

                    // Set the list properties
                    MarkerListEntry mle = mlWant.EntryAt(nLists);
                    dnList.FormatState.Marker = mle.Marker;
                    dnList.FormatState.StartIndex = mle.StartIndexToUse;
                    dnList.FormatState.StartIndexDefault = mle.StartIndexDefault;
                    dnList.VirtualListLevel = mle.VirtualListLevel;
                    dnList.FormatState.ILS = mle.ILS;
                    nLists++;
                }
            }

            // Ensure listitem is open
            nInsertAt = dna.Count - 1;
            int nList = dna.FindPending(DocumentNodeType.dnList);
            if (nList >= 0)
            {
                int nLI = dna.FindPending(DocumentNodeType.dnListItem, nList);

                if (nLI >= 0 && !added && !formatState.IsContinue)
                {
                    DocumentNode documentNodePara = dna.Pop();
                    dna.CloseAt(nLI);
                    // Don't coalesce - I may need to do margin fixup.
                    // dna.CoalesceChildren(_converterState, nLI);
                    dna.Push(documentNodePara);

                    nLI = -1;
                    nInsertAt = dna.Count - 1;
                }
                if (nLI == -1)
                {
                    DocumentNode dnLI = new DocumentNode(DocumentNodeType.dnListItem);

                    dna.InsertNode(nInsertAt, dnLI);
                }
            }
        }
Пример #2
0
            // Helper for IXamlContentHandler.StartElement.
            private XamlToRtfError HandleAttributes(ConverterState converterState, IXamlAttributes attributes, 
                DocumentNode documentNode, XamlTag xamlTag, DocumentNodeArray dna)
            { 
                int nLen = 0; 

                XamlToRtfError xamlToRtfError = attributes.GetLength(ref nLen); 

                if (xamlToRtfError == XamlToRtfError.None)
                {
                    string uri = string.Empty; 
                    string newLocalName = string.Empty;
                    string newQName = string.Empty; 
                    string valueString = string.Empty; 

                    FormatState formatState = documentNode.FormatState; 
                    XamlAttribute attribute = XamlAttribute.XAUnknown;
                    long valueData = 0;

                    for (int i = 0; xamlToRtfError == XamlToRtfError.None && i < nLen; i++) 
                    {
                        xamlToRtfError = attributes.GetName(i, ref uri, ref newLocalName, ref newQName); 
 
                        if (xamlToRtfError == XamlToRtfError.None)
                        { 
                            xamlToRtfError = attributes.GetValue(i, ref valueString);

                            if (xamlToRtfError == XamlToRtfError.None &&
                                XamlParserHelper.ConvertToAttribute(converterState, newLocalName, ref attribute)) 
                            {
                                switch (attribute) 
                                { 
                                    case XamlAttribute.XAUnknown:
                                        break; 

                                    case XamlAttribute.XAFontWeight:
                                        if (string.Compare(valueString, "Normal", StringComparison.OrdinalIgnoreCase) == 0)
                                        { 
                                            formatState.Bold = false;
                                        } 
                                        else if (string.Compare(valueString, "Bold", StringComparison.OrdinalIgnoreCase) == 0) 
                                        {
                                            formatState.Bold = true; 
                                        }
                                        break;

                                    case XamlAttribute.XAFontSize: 
                                        double fs = 0f;
 
                                        if (XamlParserHelper.ConvertToFontSize(converterState, valueString, ref fs)) 
                                        {
                                            formatState.FontSize = (long)Math.Round(fs); 
                                        }
                                        break;

                                    case XamlAttribute.XAFontStyle: 
                                        if (string.Compare(valueString, "Italic", StringComparison.OrdinalIgnoreCase) == 0)
                                        { 
                                            formatState.Italic = true; 
                                        }
                                        break; 

                                    case XamlAttribute.XAFontFamily:
                                        if (XamlParserHelper.ConvertToFont(converterState, valueString, ref valueData))
                                        { 
                                            formatState.Font = valueData;
                                        } 
                                        break; 

                                    case XamlAttribute.XAFontStretch: 
                                        if (XamlParserHelper.ConvertToFontStretch(converterState, valueString, ref valueData))
                                        {
                                            formatState.Expand = valueData;
                                        } 
                                        break;
 
                                    case XamlAttribute.XABackground: 
                                        if (XamlParserHelper.ConvertToColor(converterState, valueString, ref valueData))
                                        { 
                                            if (documentNode.IsInline)
                                            {
                                                formatState.CB = valueData;
                                            } 
                                            else
                                            { 
                                                formatState.CBPara = valueData; 
                                            }
                                        } 
                                        break;

                                    case XamlAttribute.XAForeground:
                                        if (XamlParserHelper.ConvertToColor(converterState, valueString, ref valueData)) 
                                        {
                                            formatState.CF = valueData; 
                                        } 
                                        break;
 
                                    case XamlAttribute.XAFlowDirection:
                                        DirState dirState = DirState.DirDefault;

                                        if (XamlParserHelper.ConvertToDir(converterState, valueString, ref dirState)) 
                                        {
                                            if (documentNode.IsInline) 
                                            { 
                                                formatState.DirChar = dirState;
                                            } 
                                            else if (documentNode.Type == DocumentNodeType.dnTable)
                                            {
                                                formatState.RowFormat.Dir = dirState;
                                            } 
                                            else
                                            { 
                                                formatState.DirPara = dirState; 

                                                // Set the default inline flow direction as the paragraph's flow direction 
                                                formatState.DirChar = dirState;
                                            }

                                            if (documentNode.Type == DocumentNodeType.dnList) 
                                            {
                                                // Reset the left/right margin for List as the default value(720) 
                                                // on RTL flow direction. Actually LI is set as 720 as the default 
                                                // CreateDocumentNode().
                                                if (formatState.DirPara == DirState.DirRTL) 
                                                {
                                                    formatState.LI = 0;
                                                    formatState.RI = 720;
                                                } 
                                            }
                                        } 
                                        break; 

                                    case XamlAttribute.XATextDecorations: 
                                        {
                                            ULState ulState = ULState.ULNormal;
                                            StrikeState strikeState = StrikeState.StrikeNormal;
 
                                            if (XamlParserHelper.ConvertToDecoration(converterState, valueString,
                                                                                     ref ulState, 
                                                                                     ref strikeState)) 
                                            {
                                                if (ulState != ULState.ULNone) 
                                                {
                                                    formatState.UL = ulState;
                                                }
                                                if (strikeState != StrikeState.StrikeNone) 
                                                {
                                                    formatState.Strike = strikeState; 
                                                } 
                                            }
                                        } 
                                        break;

                                    case XamlAttribute.XALocation:
                                        { 
                                            ULState ulState = ULState.ULNormal;
                                            StrikeState strikeState = StrikeState.StrikeNormal; 
 
                                            if (XamlParserHelper.ConvertToDecoration(converterState, valueString,
                                                                                     ref ulState, 
                                                                                     ref strikeState))
                                            {
                                                if (ulState != ULState.ULNone)
                                                { 
                                                    formatState.UL = ulState;
                                                } 
                                                if (strikeState != StrikeState.StrikeNone) 
                                                {
                                                    formatState.Strike = strikeState; 
                                                }
                                            }
                                        }
                                        break; 

                                    case XamlAttribute.XARowSpan: 
                                        { 
                                            int nRowSpan = 0;
 
                                            if (Converters.StringToInt(valueString, ref nRowSpan))
                                            {
                                                if (documentNode.Type == DocumentNodeType.dnCell)
                                                { 
                                                    documentNode.RowSpan = nRowSpan;
                                                } 
                                            } 
                                        }
                                        break; 

                                    case XamlAttribute.XAColumnSpan:
                                        {
                                            int nColSpan = 0; 

                                            if (Converters.StringToInt(valueString, ref nColSpan)) 
                                            { 
                                                if (documentNode.Type == DocumentNodeType.dnCell)
                                                { 
                                                    documentNode.ColSpan = nColSpan;
                                                }
                                            }
                                        } 
                                        break;
 
                                    case XamlAttribute.XACellSpacing: 
                                        {
                                            double d = 0f; 

                                            if (Converters.StringToDouble(valueString, ref d))
                                            {
                                                if (documentNode.Type == DocumentNodeType.dnTable) 
                                                {
                                                    formatState.RowFormat.Trgaph = Converters.PxToTwipRounded(d); 
                                                } 
                                            }
                                        } 
                                        break;

                                    case XamlAttribute.XANavigateUri:
                                        if (xamlTag == XamlTag.XTHyperlink && valueString.Length > 0) 
                                        {
                                            StringBuilder sb = new StringBuilder(); 
 
                                            XamlParserHelper.AppendRTFText(sb, valueString, 0);
                                            documentNode.NavigateUri = sb.ToString(); 
                                        }
                                        break;

                                    case XamlAttribute.XAWidth: 
                                        if (xamlTag == XamlTag.XTTableColumn)
                                        { 
                                            double d = 0f; 

                                            if (Converters.StringToDouble(valueString, ref d)) 
                                            {
                                                int nTableAt = dna.FindPending(DocumentNodeType.dnTable);
                                                if (nTableAt >= 0)
                                                { 
                                                    DocumentNode dnTable = dna.EntryAt(nTableAt);
                                                    RowFormat rf = dnTable.FormatState.RowFormat; 
                                                    CellFormat cf = rf.NextCellFormat(); 

                                                    cf.Width.Type = WidthType.WidthTwips; 
                                                    cf.Width.Value = Converters.PxToTwipRounded(d);
                                                }
                                            }
                                        } 
                                        else if (xamlTag == XamlTag.XTImage)
                                        { 
                                            double d = 0f; 
                                            Converters.StringToDouble(valueString, ref d);
                                            documentNode.FormatState.ImageWidth = d; 
                                        }
                                        break;

                                    case XamlAttribute.XAHeight: 
                                        if (xamlTag == XamlTag.XTImage)
                                        { 
                                            double d = 0f; 
                                            Converters.StringToDouble(valueString, ref d);
                                            documentNode.FormatState.ImageHeight = d; 
                                        }
                                        break;

                                    case XamlAttribute.XASource: 
                                        if (xamlTag == XamlTag.XTImage)
                                        { 
                                            documentNode.FormatState.ImageSource = valueString; 
                                        }
                                        break; 

                                    case XamlAttribute.XAUriSource:
                                        if (xamlTag == XamlTag.XTBitmapImage)
                                        { 
                                            documentNode.FormatState.ImageSource = valueString;
                                        } 
                                        break; 

                                    case XamlAttribute.XAStretch: 
                                        if (xamlTag == XamlTag.XTImage)
                                        {
                                            documentNode.FormatState.ImageStretch = valueString;
                                        } 
                                        break;
 
                                    case XamlAttribute.XAStretchDirection: 
                                        if (xamlTag == XamlTag.XTImage)
                                        { 
                                            documentNode.FormatState.ImageStretchDirection = valueString;
                                        }
                                        break;
 
                                    case XamlAttribute.XATypographyVariants:
                                        RtfSuperSubscript ss = RtfSuperSubscript.None; 
 
                                        if (XamlParserHelper.ConvertToSuperSub(converterState, valueString, ref ss))
                                        { 
                                            if (ss == RtfSuperSubscript.Super)
                                            {
                                                formatState.Super = true;
                                            } 
                                            else if (ss == RtfSuperSubscript.Sub)
                                            { 
                                                formatState.Sub = true; 
                                            }
                                            else if (ss == RtfSuperSubscript.Normal) 
                                            {
                                                formatState.Sub = false;
                                                formatState.Super = false;
                                            } 
                                        }
                                        break; 
 
                                    case XamlAttribute.XAMarkerStyle:
                                        MarkerStyle ms = MarkerStyle.MarkerBullet; 

                                        if (XamlParserHelper.ConvertToMarkerStyle(converterState, valueString, ref ms))
                                        {
                                            formatState.Marker = ms; 
                                        }
                                        break; 
 
                                    case XamlAttribute.XAStartIndex:
                                        int nStart = 0; 

                                        if (XamlParserHelper.ConvertToStartIndex(converterState, valueString, ref nStart))
                                        {
                                            formatState.StartIndex = nStart; 
                                        }
                                        break; 
 
                                    case XamlAttribute.XAMargin:
                                        { 
                                            XamlThickness thickness = new XamlThickness(0f, 0f, 0f, 0f);
                                            if (XamlParserHelper.ConvertToThickness(converterState, valueString, ref thickness))
                                            {
                                                formatState.LI = Converters.PxToTwipRounded(thickness.Left); 
                                                formatState.RI = Converters.PxToTwipRounded(thickness.Right);
                                                formatState.SB = Converters.PxToTwipRounded(thickness.Top); 
                                                formatState.SA = Converters.PxToTwipRounded(thickness.Bottom); 
                                            }
                                        } 
                                        break;

                                    case XamlAttribute.XAPadding:
                                        { 
                                            XamlThickness t = new XamlThickness(0f, 0f, 0f, 0f);
                                            if (XamlParserHelper.ConvertToThickness(converterState, valueString, ref t)) 
                                            { 
                                                if (xamlTag == XamlTag.XTParagraph)
                                                { 
                                                    // RTF only supports a single border padding value.
                                                    formatState.ParaBorder.Spacing = Converters.PxToTwipRounded(t.Left);
                                                }
                                                else 
                                                {
                                                    RowFormat rf = formatState.RowFormat; 
                                                    CellFormat cf = rf.RowCellFormat; 
                                                    cf.PaddingLeft = Converters.PxToTwipRounded(t.Left);
                                                    cf.PaddingRight = Converters.PxToTwipRounded(t.Right); 
                                                    cf.PaddingTop = Converters.PxToTwipRounded(t.Top);
                                                    cf.PaddingBottom = Converters.PxToTwipRounded(t.Bottom);
                                                }
                                            } 
                                        }
                                        break; 
 
                                    case XamlAttribute.XABorderThickness:
                                        { 
                                            XamlThickness t = new XamlThickness(0f, 0f, 0f, 0f);
                                            if (XamlParserHelper.ConvertToThickness(converterState, valueString, ref t))
                                            {
                                                if (xamlTag == XamlTag.XTParagraph) 
                                                {
                                                    ParaBorder pf = formatState.ParaBorder; 
                                                    pf.BorderLeft.Type = BorderType.BorderSingle; 
                                                    pf.BorderLeft.Width = Converters.PxToTwipRounded(t.Left);
                                                    pf.BorderRight.Type = BorderType.BorderSingle; 
                                                    pf.BorderRight.Width = Converters.PxToTwipRounded(t.Right);
                                                    pf.BorderTop.Type = BorderType.BorderSingle;
                                                    pf.BorderTop.Width = Converters.PxToTwipRounded(t.Top);
                                                    pf.BorderBottom.Type = BorderType.BorderSingle; 
                                                    pf.BorderBottom.Width = Converters.PxToTwipRounded(t.Bottom);
                                                } 
                                                else 
                                                {
                                                    RowFormat rf = formatState.RowFormat; 
                                                    CellFormat cf = rf.RowCellFormat;
                                                    cf.BorderLeft.Type = BorderType.BorderSingle;
                                                    cf.BorderLeft.Width = Converters.PxToTwipRounded(t.Left);
                                                    cf.BorderRight.Type = BorderType.BorderSingle; 
                                                    cf.BorderRight.Width = Converters.PxToTwipRounded(t.Right);
                                                    cf.BorderTop.Type = BorderType.BorderSingle; 
                                                    cf.BorderTop.Width = Converters.PxToTwipRounded(t.Top); 
                                                    cf.BorderBottom.Type = BorderType.BorderSingle;
                                                    cf.BorderBottom.Width = Converters.PxToTwipRounded(t.Bottom); 
                                                }
                                            }
                                        }
                                        break; 

                                    case XamlAttribute.XABorderBrush: 
                                        if (XamlParserHelper.ConvertToColor(converterState, valueString, ref valueData)) 
                                        {
                                            if (xamlTag == XamlTag.XTParagraph) 
                                            {
                                                formatState.ParaBorder.CF = valueData;
                                            }
                                            else 
                                            {
                                                RowFormat rf = formatState.RowFormat; 
                                                CellFormat cf = rf.RowCellFormat; 
                                                cf.BorderLeft.CF = valueData;
                                                cf.BorderRight.CF = valueData; 
                                                cf.BorderTop.CF = valueData;
                                                cf.BorderBottom.CF = valueData;
                                            }
                                        } 
                                        break;
 
                                    case XamlAttribute.XATextIndent: 
                                        double ti = 0;
 
                                        if (XamlParserHelper.ConvertToTextIndent(converterState, valueString, ref ti))
                                        {
                                            formatState.FI = Converters.PxToTwipRounded(ti);
                                        } 
                                        break;
 
                                    case XamlAttribute.XALineHeight: 
                                        double sl = 0;
 
                                        if (XamlParserHelper.ConvertToLineHeight(converterState, valueString, ref sl))
                                        {
                                            formatState.SL = Converters.PxToTwipRounded(sl);
                                            formatState.SLMult = false; 
                                        }
                                        break; 
 
                                    case XamlAttribute.XALang:
                                        { 
                                            try
                                            {
                                                CultureInfo ci = new CultureInfo(valueString);
 
                                                if (ci.LCID > 0)
                                                { 
                                                    // Extract LANGID from LCID 
                                                    formatState.Lang = (long)(ushort)ci.LCID;
                                                } 
                                            }
                                            catch (System.ArgumentException)
                                            {
                                                // Just omit if this is not a legal language value 
                                            }
                                        } 
                                        break; 

                                    case XamlAttribute.XATextAlignment: 
                                        HAlign halign = HAlign.AlignDefault;

                                        if (XamlParserHelper.ConvertToHAlign(converterState, valueString, ref halign))
                                        { 
                                            formatState.HAlign = halign;
                                        } 
                                        break; 
                                }
                            } 
                        }
                    }
                }
 
                return xamlToRtfError;
            }