/// ------------------------------------------------------------------------------------
        /// <summary>
        /// Output the RTF header, font table, color table, etc.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        private void OutputRTFHeadingStuff()
        {
            m_rtfBldr.AppendLine(khdr);
            m_rtfBldr.AppendLine(RtfHelper.FontTable(m_fontNumbers, ref m_uiFontNumber));

            // Add color support
            if (m_cache.IsForSearchResults)
            {
                Dictionary <int, int> colorReferences;
                m_rtfBldr.AppendLine(RtfHelper.ColorTable(
                                         Properties.Settings.Default.QuerySearchItemBackColor, out colorReferences));
            }

            m_rtfBldr.AppendLine(@"\pard\plain ");
            m_rtfBldr.AppendFormat(ktxcell, 2160);
            m_rtfBldr.AppendLine();
        }
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Write the Rtf string to an output file or the clipboard.
        /// </summary>
        /// <returns>true if the message was handled</returns>
        /// ------------------------------------------------------------------------------------
        private void WriteToFileOrClipboard()
        {
            var rtf = RtfHelper.TranslateUnicodeChars(m_rtfBldr.ToString());

            if (m_exportTarget == ExportTarget.Clipboard)
            {
                Clipboard.SetText(rtf, TextDataFormat.Rtf);
                return;
            }

            string filter = App.kstidFiletypeRTF + "|" + App.kstidFileTypeAllFiles;

            int filterIndex = 0;

            var caption = LocalizationManager.GetString("Views.WordLists.RtfExport.SaveFileDialogText", "Save RTF File",
                                                        "Save file dialog caption for specifying the rtf file exported to under RTF export");

            var filename = App.SaveFileDialog("rtf", filter, ref filterIndex, caption, string.Empty);

            if (filename != string.Empty)
            {
                try
                {
                    using (var sw = new StreamWriter(filename))
                        sw.Write(rtf);
                }
                catch (Exception ex)
                {
                    Utils.MsgBox(ex.Message);
                    return;
                }
                // Open the file with the specified RTF editor
                if (m_exportTarget == ExportTarget.FileAndOpen)
                {
                    OpenInEditor(filename);
                }
            }
        }
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Builds the RTF header, the bulk of which, is the font table.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        private void UpdateFonts(bool updateRecord)
        {
            m_uiFontSize = (int)FontHelper.UIFont.SizeInPoints * 2;

            if (App.Project == null)
            {
                return;
            }

            m_fontSizes = new Dictionary <string, int>();
            foreach (var field in App.Project.Fields.Where(f => f.Font != null))
            {
                m_fontSizes[field.Name] = (int)(field.Font.SizeInPoints * 2);
                m_fonts[field.Name]     = field.Font;
            }

            m_rtf = khdr + RtfHelper.FontTable(m_fontNumbers, ref m_uiFontNumber);

            if (updateRecord)
            {
                UpdateRecord(m_recEntry, true);
            }
        }
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Performs all the final steps (i.e. formatting all the information into a big RTF
        /// blob) for setting the text box's RTF.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        private void FormatRTF(string tabStopsString,
                               string firstLineTabStopsString, string subordinateTabStopsString)
        {
            StringBuilder         lines = new StringBuilder(m_rtf);
            Dictionary <int, int> colorReferences;
            Color clrFieldLabel = Properties.Settings.Default.RecordViewFieldLabelColor;

            lines.AppendLine();
            lines.AppendLine(RtfHelper.ColorTable(clrFieldLabel, out colorReferences));

            GetLargestFontInfo();
            m_fieldLabelColorRefNumber = colorReferences[clrFieldLabel.ToArgb()];

            for (int i = 0; i < m_rowsInCol1; i++)
            {
                lines.AppendLine(@"\pard\plain");

                if (m_useExactLineSpacing)
                {
                    // The default line spacing is usually larger than necessary, especially if
                    // one of the fonts is Doulos SIL. Therefore, scrunch them together a little.
                    lines.AppendFormat(@"\sl-{0}\slmult0", m_lineSpacing);
                }

                if (m_rtfFields[i].isInterlinearField)
                {
                    FormatInterlinearForRTF(m_rtfFields[i], lines,
                                            firstLineTabStopsString, subordinateTabStopsString);
                }
                else
                {
                    lines.AppendLine(tabStopsString);

                    int  dataFontNumber = m_fontNumbers[m_rtfFields[i].field];
                    int  dataFontSize   = m_fontSizes[m_rtfFields[i].field];
                    Font dataFont       = m_fonts[m_rtfFields[i].field];

                    lines.AppendFormat(kFmtOneLineOneCol, new object[] { m_fieldLabelColorRefNumber,
                                                                         m_uiFontSize, m_uiFontNumber, m_rtfFields[i].label });

                    lines.Append(ApplyFontStyle(dataFont, true));
                    lines.AppendFormat(kline, dataFontNumber, dataFontSize, m_rtfFields[i].fieldValue);
                    lines.Append(ApplyFontStyle(dataFont, false));

                    if (m_rowsInCol1 + i < m_rtfFields.Count)
                    {
                        lines.Append("\\tab ");
                        dataFontNumber = m_fontNumbers[m_rtfFields[m_rowsInCol1 + i].field];
                        dataFontSize   = m_fontSizes[m_rtfFields[m_rowsInCol1 + i].field];
                        dataFont       = m_fonts[m_rtfFields[m_rowsInCol1 + i].field];

                        lines.AppendFormat(kFmtOneLineOneCol, new object[] { m_fieldLabelColorRefNumber,
                                                                             m_uiFontSize, m_uiFontNumber, m_rtfFields[m_rowsInCol1 + i].label });

                        lines.Append(ApplyFontStyle(dataFont, true));
                        lines.AppendFormat(kline, dataFontNumber, dataFontSize,
                                           m_rtfFields[m_rowsInCol1 + i].fieldValue);
                        lines.Append(ApplyFontStyle(dataFont, false));
                    }

                    if (m_useExactLineSpacing)
                    {
                        // Add a zero width space at the end of the line using the largest font so all
                        // the lines will have uniform spacing between. I tried using a regular space
                        // but the RTF control ignored it. I also tried forcing the line spacing using
                        // the \slN RTF code, but that didn't seem to work either. It looked great in
                        // Word, but not the RichTextBox. Grrr!
                        lines.AppendFormat(@"\fs{0}\f{1} {2}", m_maxFontSize, m_maxFontNumber,
                                           kZeroWidthSpace);
                    }

                    lines.AppendLine(@"\par");
                }
            }

            lines.Append("}");
            Rtf = RtfHelper.TranslateUnicodeChars(lines.ToString());
        }
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// RtfCreator constructor.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        public RtfCreator(PaProject project, ExportTarget target, ExportFormat format,
                          DataGridView grid, WordListCache cache, string rtfEditor)
        {
            m_project      = project;
            m_exportTarget = target;
            m_exportFormat = format;
            m_grid         = grid;

            if (m_grid != null)
            {
                m_graphics = m_grid.CreateGraphics();

                // Store the dots per inch value from the grid's graphic object
                m_pixelsPerInch = m_graphics.DpiX;
            }

            m_cache                = cache;
            m_rtfEditor            = rtfEditor;
            m_createSearchItemTabs = CreateSearchItemTabs.FirstTab;
            m_rtfBldr              = new StringBuilder();

            // Default value is 1/8" gap between columns.
            m_colRightPadding = Properties.Settings.Default.RTFExportGapBetweenColumns;

            // Add support for highlighting the search item
            if (m_cache.IsForSearchResults)
            {
                Dictionary <int, int> colorReferences;
                RtfHelper.ColorTable(Properties.Settings.Default.QuerySearchItemBackColor, out colorReferences);
                m_searchItemColorRefNumber = colorReferences[Properties.Settings.Default.QuerySearchItemBackColor.ToArgb()];
            }

            // Sort the visible columns by their display order.
            m_sortedColumns = new SortedList <int, DataGridViewColumn>();
            foreach (DataGridViewColumn col in m_grid.Columns)
            {
                if (col.Visible && !(col is SilHierarchicalGridColumn))
                {
                    m_sortedColumns[col.DisplayIndex] = col;
                }
            }

            GetPaperAndMarginValues();
            CalculateColumnWidths();
            OutputRTFHeadingStuff();

            // This is only for running tests
            if (m_maxFieldWidths.Count > 0)
            {
                MakeFinalWidthAdjustments();
                m_rtfBldr.AppendFormat(@"\paperw{0}\paperh{1}", m_paperWidth, m_paperHeight);
                m_rtfBldr.AppendFormat(@"\margl{0}\margr{1}", m_leftMargin, m_rightMargin);
                m_rtfBldr.AppendFormat(@"\margt{0}\margb{1}", m_topMargin, m_bottomMargin);
                m_rtfBldr.AppendLine();

                OutputReportHeadingInformation();
                OutputColumnInformation();
                OutputDataRows();
                WriteToFileOrClipboard();
            }

            if (m_graphics != null)
            {
                m_graphics.Dispose();
            }
        }