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

xep.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 "utilities.h"
#include <libgen.h>
#include <glib.h>
#include <config.h>
#include "xep.h"
#include "java.h"
#include "gwrappers.h"
#include "gtkwrappers.h"
#include "directories.h"
#include "unixwrappers.h"
#include "fonts.h"
#include "uname.h"
#include "shell.h"
#include "generalconfig.h"
#include "session.h"


/*
As FOP sometimes fails to properly format a Scripture, the commercially 
available proprietary XEP was chosen instead.
*/


ustring standard_xep_command ()
// Return the command to run script xep, if found.
{
  GeneralConfiguration genconfig (0);
  ustring xep;
  xep = gw_build_filename (genconfig.xep_home(), "xep");
  if (uname_get () == untCygwin)
    xep.append (".bat");
  if (unix_which (xep))
    return xep;
  return "";
}


ustring modified_xep_command ()
// Return the command to run xep. This command is the script
// xep that comes with the program. The amount of memory assigned to it gets 
// changed in this command, to allow XEP to format a whole project.
{
  // Produce path.
  ustring modified_command (standard_xep_command ());
  
  // Get contents of the standard script.
  ReadText rt (standard_xep_command (), true, false);
  // Insert memory size.
  for (unsigned int i = 0; i < rt.lines.size(); i++) {
    // First we had assigned 512 Mbyte, but that was not enough.
    #define XEP_MEMORY1 "-Xmx512M "
    size_t position;
    position = rt.lines[i].find (XEP_MEMORY1);
    if (position != string::npos) {
      rt.lines[i].erase (position, strlen (XEP_MEMORY1));
    }
    // Now we assign 1024 Mbyte.
    #define XEP_MEMORY2 "-Xmx1024M "
    position = rt.lines[i].find (XEP_MEMORY2);
    if (position != string::npos) {
      rt.lines[i].erase (position, strlen (XEP_MEMORY2));
    }
    position = rt.lines[i].find ("-classpath");
    if (position != string::npos) {
      rt.lines[i].insert (position, XEP_MEMORY2);
    }
  }
  // Store modified contents in modified script.
  write_lines (modified_command, rt.lines);
  
  // Return it.
  return modified_command; 
}


bool xep_present (GtkWidget * window)
// Returns whether the script to run xep can be found.
// Gives message if not found.
{
  bool present;
  present = g_file_test (standard_xep_command ().c_str(), G_FILE_TEST_IS_REGULAR);
  if (!present) {
    ustring message;
    message = "XEP was not found.\n";
    message.append ("XEP is the formatter.\n");
    message.append ("It is required for printing.\n");
    message.append ("Install it first.\n");
    message.append ("For more information see menu Preferences->Formatter.");
    gtkw_dialog_info (window, message);
  }
  return present;
}


void xep_create_xep_xml ()
// Creates the file xep.xml and puts it in the directory where xep has been
// installed. It inserts the font data into the file.
{
  // Configuration / session
  GeneralConfiguration genconfig (0);
  Session session (0);
  // Printing font data.
  PrintingFonts pfonts (genconfig.project());
  // Read the template.
  ReadText rt (gw_build_filename (PACKAGE_DATA_DIR, "xep.xml"), true, false);
  vector<ustring> outputlines;
  // Gather fonts already defined in the template, so we do not redefine them
  // and get an error message.
  set<ustring> fonts_already_defined;
  for (unsigned int i = 0; i < rt.lines.size(); i++) {
    size_t position;
    position = rt.lines[i].find ("<font-family name=");
    if (position != string::npos) {
      ustring font = rt.lines[i];
      position = font.find ("\"");
      font.erase (0, ++position);
      position = font.find ("\"");
      font = font.substr (0, position);
      fonts_already_defined.insert (font);
    }
  }
  // Get list of fonts for printing, only the good ones.
  // Take from the main project first, ... 
  vector<ustring> printingfonts = pfonts.printing_families;
  // ... and then from any additional projects.
  {
    vector<ustring> additional_projects = session.additional_printing_projects();
    for (unsigned int i = 0; i < additional_projects.size(); i++) {
      PrintingFonts fonts (additional_projects[i]);
      for (unsigned int i2 = 0; i2 < fonts.printing_families.size(); i2++) {
        printingfonts.push_back (fonts.printing_families[i2]);
      }
    }
  }
  set<ustring> printingfonts_set (printingfonts.begin(), printingfonts.end());
  // Go through the template and insert font data.
  for (unsigned int i = 0; i < rt.lines.size(); i++) {
    outputlines.push_back (rt.lines[i]);
    if (rt.lines[i].find ("Bibledit") != string::npos) {
      // Insert all the fonts here, with their data.
      ustring previous_family;
      bool family_opened = false;
      // Go through each font.
      for (unsigned int i2 = 0; i2 < pfonts.xep_families.size(); i2++) {
        // Do not insert font already defined.
        if (fonts_already_defined.find (pfonts.xep_families[i2]) != fonts_already_defined.end())
          continue;
        // Do not insert font not set in editor.
        if (printingfonts_set.find (pfonts.xep_families[i2]) == printingfonts_set.end())
          continue;
        // If we find a new family, deal with that.
        if (pfonts.xep_families[i2] != previous_family) {
          // Close previous family, if there was any.
          if (family_opened)
            outputlines.push_back ("      </font-family>");
          outputlines.push_back ("      <font-family name=\"" + pfonts.xep_families[i2] + "\">");
          previous_family = pfonts.xep_families[i2];
          family_opened = true;
        }
        // See what type of font we have.
        bool pfa = g_str_has_suffix (pfonts.xep_paths[i2].c_str(), ".pfa");
        bool pfb = g_str_has_suffix (pfonts.xep_paths[i2].c_str(), ".pfb");
        bool ttf = g_str_has_suffix (pfonts.xep_paths[i2].c_str(), ".ttf");
        // Build the font line to insert.
        ustring fontline;
        fontline = "        <font";
        // Insert data for the variant.
        if ((pfonts.xep_variants[i2] == fvBold) || (pfonts.xep_variants[i2] == fvBoldItalic)) {
          fontline.append (" weight=\"bold\"");
        }
        if ((pfonts.xep_variants[i2] == fvItalic) || (pfonts.xep_variants[i2] == fvBoldItalic)) {
          fontline.append (" style=\"oblique\"");
        }
        fontline.append ("><font-data");
        if (pfa || pfb) {
           // Insert the metrics file.
           ustring afm_file = pfonts.xep_paths[i2];
           font_get_afm_file (afm_file);
           fontline.append (" afm=\"" + filename_modify_if_cygwin (afm_file) + "\"");
        }
        // Depending on the type, insert the data.
        if (pfa) {
          fontline.append (" pfa");
        }
        if (pfb) {
          fontline.append (" pfb");
        }
        if (ttf) {
          fontline.append (" ttf");
        }
        fontline.append ("=\"" + filename_modify_if_cygwin (pfonts.xep_paths[i2]) + "\"/></font>");
        outputlines.push_back (fontline); 
      }
      // Close last family.
      outputlines.push_back ("      </font-family>");
    }
  }
  // Leave or remove option to print footnotes over the whole page.
  if (genconfig.notes_print_full_page_width()) {
    for (unsigned int i = 0; i < outputlines.size(); i++)
      if (outputlines[i].find ("PAGEWIDE_FOOTNOTES") != string::npos)
        outputlines[i].clear();
  }
  // Save file as xep.xml
  ustring filename = gw_build_filename (genconfig.xep_home(), "xep.xml");
  write_lines (filename, outputlines);
}


ustring xep_convert_from_fo_to_xep (const ustring& xslfo, const ustring& xep, const ustring& logfile)
// Converts file "xslfo" to file "xep" in XEP intermediate format, and returns the result.
{
  // Create xep.xml file.
  xep_create_xep_xml ();
  // Do the transformation.
  ustring xepcommand (modified_xep_command ());
  ustring workingdirectory = gw_path_get_dirname (xslfo);
  ustring command;
  command = "cd" + shell_quote_space (workingdirectory) + ";";
  command.append (shell_quote_space (xepcommand));
  command.append (" -valid -fo " );
  command.append (gw_path_get_basename (xslfo));
  command.append (" -out ");
  command.append (gw_path_get_basename (xep));
  command.append (" -format xep >");
  command.append (shell_quote_space (logfile));
  command.append ("2>&1 &");
  if (system (command.c_str()) < 0)
    xepcommand.clear();
  return xepcommand;
}


void xep_convert_footnote_callers (const ustring& filename, NoteCaller * footnotecaller, NoteCaller * crossreferencecaller, ProgressWindow& progresswindow)
/*
Modifies the footnote numbering in the intermediate xep filename if the 
numbering restarts each page.
Whether it restarts each page is indicated by a special character in the text:
FOOTNOTE_CALLER_NUMBERING_PER_PAGE and similar ones, also for xrefs.
XEP first writes out all footnote callers as they are in the text, and at the
end of the page it writes down the footnotes themselves, starting with the
caller.
*/

{
  // Progress information.
  progresswindow.set_text ("Renumbering footnotes ...");
  progresswindow.set_fraction (0);
  // Read all text.
  ReadText rt (filename, true, false);
  // Mark all page boundaries.
  vector<unsigned int> page_beginning;
  vector<unsigned int> page_ending;
  {
    unsigned int begin = 0;
    for (unsigned int i = 0; i < rt.lines.size(); i++) {
      if (rt.lines[i].find ("<xep:page") != string::npos)
        begin = i;
      if (rt.lines[i].find ("</xep:page") != string::npos) {
        page_beginning.push_back (begin);
        page_ending.push_back (i);
      }
    }
  }
  // Progress.
  progresswindow.set_iterate (0, 1, page_beginning.size());
  // Go through each page.
  for (unsigned int i = 0; i < page_beginning.size(); i++) {
    // Progress.
    progresswindow.iterate ();
    // Store information about the position of the footnote and xref markers.
    vector<unsigned int> lines_with_footnote_markers_text;
    vector<size_t> footnote_markers_positions_text;
    vector<unsigned int> lines_with_footnote_markers_note;
    vector<size_t> footnote_markers_positions_note;
    vector<unsigned int> lines_with_crossreference_markers_text;
    vector<size_t> crossreference_markers_positions_text;
    vector<unsigned int> lines_with_crossreference_markers_note;
    vector<size_t> crossreference_markers_positions_note;
    for (unsigned int i2 = page_beginning[i]; i2 < page_ending[i]; i2++) {
      size_t position;
      position = rt.lines[i2].find (FOOTNOTE_CALLER_NUMBERING_PER_PAGE_TEXT);
      if (position != string::npos) {
        lines_with_footnote_markers_text.push_back (i2);
        footnote_markers_positions_text.push_back (position);
      }
      position = rt.lines[i2].find (FOOTNOTE_CALLER_NUMBERING_PER_PAGE_NOTE);
      if (position != string::npos) {
        lines_with_footnote_markers_note.push_back (i2);
        footnote_markers_positions_note.push_back (position);
      }
      position = rt.lines[i2].find (CROSSREFERENCE_CALLER_NUMBERING_PER_PAGE_TEXT);
      if (position != string::npos) {
        lines_with_crossreference_markers_text.push_back (i2);
        crossreference_markers_positions_text.push_back (position);
      }
      position = rt.lines[i2].find (CROSSREFERENCE_CALLER_NUMBERING_PER_PAGE_NOTE);
      if (position != string::npos) {
        lines_with_crossreference_markers_note.push_back (i2);
        crossreference_markers_positions_note.push_back (position);
      }
    }
    // Handle all positions with the footnote and xref markers.
    size_t footnote_caller_length = 1;
    if (footnotecaller->get_spacious ())
      footnote_caller_length = 2;
    size_t xref_caller_length = 1;
    if (crossreferencecaller->get_spacious ())
      xref_caller_length = 2;
    if (lines_with_footnote_markers_text.size() > 0) {
      footnotecaller->reset ();
      for (unsigned int i2 = 0; i2 < lines_with_footnote_markers_text.size(); i2++) {
        rt.lines[lines_with_footnote_markers_text[i2]].replace (footnote_markers_positions_text[i2], footnote_caller_length, footnotecaller->get_caller ());
      }      
    }
    if (lines_with_footnote_markers_note.size() > 0) {
      footnotecaller->reset ();
      for (unsigned int i2 = 0; i2 < lines_with_footnote_markers_note.size(); i2++) {
        rt.lines[lines_with_footnote_markers_note[i2]].replace (footnote_markers_positions_note[i2], footnote_caller_length, footnotecaller->get_caller ());
      }      
    }
    if (lines_with_crossreference_markers_text.size() > 0) {
      crossreferencecaller->reset ();
      for (unsigned int i2 = 0; i2 < lines_with_crossreference_markers_text.size(); i2++) {
        rt.lines[lines_with_crossreference_markers_text[i2]].replace (crossreference_markers_positions_text[i2], xref_caller_length, crossreferencecaller->get_caller ());
      }      
    }
    if (lines_with_crossreference_markers_note.size() > 0) {
      crossreferencecaller->reset ();
      for (unsigned int i2 = 0; i2 < lines_with_crossreference_markers_note.size(); i2++) {
        rt.lines[lines_with_crossreference_markers_note[i2]].replace (crossreference_markers_positions_note[i2], xref_caller_length, crossreferencecaller->get_caller ());
      }      
    }
  }
  // Write all text.
  write_lines (filename, rt.lines);
}


ustring xep_convert_from_xep_to_pdf (const ustring& xep, const ustring& pdf, const ustring& logfile)
// Converts file "xep" in XEP intermediate format to file "pdf", and returns the result.
{
  // Create xep.xml file.
  xep_create_xep_xml ();
  // Do the transformation.
  ustring xepcommand (modified_xep_command ());
  ustring workingdirectory = gw_path_get_dirname (xep);
  ustring command;
  command = "cd" + shell_quote_space (workingdirectory) + ";";
  command.append (shell_quote_space (xepcommand));
  command.append (" -valid -xep ");
  command.append (gw_path_get_basename (xep));
  command.append (" -out ");
  command.append (gw_path_get_basename (pdf));
  command.append (" >");
  command.append (shell_quote_space (logfile));
  command.append ("2>&1 &");
  if (system (command.c_str()) < 0)
    xepcommand.clear();
  return xepcommand;
}

Generated by  Doxygen 1.6.0   Back to index