Logo Search packages:      
Sourcecode: bibledit version File versions  Download package

printreferences.cpp

/*
** Copyright (C) 2003-2006 Teus Benschop.
**  
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**  
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**  
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**  
*/


#include "libraries.h"
#include <glib.h>
#include "printreferences.h"
#include "utilities.h"
#include "bible.h"
#include "usfm.h"
#include "usfmtools.h"
#include <config.h>
#include "pdfviewer.h"
#include "xmlutils.h"
#include "paper.h"
#include "formatter.h"
#include "xmlfo-utils.h"
#include "constants.h"
#include "gwrappers.h"
#include "gtkwrappers.h"
#include "directories.h"
#include "fonts.h"
#include "notecaller.h"
#include "xslfofootnote.h"
#include "xslfoendnote.h"
#include "xslfoxref.h"
#include "projectutils.h"
#include "generalconfig.h"
#include "projectconfig.h"
#include "session.h"


void view_references_pdf (const vector<ustring>& references, ProgressWindow& progresswindow)
/*
Formats the references in "references", and highlights all words in
"session->highlights*" and shows them in a pdf viewer.
*/
{
  // Log.
  gw_message ("Starting to print the references");
  
  // Progress system.
  progresswindow.set_text ("Starting");
  progresswindow.set_iterate (0, 0.5, references.size());
  if (progresswindow.cancel) {
    return;
  }

  // Configuration and session
  GeneralConfiguration genconfig (0);
  Session session (0);
  
  // Prepare for the inline text markers.
  ProjectConfiguration projectconfig ("");
  Usfm usfm (projectconfig.stylesheet());
  UsfmInlineMarkers usfm_inline_markers (usfm);

  // Prepare for leaving out footnotes, endnotes and crossreferences.
  XslFoFootnote xslfofootnote (usfm, false);
  XslFoEndnote xslfoendnote (usfm, false);
  XslFoXref xslfoxref (usfm, false);
  
  // Storage for final xsl-fo file.
  vector<ustring> xslfo_lines;

  // Start building the xml-fo file.
  // The various elements of this file are created using objects.
  // When the object goes out of scope, it writes the closing elements.
  {
    XmlFoRoot xmlforoot (&xslfo_lines);
    {
      XmlFoLayoutMasterSet layoutmasterset (&xslfo_lines, false);
    }      
    {
      XmlFoPageSequence pagesequence (&xslfo_lines, false);
      {
        XmlFoStaticContent staticcontent (&xslfo_lines);
      }
      {
        XmlFoFlow flow (&xslfo_lines);
        {
  
          // Some variables to avoid excessive session database access.
          vector<bool> highlight_casesensitives = session.highlight_casesensitives();
          vector<ustring> highlight_words = session.highlight_words();
          // Produce chunks for the xsl-fo file for all references.
          for (unsigned int i = 0; i < references.size(); i++) {
            // Update progress bar.
            progresswindow.iterate();
            progresswindow.set_text ("Collecting references");
            if (progresswindow.cancel) {
              return;
            }
            // Get the reference decoded.
            ustring bookref, chapterref, verse;
            decode_reference (references[i], bookref, chapterref, verse);
            if (true) {
              // Get the verse text.
              ParseLine parseline (project_retrieve_verse (genconfig.project(), bookref, convert_to_int (chapterref), verse));
              ustring line;
              for (unsigned int i2 = 0; i2 < parseline.lines.size (); i2++) {
                ustring s = parseline.lines[i2];
                usfm_extract_marker (s);
                line.append (" " + s);
              }
              // Take out footnotes, endnotes, crossreferences.
              xslfofootnote.transform (NULL, line);
              xslfoendnote.transform (NULL, line);
              xslfoxref.transform (NULL, line);              
              // Positions in the line, and lengths to highlight.
              vector <size_t> highlight_positions;
              vector <size_t> highlight_lengths;
              // Go through all the words to highlight.
              for (unsigned int i2 = 0; i2 < highlight_casesensitives.size(); i2++) {
                // Word to highlight
                ustring highlightword;
                if (highlight_casesensitives[i2]) 
                  highlightword = highlight_words[i2];
                else 
                  highlightword = highlight_words[i2].casefold ();
                // Variabele s holds a shadow string.
                ustring s;
                if (highlight_casesensitives[i2]) 
                  s = line;
                else 
                  s = line.casefold ();
                // Find positions for highlighting.
                size_t offposition = s.find (highlightword);
                while (offposition != string::npos) {
                  // Store position and length.
                  highlight_positions.push_back (offposition);
                  highlight_lengths.push_back (highlightword.length());
                  // Look for possible next word to highlight.
                  offposition = offposition + highlightword.length () + 1;
                  // There is something like a bug in s.find. If the offposition
                  // is greater than the length of s, then s.find will return
                  // a value below offposition, instead of string::npos as is
                  // expected. Workaround.
                  if (offposition > s.length())
                    break;
                  offposition = s.find (highlightword, offposition);
                }
              }
              // Sort the positions from small to bigger.
              xml_sort_positions (highlight_positions, highlight_lengths);
              // Combine overlapping positions.
              xml_combine_overlaps (highlight_positions, highlight_lengths);
              // Change <, > and & to their corresponding entities.
              xml_handle_entities (line, highlight_positions);
              // Insert the code for highlighting.
              xml_fo_insert_emphasis (line, highlight_positions, highlight_lengths);
              // In case this prints changes, deal with strike-through and bold.
              replace_text (line, STRIKE_THROUGH_BEGIN, "<fo:inline text-decoration=\"line-through\">");
              replace_text (line, STRIKE_THROUGH_END, "</fo:inline>");
              replace_text (line, BOLD_BEGIN, "<fo:inline font-weight=\"bold\">");
              replace_text (line, BOLD_END, "</fo:inline>");
              // Deal with inline markers, so that they do not appear in the output
              // as markers, but format the text instead.
              // At times there is an overlap of fo:inline markers, caused in a 
              // situation where there are changes at a position where an inline
              // format marker is active too. This overlap is not allowed in the
              // XSL standard, and therefore must be avoided. It is avoided so:
              // 1. See if there were any replacements due to changes.
              // 2. If so, do not handle the inline text, but just remove their
              //    corresponding usfm markers.
              usfm_handle_inline_text (line, &usfm_inline_markers, NULL);
              // Add the block, and this line, to the xsl-fo file.
              // Measures are taken, within the capabilities of fop 0.20.5, that
              // any reference stays wholly on one page. FOP 0.20.5 does that only
              // within a table row.
              {
                xslfo_lines.push_back ("      <fo:table table-layout=\"fixed\" width=\"100%\">");
                xslfo_lines.push_back ("        <fo:table-column column-width=\"proportional-column-width(1)\"/>");
                xslfo_lines.push_back ("        <fo:table-body>");
                // Next line has keep-together.within-page="always", rather than
                // keep-together="always", as the latter one causes things to be 
                // kept together, in in a line, which causes the line to overflow
                // the right margin.
                xslfo_lines.push_back ("          <fo:table-row keep-together.within-page=\"always\">");
                xslfo_lines.push_back ("            <fo:table-cell>");
                // XSLFormatter was better than FOP in that it does honour space conditionality,
                // which is initially set at "discard" for the beginning of a 
                // references area, as here. So to get the distance between the 
                // lines right, this is inserted: space-before.conditionality="retain".
                xslfo_lines.push_back ("              <fo:block space-before=\"2mm\" space-before.conditionality=\"retain\">");
                xslfo_lines.push_back (references[i] + line);
                xslfo_lines.push_back ("              </fo:block>");
                xslfo_lines.push_back ("            </fo:table-cell>");
                xslfo_lines.push_back ("          </fo:table-row>");
                xslfo_lines.push_back ("        </fo:table-body>");
                xslfo_lines.push_back ("      </fo:table>");
              }
            }
          }
        }
      }
    }
  }
  
  // Make a temporary directory where to put the working files and the resulting
  // .pdf file.information. This directory is not removed, because the pdf viewer 
  // needs the .pdf file to be there during viewing or printing.
  string working_directory = gw_build_filename(directories_get_temp(), "references");
  create_directory (working_directory);
  // Produce filename of .fo file.
  string fofilename = gw_build_filename(working_directory, "document.fo");
  // Write the document.
  write_lines (fofilename, xslfo_lines);
  // Tell user to be patient while we pdfxmltex runs.  
  progresswindow.set_text ("Typesetting pages ...");
  if (progresswindow.cancel) {
    return;
  }
  // Convert the xsl-fo document to .pdf.
  NoteCaller dummy (nntNumerical, "", false);
  string pdffilename = gw_build_filename(working_directory, "document.pdf");
  int conversion_result = formatter_convert_to_pdf (fofilename, pdffilename, progresswindow, &dummy, &dummy);
  // Progressbar: ready.
  progresswindow.set_fraction (1);
  progresswindow.set_text ("Ready");
  if (progresswindow.cancel) {
    return;
  }
  // View the .pdf document.
  pdfviewer (pdffilename);
  // Give message if there were errors.
  if (conversion_result != 0) {
    string message = "While formatting the text problems were encountered.\n"
                     "See menu Help - System log for more details.\n"
                     "See the helpfile for a possible solution.";
    gtkw_dialog_error (NULL, message);
  };
  // Log: ready.
  gw_message ("Ready printing the references");
}

Generated by  Doxygen 1.6.0   Back to index