internal void RepopulateFromCSLProcessor(CSLProcessorOutputConsumer ip, CSLProcessor.BrowserThreadPassThru passthru)
        {
            if (null != ip.error_message)
            {
                RepopulateFromCSLProcessor_FAIL(ip, passthru);
            }
            else
            {
                RepopulateFromCSLProcessor_SUCCESS(ip, passthru);
            }

            StatusManager.Instance.UpdateStatus("InCite", "Updated InCite fields in Word");
        }
        internal void RepopulateFromCSLProcessor_FAIL(CSLProcessorOutputConsumer ip, CSLProcessor.BrowserThreadPassThru passthru)
        {
            // Dump the logs
            StringBuilder sb = new StringBuilder();

            foreach (string msg in ip.logs)
            {
                sb.AppendLine(msg);
            }
            sb.AppendLine();
            sb.AppendLine(ip.error_message);

            // Display the error
            string dialog_msg =
                "There was a problem while processing one of your references.  Please check this output to see if perhaps there is something strange in one of your BibTeX fields.  The error is sometimes preceded by ??????\n\n"
                + ip.error_message;

            MessageBoxes.Error("{0}", dialog_msg);
        }
        internal void RepopulateFromCSLProcessor_SUCCESS(CSLProcessorOutputConsumer ip, CSLProcessor.BrowserThreadPassThru passthru)
        {
            int MAX_DODGY_PASTE_RETRY_COUNT     = 5;
            int DODGY_PASTE_RETRY_SLEEP_TIME_MS = 200;
            int dodgy_paste_retry_count         = 0;

            try
            {
                // Suppress screen updates (for performance reasons)
                repopulating_clusters           = true;
                word_application.ScreenUpdating = false;

                Document document = word_application.Selection.Document;

                // Get all the fields out there
                Logging.Info("+Enumerating all fields");
                List <Field> fields = GetDocumentFields(document);
                Logging.Info("-Enumerating all fields");

                StatusManager.Instance.ClearCancelled("InCite");
                for (int f = 0; f < fields.Count; ++f)
                {
                    if (StatusManager.Instance.IsCancelled("InCite"))
                    {
                        Logging.Info("Updating of citations in Word has been cancelled by the user.");
                        break;
                    }

                    Field field = fields[f];

                    StatusManager.Instance.UpdateStatus("InCite", "Updating InCite fields in Word", f, fields.Count, true);
                    word_application.StatusBar = String.Format("Updating InCite field {0} of {1}...", f, fields.Count);

                    try
                    {
                        // Do we have a citation that we can fill?
                        CitationCluster citation_cluster = GenerateCitationClusterFromField(field);
                        if (null != citation_cluster)
                        {
                            string text_for_cluster = ip.GetTextForCluster(citation_cluster.cluster_id);
                            string rtf_hash         = GenerateRTFHash(passthru.is_note_format, text_for_cluster);

                            // Update this citation cluster only if it needs updating (if it has changed from what is currently stored in it)
                            if (!String.IsNullOrEmpty(text_for_cluster))
                            {
                                bool needs_update = false;

                                if (!needs_update)
                                {
                                    if (rtf_hash != citation_cluster.rtf_hash)
                                    {
                                        needs_update = true;
                                    }
                                }

                                if (!needs_update)
                                {
                                    string current_field_contents = field.Result.Text;
                                    if (current_field_contents.Contains("QIQQA"))
                                    {
                                        needs_update = true;
                                    }
                                }

                                if (needs_update)
                                {
                                    // Update the field with the new hash
                                    citation_cluster.rtf_hash = rtf_hash;
                                    PopulateFieldWithRawCitationCluster(field, citation_cluster);

                                    // Remember the font
                                    string font_name = field.Result.Font.Name;
                                    float  font_size = field.Result.Font.Size;

                                    string rtf = RTF_START + text_for_cluster + RTF_END;
                                    ClipboardTools.SetText(rtf, TextDataFormat.Rtf);

                                    if (passthru.is_note_format)
                                    {
                                        field.Result.Text = "";
                                        Footnote footnote = field.Result.Footnotes.Add(field.Result);
                                        footnote.Range.Text = " ";
                                        Range range = footnote.Range;
                                        range.Collapse(WdCollapseDirection.wdCollapseStart);
                                        range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF);
                                        footnote.Range.Font.Name = font_name;
                                        footnote.Range.Font.Size = font_size;
                                    }
                                    else
                                    {
                                        field.Result.Text = " ";
                                        Range range = field.Result;
                                        range.Collapse(WdCollapseDirection.wdCollapseStart);
                                        range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF);
                                        field.Result.Text      = field.Result.Text.Trim();
                                        field.Result.Font.Name = font_name;
                                        field.Result.Font.Size = font_size;
                                    }
                                }
                            }
                            else
                            {
                                citation_cluster.rtf_hash = rtf_hash;
                                PopulateFieldWithRawCitationCluster(field, citation_cluster);
                                field.Result.Text = String.Format("ERROR: Unable to find key {0} in the CSL output.", citation_cluster.cluster_id);
                            }

                            // If we get here, it must have worked!
                            dodgy_paste_retry_count = 0;

                            continue;
                        }

                        // Do we have a bibliography that we can fill?
                        if (IsFieldBibliography(field))
                        {
                            // Remember the font
                            string font_name = field.Result.Font.Name;
                            float  font_size = field.Result.Font.Size;

                            string formatted_bibliography_section = ip.GetFormattedBibliographySection();
                            if (String.IsNullOrEmpty(formatted_bibliography_section))
                            {
                                formatted_bibliography_section = "Either this CSL citation style does not produce a bibliography section or you have not yet added any citations to this document, so this bibliography is empty.";
                            }

                            string formatted_bibliography_section_wrapped = CSLProcessorOutputConsumer.RTF_START + formatted_bibliography_section + CSLProcessorOutputConsumer.RTF_END;

                            ClipboardTools.SetText(formatted_bibliography_section_wrapped, TextDataFormat.Rtf);

                            field.Result.Text = " ";
                            Range range = field.Result;
                            range.Collapse(WdCollapseDirection.wdCollapseStart);
                            range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF);
                            field.Result.Font.Name = font_name;
                            field.Result.Font.Size = font_size;

                            // If we get here, it must have worked!
                            dodgy_paste_retry_count = 0;

                            continue;
                        }

                        // Do we have a CSL stats region?
                        if (IsFieldCSLStats(field))
                        {
                            StringBuilder sb = new StringBuilder();
                            sb.Append(RTF_START);
                            {
                                sb.AppendFormat("maxoffset={0}\\line\n", ip.max_offset);
                                sb.AppendFormat("entryspacing={0}\\line\n", ip.entry_spacing);
                                sb.AppendFormat("linespacing={0}\\line\n", ip.line_spacing);
                                sb.AppendFormat("hangingindent={0}\\line\n", ip.hanging_indent);
                                sb.AppendFormat("second_field_align={0}\\line\n", ip.second_field_align);
                            }
                            sb.Append(RTF_END);

                            Clipboard.SetText(sb.ToString(), TextDataFormat.Rtf);

                            field.Result.Text = " ";
                            Range range = field.Result;
                            range.Collapse(WdCollapseDirection.wdCollapseStart);
                            range.PasteSpecial(DataType: WdPasteDataType.wdPasteRTF);

                            // If we get here, it must have worked!
                            dodgy_paste_retry_count = 0;

                            continue;
                        }
                    }
                    catch (Exception ex)
                    {
                        ++dodgy_paste_retry_count;
                        if (dodgy_paste_retry_count < MAX_DODGY_PASTE_RETRY_COUNT)
                        {
                            Logging.Warn(ex, "Will try again (try {0}) because there was a problem updating a citation field: {1}", dodgy_paste_retry_count, field.Result.Text);

                            // Back up one field so we can try again
                            Thread.Sleep(DODGY_PASTE_RETRY_SLEEP_TIME_MS);
                            --f;
                            continue;
                        }
                        else
                        {
                            Logging.Error(ex, "Giving up because there was a problem updating a citation field: {0}", field.Result.Text);
                            dodgy_paste_retry_count = 0;
                            continue;
                        }
                    }
                }
            }
            finally
            {
                // Restore the screen updates
                repopulating_clusters           = false;
                word_application.ScreenUpdating = true;
                word_application.StatusBar      = "Updated InCite fields.";
            }
        }
        internal void RepopulateFromCSLProcessor(object ip_object)
        {
            CSLProcessorOutputConsumer ip = (CSLProcessorOutputConsumer)ip_object;

            RepopulateFromCSLProcessor(ip, (CSLProcessor.BrowserThreadPassThru)ip.user_argument);
        }