void XeTeX::write_document_tex_file () { // Settings. extern Settings * settings; ProjectConfiguration *projectconfig = settings->projectconfig(settings->genconfig.project_get()); // Style sheet. extern Styles * styles; Stylesheet * sheet = styles->stylesheet (stylesheet_get_actual ()); document_tex.push_back (_("% Configuration file created by Bibledit-Gtk")); document_tex.push_back (_("% You can modify it to suit your needs")); document_tex.push_back (_("% After modification, run the following command in this directory:")); document_tex.push_back (_("% xetex document.tex")); document_tex.push_back (_("% After that look carefully at the output")); document_tex.push_back (_("% If it says that a re-run is required, repeat this command")); document_tex.push_back (""); document_tex.push_back (_("% Include the ptx2pdf macros")); document_tex.push_back ("\\input paratext2.tex"); document_tex.push_back (""); document_tex.push_back (_("% Paper size")); document_tex.push_back ("\\PaperWidth=" + convert_to_string (settings->genconfig.paper_width_get()) + "cm"); document_tex.push_back ("\\PaperHeight=" + convert_to_string (settings->genconfig.paper_height_get()) + "cm"); if (settings->session.print_crop_marks){ document_tex.push_back (""); document_tex.push_back (_("% Crop marks")); document_tex.push_back ("\\CropMarkstrue"); } document_tex.push_back (""); document_tex.push_back (_("% The basic unit for the margins; changing this will alter them all")); document_tex.push_back ("\\MarginUnit=1cm"); document_tex.push_back (""); document_tex.push_back (_("% Relative sizes of margins, based on the unit above")); document_tex.push_back ("\\def\\TopMarginFactor{" + convert_to_string (settings->genconfig.paper_top_margin_get()) + "}"); document_tex.push_back ("\\def\\BottomMarginFactor{" + convert_to_string (settings->genconfig.paper_bottom_margin_get()) + "}"); document_tex.push_back ("\\def\\SideMarginFactor{" + convert_to_string (settings->genconfig.paper_outside_margin_get()) + "}"); if (settings->genconfig.paper_inside_margin_get() != settings->genconfig.paper_outside_margin_get()) { document_tex.push_back (""); document_tex.push_back (_("% Extra margin for the gutter on the binding side")); document_tex.push_back ("\\BindingGuttertrue"); document_tex.push_back ("\\BindingGutter=" + convert_to_string (settings->genconfig.paper_inside_margin_get() - settings->genconfig.paper_outside_margin_get()) + "cm"); document_tex.push_back (""); document_tex.push_back (_("% Double sided printing")); document_tex.push_back ("\\DoubleSidedtrue"); } if (!projectconfig->editor_font_default_get()) { PangoFontDescription *font_desc = pango_font_description_from_string(projectconfig->editor_font_name_get().c_str()); if (font_desc){ // Assemble the string for the font mapping. ustring font_mapping = projectconfig->xetex_font_mapping_file_get(); if (!font_mapping.empty()) { if (g_str_has_suffix (font_mapping.c_str(), ".tec")) { font_mapping = gw_path_get_basename (font_mapping); // Remove the .tec suffix. font_mapping.erase (font_mapping.length() - 4, 4); // Insert the mapping command. font_mapping.insert (0, "mapping="); } else { gw_warning (_("Font mapping file ") + font_mapping + _(" should have the .tec suffix - ignoring this file")); font_mapping.clear(); } } // Assemble the string for the shaping engine. ustring shaping_engine; switch (XeTeXScriptingEngineType (projectconfig->xetex_shaping_engine_get())) { case xtxsetGeneric: break; case xtxsetArab: shaping_engine = "script=arab"; break; } // Assemble the addition to the font. ustring font_addition; if (!font_mapping.empty()) { if (font_addition.empty()) font_addition.append (":"); else font_addition.append (";"); font_addition.append (font_mapping); } if (!shaping_engine.empty()) { if (font_addition.empty()) font_addition.append (":"); else font_addition.append (";"); font_addition.append (shaping_engine); } ustring font_family = pango_font_description_get_family (font_desc); document_tex.push_back (""); document_tex.push_back (_("% Fonts to use for \"plain\", \"bold\", \"italic\", and \"bold italic\" from the stylesheet")); document_tex.push_back (_("% (they need not really be italic, etc.)")); document_tex.push_back (_("% Add e.g. \":mapping=farsidigits\" to get digits in Farsi, provided the farsidigits.tec TECkit mapping is available")); document_tex.push_back (_("% Add e.g. \":script=arab\" to use the arab shaping engine instead of the generic one")); document_tex.push_back ("\\def\\regular{\"" + font_family + font_addition + "\"}"); document_tex.push_back ("\\def\\bold{\"" + font_family + "/B" + font_addition + "\"}"); document_tex.push_back ("\\def\\italic{\"" + font_family + "/I" + font_addition + "\"}"); document_tex.push_back ("\\def\\bolditalic{\"" + font_family + "/BI" + font_addition + + "\"}"); pango_font_description_free(font_desc); } } if (projectconfig->right_to_left_get()) { document_tex.push_back (""); document_tex.push_back (_("% Right-to-left layout mode")); document_tex.push_back ("\\RTLtrue"); } document_tex.push_back (""); document_tex.push_back (_("% The unit for font sizes in the stylesheet; changing this will scale all text proportionately")); document_tex.push_back ("\\FontSizeUnit=1pt"); document_tex.push_back (""); document_tex.push_back (_("% Scaling factor used to adjust line spacing, relative to font size")); double line_spacing_factor = 1.0; double vertical_space_factor = 1.0; if (!projectconfig->editor_font_default_get()){ line_spacing_factor = projectconfig->text_line_height_get() / 100; vertical_space_factor = projectconfig->text_line_height_get() / 100; } document_tex.push_back ("\\def\\LineSpacingFactor{" + convert_to_string (line_spacing_factor) + "}"); document_tex.push_back ("\\def\\VerticalSpaceFactor{" + convert_to_string (vertical_space_factor) + "}"); document_tex.push_back (""); document_tex.push_back (_("% Information to include in the running header (at top of pages, except first)")); document_tex.push_back (_("% We set the items to print at left/center/right of odd and even pages separately")); document_tex.push_back (_("% Possible contents:")); document_tex.push_back (_("% \\rangeref = Scripture reference of the range of text on the page;")); document_tex.push_back (_("% \\firstref = reference of the first verse on the page)")); document_tex.push_back (_("% \\lastref = reference of the last verse on the page)")); document_tex.push_back (_("% \\pagenumber = the page number")); document_tex.push_back (_("% \\empty = print nothing in this position")); document_tex.push_back ("\\def\\RHoddleft{\\empty}"); document_tex.push_back ("\\def\\RHoddcenter{\\empty}"); document_tex.push_back ("\\def\\RHoddright{\\rangeref}"); document_tex.push_back (""); document_tex.push_back ("\\def\\RHevenleft{\\rangeref}"); document_tex.push_back ("\\def\\RHevencenter{\\empty}"); document_tex.push_back ("\\def\\RHevenright{\\empty}"); document_tex.push_back (""); document_tex.push_back ("\\def\\RHtitleleft{\\empty}"); document_tex.push_back ("\\def\\RHtitlecenter{\\empty}"); document_tex.push_back ("\\def\\RHtitleright{\\empty}"); document_tex.push_back (""); document_tex.push_back ("\\def\\RFoddcenter{\\pagenumber}"); document_tex.push_back ("\\def\\RFevencenter{\\pagenumber}"); document_tex.push_back ("\\def\\RFtitlecenter{\\pagenumber}"); document_tex.push_back (""); document_tex.push_back (_("% Whether to include verse number in running head, or only chapter")); document_tex.push_back ("\\VerseRefstrue"); document_tex.push_back (""); document_tex.push_back (_("% Whether to skip printing verse number 1 at start of chapter")); document_tex.push_back ("\\OmitVerseNumberOnetrue"); document_tex.push_back (""); document_tex.push_back (_("% Whether to use paragraph indent at drop-cap chapter numbers")); document_tex.push_back (_("% \\IndentAtChaptertrue")); // Go through the stylesheet looking for note markers. for (unsigned int i = 0; i < sheet->styles.size(); i++) { bool retrieve_note_data = false; StyleV2 * style = sheet->styles[i]; if (style->type == stFootEndNote) { if ((style->subtype == fentFootnote) || (style->subtype == fentEndnote)) { retrieve_note_data = true; } } if ((style->type == stFootEndNote) || (style->type == stCrossreference)) { if (style->subtype == ctCrossreference) { retrieve_note_data = true; } } if (retrieve_note_data) { ustring marker = style->marker; document_tex.push_back (""); document_tex.push_back (_("% Reformat \\") + marker + " notes as a single paragraph"); document_tex.push_back ("\\ParagraphedNotes{" + marker + "}"); document_tex.push_back (""); NoteNumberingType note_numbering = NoteNumberingType (style->userint1); switch (note_numbering) { case nntNumerical: document_tex.push_back (_("% Numerical callers for \\") + marker + _(" notes")); document_tex.push_back ("\\NumericCallers{" + marker + "}"); break; case nntAlphabetical: document_tex.push_back (_("% Alphabetical callers for \\") + marker + _(" notes")); document_tex.push_back ("\\AutoCallers{" + marker+ "}{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}"); break; case nntUserDefined: ustring autocallers; for (unsigned int i = 0; i < style->userstring1.size(); i++) { if (i) autocallers.append (","); autocallers.append (style->userstring1.substr (i, 1)); } if (!autocallers.empty()) { document_tex.push_back (_("% Special caller sequence for \\") + marker + " notes"); document_tex.push_back ("\\AutoCallers{" + marker+ "}{" + autocallers + "}"); } break; } document_tex.push_back (""); NoteNumberingRestartType note_restart = NoteNumberingRestartType (style->userint2); switch (note_restart) { case nnrtNever: break; case nnrtBook: break; case nnrtChapter: break; } document_tex.push_back (_("% Reset callers every page for \\") + marker + _(" notes")); document_tex.push_back ("\\PageResetCallers{" + marker + "}"); document_tex.push_back (""); document_tex.push_back (_("% Omit callers in the note for \\") + marker + _(" notes")); document_tex.push_back (_("% \\OmitCallerInNote{") + marker + "}"); } } document_tex.push_back (""); document_tex.push_back (_("% The number of columns")); document_tex.push_back ("\\TitleColumns=1"); document_tex.push_back ("\\IntroColumns=1"); document_tex.push_back ("\\BodyColumns=2"); document_tex.push_back (""); document_tex.push_back (_("% The gutter between double cols, relative to font size")); document_tex.push_back ("\\def\\ColumnGutterFactor{15}"); // Define the Paratext stylesheet to be used as a basis for formatting write_stylesheet (); // Write the data and add their filenames. for (unsigned int i = 0; i < book_ids.size(); i++) { ustring filename = convert_to_string (book_ids[i]) + " " + books_id_to_english(book_ids[i]) + ".usfm"; replace_text (filename, " ", "_"); write_lines (gw_build_filename (working_directory, filename), book_data[i]); document_tex.push_back ("\\ptxfile{" + filename + "}"); } // End of document input. document_tex.push_back ("\\end"); // Write document.text to file. write_lines (gw_build_filename (working_directory, "document.tex"), document_tex); }
void view_parallel_references_pdf(ProjectMemory & main_project, vector < ustring > *extra_projects, vector < Reference > references, bool keep_verses_together_within_page, vector < ustring > *remarks, bool highlight) /* Formats the references in "references", and highlights all words in "session->highlights*" and shows them in a pdf viewer. There is a pointer to a list of "remarks". Any remarks will be printed first. */ { // Log. gw_message(_("Printing parallel references")); // Progress system. ProgressWindow progresswindow(_("Printing Parallel References"), false); progresswindow.set_iterate(0, 1, references.size()); // Configuration extern Settings *settings; ProjectConfiguration *projectconfig = settings->projectconfig(main_project.name); ustring stylesheet = stylesheet_get_actual (); // Store the additional projects to print. vector < ustring > additional_projects; if (extra_projects) additional_projects = *extra_projects; settings->session.additional_printing_projects = additional_projects; // Prepare for mapping. Mapping mapping(projectconfig->versification_get(), 0); // The converter. Text2Pdf text2pdf(gw_build_filename(Directories->get_temp(), "document.pdf"), settings->genconfig.print_engine_use_intermediate_text_get()); // Page. text2pdf.page_size_set(settings->genconfig.paper_width_get(), settings->genconfig.paper_height_get()); text2pdf.page_margins_set(settings->genconfig.paper_inside_margin_get(), settings->genconfig.paper_outside_margin_get(), settings->genconfig.paper_top_margin_get(), settings->genconfig.paper_bottom_margin_get()); text2pdf.page_one_column_only(); // Headers. if (settings->genconfig.printdate_get()) { text2pdf.print_date_in_header(); } // Font, etc., of main project. ustring main_font = projectconfig->editor_font_name_get(); unsigned int main_line_spacing = projectconfig->text_line_height_get(); if (projectconfig->editor_font_default_get()) { main_font.clear(); main_line_spacing = 100; } text2pdf.set_font(main_font); text2pdf.set_line_spacing(main_line_spacing); bool main_right_to_left = projectconfig->right_to_left_get(); text2pdf.set_right_to_left(main_right_to_left); // Start off with inserting any remarks. if (remarks) { for (unsigned int r = 0; r < remarks->size(); r++) { text2pdf.open_paragraph(); text2pdf.paragraph_set_column_count(1); text2pdf.add_text(remarks->at(r)); text2pdf.close_paragraph(); } } // Some variables to avoid excessive session access during highlighting. vector < bool > highlight_casesensitives; vector < ustring > highlight_words; if (highlight) { for (unsigned int hl = 0; hl < settings->session.highlights.size(); hl++) { highlight_casesensitives.push_back(settings->session.highlights[hl].casesensitive); highlight_words.push_back(settings->session.highlights[hl].word); } } // All the projects to be put in this parallel Bible, together with // their related information, like mapping, fonts. vector < ustring > project_names; vector < ProjectMemory > project_memories; vector < Mapping > mapping_s; vector < ustring > fonts; vector < unsigned int >line_spacings; vector < bool > right_to_lefts; if (extra_projects) { vector < ustring > project_s_raw = *extra_projects; for (unsigned int i = 0; i < project_s_raw.size(); i++) { ProjectMemory projectmemory(project_s_raw[i], true); project_memories.push_back(projectmemory); ProjectConfiguration *projectconfig = settings->projectconfig(project_s_raw[i]); project_names.push_back(project_s_raw[i]); Mapping mapping(projectconfig->versification_get(), 0); mapping_s.push_back(mapping); ustring font = projectconfig->editor_font_name_get(); unsigned int line_spacing = projectconfig->text_line_height_get(); if (projectconfig->editor_font_default_get()) { font.clear(); line_spacing = 100; } fonts.push_back(font); line_spacings.push_back(line_spacing); right_to_lefts.push_back(projectconfig->right_to_left_get()); } } // Produce chunks for all references. for (unsigned int rf = 0; rf < references.size(); rf++) { // Update progress bar. progresswindow.iterate(); // Whether to keep things on one page. if (keep_verses_together_within_page) { text2pdf.open_keep_together(); } // Set main font, etc. text2pdf.set_font(main_font); text2pdf.set_line_spacing(main_line_spacing); text2pdf.set_right_to_left(main_right_to_left); // Add the reference to the text. text2pdf.add_text(references[rf].human_readable("")); // Map this verse to the original, that is, to Hebrew or Greek. vector <int> hebrew_greek_chapters; vector <int> hebrew_greek_verses; mapping.book_change(references[rf].book); mapping.me_to_original(references[rf].chapter, references[rf].verse, hebrew_greek_chapters, hebrew_greek_verses); // Get verse text for each version. for (unsigned int vsn = 0; vsn <= project_names.size(); vsn++) { // Add the font, etc., for each project. ustring font(main_font); unsigned int line_spacing = main_line_spacing; bool right_to_left = main_right_to_left; if (vsn > 0) { font = fonts[vsn - 1]; line_spacing = line_spacings[vsn - 1]; right_to_left = right_to_lefts[vsn - 1]; } text2pdf.set_font(font); text2pdf.set_line_spacing(line_spacing); text2pdf.set_right_to_left(right_to_left); // Get the verse text. ustring line; if (vsn == 0) { // First version. ProjectBook *projectbook = main_project.get_book_pointer(references[rf].book); if (projectbook) { ProjectChapter *projectchapter = projectbook->get_chapter_pointer(references[rf].chapter); if (projectchapter) { ProjectVerse *projectverse = projectchapter->get_verse_pointer(references[rf].verse); if (projectverse) { line = projectverse->data; } } } } else { // Other versions. // Get mapped chapters / verses. line.clear(); vector <int> mychapters; vector <int> myverses; mapping_s[vsn - 1].book_change(references[rf].book); mapping_s[vsn - 1].original_to_me(hebrew_greek_chapters, hebrew_greek_verses, mychapters, myverses); // Get text of any of the mapped verses. for (unsigned int mp = 0; mp < mychapters.size(); mp++) { // Get the verse and add it to the usfm code. ProjectBook *projectbook = project_memories[vsn - 1].get_book_pointer(references[rf].book); if (projectbook) { ProjectChapter *projectchapter = projectbook->get_chapter_pointer(mychapters[mp]); if (projectchapter) { ProjectVerse *projectverse = projectchapter->get_verse_pointer(convert_to_string(myverses[mp])); if (projectverse) { if (!line.empty()) line.append (" "); line.append (projectverse->data); } } } } } // Add the project name if there are more than one. if (!project_names.empty()) { ustring project; if (vsn == 0) project = main_project.name; else project = project_names[vsn - 1]; text2pdf.open_paragraph(); text2pdf.inline_set_font_size_percentage(65); text2pdf.add_text(project); text2pdf.inline_clear_font_size_percentage(); text2pdf.add_text(" "); } else { text2pdf.open_paragraph(); } // Do text replacement. text_replacement(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); // Insert the code for highlighting. for (int i = highlight_positions.size () - 1; i >= 0; i--) { for (int i2 = highlight_lengths.size() - 1; i2 >= 0; i2--) { line.insert (highlight_positions[i] + i2, INSERTION_FLAG); } } // Add usfm converter to the layout engine, and set various things. Usfm2Text usfm2text(&text2pdf, false); usfm2text.add_styles(usfm2xslfo_read_stylesheet(stylesheet)); usfm2text.no_bold(); usfm2text.no_space_before_or_after(); usfm2text.no_new_page(); usfm2text.add_usfm_code(line); usfm2text.process(); } // Add a bit of space. text2pdf.close_paragraph(); text2pdf.add_text(" "); text2pdf.close_paragraph(); // Whether to close code keeping things on one page. if (keep_verses_together_within_page) { text2pdf.close_keep_together(); } } // Hide progeressbar. progresswindow.hide(); // Process the data. text2pdf.run(); // Display the pdf file. text2pdf.view(); // Log: ready. gw_message(_("Ready printing the parallel references")); }