void notes_handle_vcs_feedback (const ustring& directory, const ustring& feedback) // This handles the feedback that comes from the version control system. { if (directory == notes_shared_storage_folder ()) { unsigned int note_id = 0; // The following feedback indicates that somebody created a new note: // create mode 100644 27185458 if (feedback.find ("create mode") != string::npos) { ustring s (feedback); s.erase (12); Parse parse (s); if (parse.words.size () == 2) { note_id = convert_to_int (parse.words[1]); } } // The following feedback indicates that somebody modified a note: // # modified: 27185458 if (feedback.find ("modified:") != string::npos) { ustring s (feedback); s.erase (12); note_id = convert_to_int (number_in_string (feedback)); } // The following feedback indicates that somebody deleted a note: // # deleted: 46473236 if (feedback.find ("deleted:") != string::npos) { ustring s (feedback); s.erase (11); note_id = convert_to_int (number_in_string (feedback)); } // See the following: // 95935882 | 9 +++++++++ // It means that this note was edited. if (feedback.find (" | ") != string::npos) { note_id = convert_to_int (number_in_string (feedback)); } if (note_id != 0) { gw_message (_("Change detected for note ") + convert_to_string (note_id)); // Update the index. sqlite3 *db; sqlite3_open(notes_index_filename ().c_str(), &db); sqlite3_busy_timeout(db, 1000); notes_store_index_entry (db, note_id); sqlite3_close(db); } } }
ustring resource_url_enter_reference(const ustring& constructor, map <unsigned int, ustring>& books, map <unsigned int, ustring>& books2, const Reference& reference) { ustring url (constructor); replace_text(url, resource_url_constructor_book(), books[reference.book_get()]); replace_text(url, resource_url_constructor_book2(), books2[reference.book_get()]); replace_text(url, resource_url_constructor_chapter(), convert_to_string(reference.chapter_get())); replace_text(url, resource_url_constructor_verse(), number_in_string(reference.verse_get())); return url; }
CategorizeChapterVerse::CategorizeChapterVerse(const vector < ustring > &lines) // Categorizes the lines by adding chapter and verse information to it. // It expects each \c and \v to start a new line, i.e. the lines are "clean". // Gives one line per verse. { // Variables. unsigned int chapternumber = 0; ustring versenumber = "0"; ustring text; unsigned int previous_chapter = 0; ustring previous_verse = "0"; // Go through all the lines. for (unsigned int i = 0; i < lines.size(); i++) { // Extract the marker, and deal with it. ustring ln = lines[i]; ustring marker = usfm_extract_marker(ln); // Chapter. if (marker == "c") { ustring number_in_line = number_in_string(ln); // Only accept the number if it is well-formed. if ((ln.substr(0, number_in_line.length()) == number_in_line) && (!number_in_line.empty())) { chapternumber = convert_to_int(number_in_line); if (i == 0) previous_chapter = chapternumber; // For one-chapter texts versenumber = "0"; } } // Verse if (marker == "v") { versenumber = ln; // Make it robust, even handling cases like: // - \v 1-2"Moi - No space after verse number. size_t spaceposition = versenumber.find_first_not_of("0123456789,-ab"); if (spaceposition != string::npos) { versenumber = versenumber.substr(0, spaceposition); } // Handle case that the usfm file does not contain the \c 1. if ((versenumber != "0") && (chapternumber == 0)) { chapternumber = 1; } } // Store data. if ((chapternumber != previous_chapter) || (versenumber != previous_verse)) { store(previous_chapter, previous_verse, text); text.clear(); previous_chapter = chapternumber; previous_verse = versenumber; } // Save text. if (!text.empty()) text.append("\n"); text.append(lines[i]); } if (!text.empty()) store(chapternumber, versenumber, text); }
void NotesTransferDialog::clean_note(ustring & note) // "Cleans" the note: removes unnecessary stuff. { ustring working_copy(note); ustring marker = usfm_extract_marker(working_copy); if (marker == "v") { usfm_extract_marker(note); note = trim(note); ustring verse = number_in_string(note); note.erase(0, verse.length()); note = trim(note); } }
void GotoReferenceDialog::on_move_chapter() { extern Settings *settings; // Chapter number changed, therefore update the verse numbers. ustring chapter = listview_get_active_string(treeview_chapter); // Something weird in Gtk: If the listview was not in view, it gives no results. // Deal with that here. if (chapter.empty()) return; // Get the verses as they are in the chapter. unsigned int bookid = books_name_to_id(language, listview_get_active_string(treeview_book)); vector < ustring > verses; verses = project_get_verses(settings->genconfig.project_get(), bookid, convert_to_int(chapter)); // The verses may contain sequences and ranges, but fill them up with the // verses contained in those. E.g.: 10-12 also contains 11. vector < ustring > verses2; set < ustring > verses2_set; for (unsigned int i = 0; i < verses.size(); i++) { verses2.push_back(verses[i]); if (number_in_string(verses[i]) != verses[i]) { vector < unsigned int >int_verses = verse_range_sequence(verses[i]); for (unsigned int i2 = 0; i2 < int_verses.size(); i2++) { ustring verse2 = convert_to_string(int_verses[i2]); // No double verses will be listed. if (verses2_set.find(verse2) == verses2_set.end()) { verses2.push_back(verse2); } verses2_set.insert(verse2); } } } listview_set_strings(treeview_verse, store_verse, verses2); if (oldbook == bookid) if (oldchapter == convert_to_int(chapter)) listview_focus_string(treeview_verse, oldverse); }
void CheckValidateUsfm::check(const ustring & text) // Do the actual check of one verse. { // Extract the marker, and deal with it. ustring utext = trim(text); if (utext.empty()) return; ustring line = utext; ustring marker = usfm_extract_marker_within_line(line); if (marker.empty()) { // No marker found. message(_("Line without USFM")); } while (!marker.empty()) { if (marker == "id") { // Is the line long enough? if (line.length() < 3) { message(_("ID line is too short: ") + line); } else { ustring id = line.substr(0, 3); unsigned int myid = books_paratext_to_id(id); if (myid == 0) message(_("Unknown id ") + id); if (id != upperCase(id)) message(_("Non-uppercase id code")); } } else if (marker == "c") { } else if (marker == "v") { // Is there a space after the verse number? // Check it by extracting the text will the first space, and see if any unusual characters are in it. // It should cover things like \v 10a-11b or \v 10,11 size_t position = line.find(" "); position = CLAMP(position, 0, line.length()); ustring verse_number = line.substr (0, position); for (unsigned int i = 0; i < verse_number.length(); i++) { ustring character = verse_number.substr (i, 1); if (number_in_string (character) != character) { if ((character != "a") || (character != "b") || (character != "-") || (character != ",")) { message (_("Unusual character in verse number ") + verse_number); break; } } } } else if (marker == "add") { check_on_endmarker(line, marker, false); } else if (marker == "bdit") { check_on_endmarker(line, marker, false); deprecated_marker(marker); } else if (marker == "bd") { check_on_endmarker(line, marker, false); deprecated_marker(marker); } else if (marker == "bk") { check_on_endmarker(line, marker, false); } else if (marker == "b") { } else if (marker == "ca") { } else if (marker == "cd") { } else if (marker == "cls") { } else if (marker == "cl") { } else if (marker == "conc") { } else if (marker == "cov") { } else if (marker == "cp") { } else if (marker == "dc") { check_on_endmarker(line, marker, false); } else if (marker == "d") { } else if (marker == "em") { check_on_endmarker(line, marker, false); deprecated_marker(marker); } else if (marker == "fdc") { check_on_endmarker(line, marker, true); } else if (marker == "fe") { check_on_endmarker(line, marker, false); } else if (marker == "fig") { check_on_endmarker(line, marker, false); } else if (marker == "fk") { check_on_endmarker(line, marker, true); } else if (marker == "fl") { check_on_endmarker(line, marker, true); } else if (marker == "fm") { check_on_endmarker(line, marker, false); } else if (marker == "fp") { } else if (marker == "fqa") { check_on_endmarker(line, marker, true); } else if (marker == "fq") { check_on_endmarker(line, marker, true); } else if (marker == "fr") { check_on_endmarker(line, marker, true); } else if (marker == "ft") { check_on_endmarker(line, marker, true); } else if (marker == "fv") { check_on_endmarker(line, marker, true); } else if (marker == "f") { check_on_endmarker(line, marker, false); } else if (marker == "fb") { // todo rogue fix - this check needs to be based on stylesheet, not hard coded. // A task was opened for this to be done. check_on_endmarker(line, marker, false); } else if (marker == "fx") { // todo rogue fix - this check needs to be based on stylesheet, not hard coded. // A task was opened for this to be done. check_on_endmarker(line, marker, false); } else if (marker == "glo") { } else if (marker == "h1") { } else if (marker == "h2") { } else if (marker == "h3") { } else if (marker == "h") { } else if (marker == "ib") { } else if (marker == "ide") { } else if (marker == "idx") { } else if (marker == "ie") { } else if (marker == "iex") { } else if (marker == "imi") { } else if (marker == "imq") { } else if (marker == "imt1") { } else if (marker == "imt2") { } else if (marker == "imt3") { } else if (marker == "imt4") { } else if (marker == "imte") { } else if (marker == "imt") { } else if (marker == "im") { } else if (marker == "intro") { } else if (marker == "io1") { } else if (marker == "io2") { } else if (marker == "io3") { } else if (marker == "io4") { } else if (marker == "ior") { check_on_endmarker(line, marker, false); } else if (marker == "iot") { } else if (marker == "io") { } else if (marker == "ipi") { } else if (marker == "ipq") { } else if (marker == "ipr") { } else if (marker == "ip") { } else if (marker == "iq1") { } else if (marker == "iq2") { } else if (marker == "iq3") { } else if (marker == "iq") { } else if (marker == "is1") { } else if (marker == "is2") { } else if (marker == "is") { } else if (marker == "it") { check_on_endmarker(line, marker, false); deprecated_marker(marker); } else if (marker == "k1") { } else if (marker == "k2") { } else if (marker == "k") { check_on_endmarker(line, marker, false); } else if (marker == "li1") { } else if (marker == "li2") { } else if (marker == "li3") { } else if (marker == "li4") { } else if (marker == "lit") { } else if (marker == "li") { } else if (marker == "maps") { } else if (marker == "mi") { } else if (marker == "mr") { } else if (marker == "ms1") { } else if (marker == "ms2") { } else if (marker == "ms") { } else if (marker == "mt1") { } else if (marker == "mt2") { } else if (marker == "mt3") { } else if (marker == "mt4") { } else if (marker == "mte1") { } else if (marker == "mte2") { } else if (marker == "mte") { } else if (marker == "mt") { } else if (marker == "m") { } else if (marker == "nb") { } else if (marker == "nd") { check_on_endmarker(line, marker, false); } else if (marker == "ndx") { check_on_endmarker(line, marker, false); } else if (marker == "no") { check_on_endmarker(line, marker, false); deprecated_marker(marker); } else if (marker == "ord") { check_on_endmarker(line, marker, false); } else if (marker == "p1") { } else if (marker == "p2") { } else if (marker == "pb") { } else if (marker == "pc") { } else if (marker == "pi1") { } else if (marker == "pi2") { } else if (marker == "pi3") { } else if (marker == "pi") { } else if (marker == "pmc") { } else if (marker == "pmo") { } else if (marker == "pmr") { } else if (marker == "pm") { } else if (marker == "pn") { check_on_endmarker(line, marker, false); } else if (marker == "pref") { } else if (marker == "pro") { check_on_endmarker(line, marker, false); } else if (marker == "pubinfo") { } else if (marker == "pub") { } else if (marker == "p") { } else if (marker == "q1") { } else if (marker == "q2") { } else if (marker == "q3") { } else if (marker == "qac") { check_on_endmarker(line, marker, false); } else if (marker == "qa") { } else if (marker == "qc") { } else if (marker == "qm1") { } else if (marker == "qm2") { } else if (marker == "qm3") { } else if (marker == "qm") { } else if (marker == "qr") { } else if (marker == "qs") { } else if (marker == "qt") { check_on_endmarker(line, marker, false); } else if (marker == "q") { } else if (marker == "rem") { } else if (marker == "restore") { } else if (marker == "r") { } else if (marker == "rq") { } else if (marker == "s1") { } else if (marker == "s2") { } else if (marker == "s3") { } else if (marker == "s4") { } else if (marker == "sc") { check_on_endmarker(line, marker, false); deprecated_marker(marker); } else if (marker == "sig") { check_on_endmarker(line, marker, false); } else if (marker == "sls") { check_on_endmarker(line, marker, false); } else if (marker == "spine") { } else if (marker == "sp") { } else if (marker == "sr") { } else if (marker == "s") { } else if (marker == "tc1") { } else if (marker == "tc2") { } else if (marker == "tc3") { } else if (marker == "tc4") { } else if (marker == "tcr1") { } else if (marker == "tcr2") { } else if (marker == "tcr3") { } else if (marker == "tcr4") { } else if (marker == "th1") { } else if (marker == "th2") { } else if (marker == "th3") { } else if (marker == "th4") { } else if (marker == "thr1") { } else if (marker == "thr2") { } else if (marker == "thr3") { } else if (marker == "thr4") { } else if (marker == "tl") { check_on_endmarker(line, marker, false); } else if (marker == "toc1") { } else if (marker == "toc2") { } else if (marker == "toc3") { } else if (marker == "toc") { } else if (marker == "tr") { } else if (marker == "va") { check_on_endmarker(line, marker, false); } else if (marker == "vp") { check_on_endmarker(line, marker, false); } else if (marker == "wg") { check_on_endmarker(line, marker, false); } else if (marker == "wh") { check_on_endmarker(line, marker, false); } else if (marker == "wj") { check_on_endmarker(line, marker, false); } else if (marker == "w") { check_on_endmarker(line, marker, false); } else if (marker == "xdc") { check_on_endmarker(line, marker, true); } else if (marker == "xk") { check_on_endmarker(line, marker, true); } else if (marker == "xo") { check_on_endmarker(line, marker, true); } else if (marker == "xq") { check_on_endmarker(line, marker, true); } else if (marker == "xt") { check_on_endmarker(line, marker, true); } else if (marker == "x") { check_on_endmarker(line, marker, false); } else if (marker.find("*") != string::npos) { message(_("Unmatched end marker ") + marker); } else { message(_("Unknown USFM ") + marker); } // Optionally check whether this marker is in the stylesheet. if (mychecksheet) { if (styles.find(marker) == styles.end()) { message(_("Marker ") + marker + _(" not in stylesheet")); } } // Extract any next marker in this line. marker = usfm_extract_marker_within_line(line); } // Deal with accidentally entered forward slashes instead of backslashes. line = utext; marker = usfm_extract_marker_with_forwardslash(line); while (!marker.empty()) { ustring originalmarker(marker); size_t pos = marker.find("*"); if (pos != string::npos) { marker.erase(pos, 1); } if ((marker == "id") || (marker == "c") || (marker == "v") || (marker == "add") || (marker == "bdit") || (marker == "bd") || (marker == "bk") || (marker == "b") || (marker == "ca") || (marker == "cd") || (marker == "cls") || (marker == "cl") || (marker == "conc") || (marker == "cov") || (marker == "cp") || (marker == "dc") || (marker == "d") || (marker == "em") || (marker == "fdc") || (marker == "fe") || (marker == "fig") || (marker == "fk") || (marker == "fl") || (marker == "fm") || (marker == "fp") || (marker == "fqa") || (marker == "fq") || (marker == "fr") || (marker == "ft") || (marker == "fv") || (marker == "f") || (marker == "glo") || (marker == "h1") || (marker == "h2") || (marker == "h3") || (marker == "h") || (marker == "ib") || (marker == "ide") || (marker == "idx") || (marker == "ie") || (marker == "iex") || (marker == "imi") || (marker == "imq") || (marker == "imt1") || (marker == "imt2") || (marker == "imt3") || (marker == "imt4") || (marker == "imte") || (marker == "imt") || (marker == "im") || (marker == "intro") || (marker == "io1") || (marker == "io2") || (marker == "io3") || (marker == "io4") || (marker == "ior") || (marker == "iot") || (marker == "io") || (marker == "ipi") || (marker == "ipq") || (marker == "ipr") || (marker == "ip") || (marker == "iq1") || (marker == "iq2") || (marker == "iq3") || (marker == "iq") || (marker == "is1") || (marker == "is2") || (marker == "is") || (marker == "it") || (marker == "k1") || (marker == "k2") || (marker == "k") || (marker == "li1") || (marker == "li2") || (marker == "li3") || (marker == "li4") || (marker == "lit") || (marker == "li") || (marker == "maps") || (marker == "mi") || (marker == "mr") || (marker == "ms1") || (marker == "ms2") || (marker == "ms") || (marker == "mt1") || (marker == "mt2") || (marker == "mt3") || (marker == "mt4") || (marker == "mte1") || (marker == "mte2") || (marker == "mte") || (marker == "mt") || (marker == "m") || (marker == "nb") || (marker == "nd") || (marker == "ndx") || (marker == "no") || (marker == "ord") || (marker == "p1") || (marker == "p2") || (marker == "pb") || (marker == "pc") || (marker == "pi1") || (marker == "pi2") || (marker == "pi3") || (marker == "pi") || (marker == "pmc") || (marker == "pmo") || (marker == "pmr") || (marker == "pm") || (marker == "pn") || (marker == "pref") || (marker == "pro") || (marker == "pubinfo") || (marker == "pub") || (marker == "p") || (marker == "q1") || (marker == "q2") || (marker == "q3") || (marker == "qac") || (marker == "qa") || (marker == "qc") || (marker == "qm1") || (marker == "qm2") || (marker == "qm3") || (marker == "qm") || (marker == "qr") || (marker == "qs") || (marker == "qt") || (marker == "q") || (marker == "rem") || (marker == "restore") || (marker == "r") || (marker == "rq") || (marker == "s1") || (marker == "s2") || (marker == "s3") || (marker == "s4") || (marker == "sc") || (marker == "sig") || (marker == "sls") || (marker == "spine") || (marker == "sp") || (marker == "sr") || (marker == "s") || (marker == "tc1") || (marker == "tc2") || (marker == "tc3") || (marker == "tc4") || (marker == "tcr1") || (marker == "tcr2") || (marker == "tcr3") || (marker == "tcr4") || (marker == "th1") || (marker == "th2") || (marker == "th3") || (marker == "th4") || (marker == "thr1") || (marker == "thr2") || (marker == "thr3") || (marker == "thr4") || (marker == "tl") || (marker == "toc1") || (marker == "toc2") || (marker == "toc3") || (marker == "toc") || (marker == "tr") || (marker == "va") || (marker == "vp") || (marker == "wg") || (marker == "wh") || (marker == "wj") || (marker == "w") || (marker == "xdc") || (marker == "xk") || (marker == "xo") || (marker == "xq") || (marker == "xt") || (marker == "x") ) { message(_("Normal slash for /") + originalmarker); } // Extract any next marker in this line. marker = usfm_extract_marker_with_forwardslash(line); } // Check for widow backslashes. line = utext + " "; if ((line.find("\\ ") != string::npos) || (line == "\\")) { message(_("Widow backslash")); } }
void PrintProject2::print() // Runs the project through xetex and shows it in a pdf viewer. { // Scripture related data. // Possible exclusion of books. if (portionproject.empty()) portionproject = myproject->name; scriptureportions = new ScripturePortions(portionproject); if (scriptureportions->books.empty()) { gtkw_dialog_info(NULL, _("There were no books to print\nSelect some books and try again")); return; } // Create the XeTeX object. XeTeX xetex (0); // Usfm style object. Usfm usfm (stylesheet_get_actual ()); // Collect usfm code for all the books. for (unsigned int i = 0; i < scriptureportions->books.size(); i++) { // Book id. unsigned int book_id = books_english_to_id(scriptureportions->books[i]); // Ranges to include. WithinReferencesRange inrange; { vector <unsigned int> chapters_from, chapters_to; vector <ustring> verses_from, verses_to; select_portion_get_values(portionproject, book_id, scriptureportions->portions[i], chapters_from, verses_from, chapters_to, verses_to); inrange.add_portion(book_id, chapters_from, verses_from, chapters_to, verses_to); } inrange.set_book (book_id); inrange.set_chapter (0); inrange.set_verse ("0"); // Open the book. vector <ustring> full_book_lines; for (unsigned int i2 = 0; i2 < myproject->data.size(); i2++) { if (myproject->data[i2].number == book_id) { full_book_lines = myproject->data[i2].get_data(); } } // Take only those portions the user wishes to print. vector <ustring> book_lines; for (unsigned int i = 0; i < full_book_lines.size(); i++) { ustring line = full_book_lines[i]; ustring marker = usfm_extract_marker(line); if (usfm.is_chapter_number(marker)) { inrange.set_chapter (convert_to_int(number_in_string(line))); inrange.set_verse ("0"); } if (usfm.is_verse_number(marker)) { size_t position = line.find(" "); position = CLAMP(position, 0, line.length()); ustring verse = line.substr(0, position); inrange.set_verse (verse); } if (inrange.in_range()) { book_lines.push_back (full_book_lines[i]); } else { if (marker == "id") { ParseLine parseline (full_book_lines[i]); if (!parseline.lines.empty ()) { book_lines.push_back (parseline.lines[0]); } } } } // Do text replacements on the lines. text_replacement(book_lines); // Add the lines to the XeTeX object. xetex.add_book (book_id, book_lines); } // Process the data. ustring pdf_file = xetex.run (); // Display the pdf file if there is one. // There would be none if the formatting process was cancelled by the user. if (!pdf_file.empty()) { pdfviewer_view (pdf_file); } }
void import_bibleworks_text_file (const ustring& file, const ustring& bible, vector <ustring>& messages) // Imports a bibleworks text file. { // Read the file. ReadText rt (file, true, false); // If there's nothing to import, bail out. if (rt.lines.empty()) { messages.push_back ("The file is empty"); } // Divide the input into separate bits for each book. vector <VectorUstring> bookdata; if (messages.empty()) { try { ustring previousbook; vector < ustring > booklines; de_byte_order_mark (rt.lines[0]); for (unsigned int i = 0; i < rt.lines.size(); i++) { ustring currentbook = rt.lines[i].substr(0, 3); if (i == 0) { previousbook = currentbook; } if (currentbook != previousbook) { bookdata.push_back (booklines); booklines.clear(); previousbook = currentbook; } booklines.push_back(rt.lines[i]); } bookdata.push_back (booklines); } catch(exception & ex) { messages.push_back(ex.what()); } } // Import each book. if (messages.empty ()) { ProgressWindow progresswindow ("Importing", false); progresswindow.set_iterate (0, 1, bookdata.size()); for (unsigned int i = 0; i < bookdata.size(); i++) { progresswindow.iterate (); try { // Input and output data. vector <ustring> rawlines = bookdata[i]; vector <ustring> usfmlines; // Get the name of the book. unsigned int book_id = books_bibleworks_to_id(rawlines[0].substr(0, 3)); if (book_id == 0) { messages.push_back ("Unknown book: " + rawlines[0]); return; } // Store USFM id. ustring usfmid = books_id_to_paratext (book_id); usfmlines.push_back("\\id " + usfmid); // Convert the BibleWorks lines to USFM code. ustring previouschapter = "0"; for (unsigned int i = 0; i < rawlines.size(); i++) { // Convert chapter information. ustring line = rawlines[i]; line.erase(0, 4); ustring currentchapter = number_in_string(line); line.erase(0, currentchapter.length() + 1); if (currentchapter != previouschapter) { usfmlines.push_back("\\c " + currentchapter); usfmlines.push_back("\\p"); previouschapter = currentchapter; } // Convert verse data. usfmlines.push_back("\\v " + line); } // Store into the Bible. CategorizeChapterVerse ccv(usfmlines); project_store_book(bible, book_id, ccv); } catch(exception & ex) { messages.push_back(ex.what()); } } } }
vector <ustring> mechon_mamre_extract_contents (const ustring& file, unsigned int chapter) { // Usfm data. vector <ustring> lines; // Convert chapter number to USFM code. lines.push_back("\\c " + convert_to_string(chapter)); lines.push_back("\\p"); // Read the text of the .htm file, and select only the .htm lines that // contain the actual text. vector < ustring > htmlines; { ReadText rt (file, true, false); // Find lower boundary: the relevant parts start with a verse number. unsigned int lower_boundary = 0; for (unsigned int i = 0; i < rt.lines.size(); i++) { if (rt.lines[i].find("A NAME=") != string::npos) { lower_boundary = i; break; } } // Find higher boundary: the relevant part ends with a verse number // that is one past the last verse. unsigned int upper_boundary = 0; for (unsigned int i = rt.lines.size() - 1; i > 0; i--) { if (rt.lines[i].find("A NAME=") != string::npos) { upper_boundary = i; upper_boundary++; break; } } // Store the relevant html lines that contain the verses. for (unsigned int i = lower_boundary; i <= upper_boundary; i++) { htmlines.push_back(rt.lines[i]); } } // Go through the relevant text and extract the verses. ustring verse; for (unsigned int ln = 0; ln < htmlines.size(); ln++) { ustring s = number_in_string(htmlines[ln]); if (!s.empty()) { verse = "\\v " + s; } else { // A text line could be looking so (Psalms 1:1): // <P><B>א</B> אַ֥שְֽׁרֵי הָאִ֗ישׁ אֲשֶׁ֤ר ׀ לֹ֥א הָלַךְ֮ בַּֽעֲצַ֪ת רְשָׁ֫עִ֥ים<BR>וּבְדֶ֣רֶךְ חַ֭טָּאִים לֹ֥א עָמָ֑ד וּבְמוֹשַׁ֥ב לֵ֝צִ֗ים לֹ֣א יָשָֽׁב׃<BR> ustring line = htmlines[ln]; // Convert <BR>, </P>, etc. replace_text(line, "<BR>", "\n\\nb\n"); replace_text(line, "</P>", "\n\\p\n"); replace_text(line, "<BIG>", ""); replace_text(line, "</BIG>", ""); replace_text(line, "{פ}", ""); replace_text(line, "{ס}", ""); size_t position = line.find_last_of(">"); line.erase(0, ++position); line = trim(line); lines.push_back(verse + " " + line); } } // Return the data. return lines; }
void OpenDocument::format_general(vector <ustring>& lines) // General formatter for USFM lines given. { // Go through all the lines. odttextparagraph = NULL; for (unsigned int ln = 0; ln < lines.size(); ln++) { ustring line = lines[ln]; // Take any elastics out, put the \b marker instead. replace_text(line, ELASTIC_MARKER, "b"); // Change certain characters to xml entities. xml_handle_entities(line, NULL); // Deal with footnotes. odtfootnote->transform(line); // Deal with endnotes. odtendnote->transform(line); // Deal with crossreferences. odtxref->transform(line); // Deal with inline text. usfm_handle_inline_text(line, usfm_inline_markers, NULL, imOpenDocument, NULL); // Signal new line. if (odttextparagraph) odttextparagraph->newline(); // Get the style belonging to the marker. ustring marker = usfm_extract_marker(line); if (usfm->is_identifier(marker)) { // Handle some identifiers. IdentifierType identifiertype = usfm->identifier_get_subtype(marker); // New book. if (identifiertype == itBook) { if (odttextparagraph) delete odttextparagraph; odttextparagraph = new OdtTextParagraph(&odtlines, marker); } } else if (usfm->is_verse_number(marker)) { // Because of dealing with portions to include/exclude, handle verse first. // Get verse number. Handle combined verses too, e.g. 10-12b, etc. size_t position = line.find(" "); position = CLAMP(position, 0, line.length()); ustring versenumber = line.substr(0, position); position++; line.erase(0, position); // There was a bug that the chapter number was missing from a book, // and that results in text being inserted without the opening xml code. // Solution: If no paragraph has been opened, open a default one. if (odttextparagraph == NULL) odttextparagraph = new OdtTextParagraph(&odtlines, ""); // Insert a bookmark at the verse. // This will become an anchor for the Bibledit Resource Viewer, // once OpenOffice saves the document to a HTML Document. // Example bookmark: <text:bookmark text:name="Malachi_1_1"/> ustring bookmark = resource_viewer_produce_anchor(anchor_book, anchor_chapter, convert_to_int(number_in_string(versenumber))); bookmark.insert(0, "<text:bookmark text:name=\""); bookmark.append("\"/>"); odttextparagraph->plaintext(bookmark); // When the usfm is a verse number, then the number is put in the // format specified by the stylesheet, but the remaining part of the // line inherits the formatting from the paragraph it is in. odttextparagraph->spannedtext(versenumber, marker); odttextparagraph->plaintext(line); } else if (usfm->is_starting_paragraph(marker)) { if (odttextparagraph) delete odttextparagraph; odttextparagraph = new OdtTextParagraph(&odtlines, marker); if (!line.empty()) odttextparagraph->plaintext(line); } else if (usfm->is_inline_text(marker)) { // Inline text, has been dealt with before (therefore should never occur here). if (odttextparagraph) odttextparagraph->spannedtext(line, marker); } else if (usfm->is_chapter_number(marker)) { // Close possible open paragraph. if (odttextparagraph) delete odttextparagraph; // Signal new chapter to footnotes object. odtfootnote->new_chapter(); // Store chapter for the anchors. anchor_chapter = convert_to_int(number_in_string(line)); // Insert or prepare chapter text. odttextparagraph = new OdtTextParagraph(&odtlines, marker); odttextparagraph->plaintext(line); } else if (usfm->is_peripheral(marker)) { } else if (usfm->is_picture(marker)) { } else if (usfm->is_pagebreak(marker)) { if (odttextparagraph) delete odttextparagraph; odttextparagraph = new OdtTextParagraph(&odtlines, marker); } else { // Fallback for unknown marker or no marker. if (!odttextparagraph) odttextparagraph = new OdtTextParagraph(&odtlines, ""); odttextparagraph->plaintext(line); // Make a note of this marker, that it was not formatted. unformatted_markers.insert (marker); } } // Close possible last paragraph. if (odttextparagraph) delete odttextparagraph; }
// Returns an array with the verse numbers found in $usfm. // It handles a single verse, a range of verses, or a sequence of verses. // It locates separate whole verse numbers. // Examples: // 10 // 10-12b // 10,11a // 10,12 vector <int> usfm_get_verse_numbers (string usfm) { vector <int> verse_numbers = { 0 }; vector <string> markers_and_text = usfm_get_markers_and_text (usfm); bool extract_verse = false; for (string marker_or_text : markers_and_text) { if (extract_verse) { string verse = usfm_peek_verse_number (marker_or_text); // If there is a range, take the beginning and the end and fill up in between. if (verse.find("-") != string::npos) { size_t position; position = verse.find("-"); string start_range, end_range; start_range = verse.substr (0, position); verse.erase (0, ++position); end_range = verse; unsigned int start_verse_i = convert_to_int(number_in_string(start_range)); unsigned int end_verse_i = convert_to_int(number_in_string(end_range)); for (unsigned int i = start_verse_i; i <= end_verse_i; i++) { if (i == start_verse_i) verse_numbers.push_back (convert_to_int (start_range)); else if (i == end_verse_i) verse_numbers.push_back (convert_to_int (end_range)); else verse_numbers.push_back (i); } } // Else if there is a sequence, take each verse in the sequence, and store it. else if (verse.find(",") != string::npos) { int iterations = 0; do { // In case of an unusual range formation, do not hang, but give message. iterations++; if (iterations > 50) { break; } size_t position = verse.find (","); string vs; if (position == string::npos) { vs = verse; verse.clear (); } else { vs = verse.substr (0, position); verse.erase(0, ++position); } verse_numbers.push_back (convert_to_int (vs)); } while (!verse.empty()); } // No range and no sequence: a single verse. else { verse_numbers.push_back (convert_to_int (verse)); } extract_verse = false; } if (marker_or_text.substr (0, 2) == "\\v") { extract_verse = true; } } return verse_numbers; }
void CheckChaptersVerses::verses_check(unsigned int book, unsigned int chapter, const vector < ustring > &verses) // This checks all the verses that are in 'book' and 'chapter'. // It supports sequences in the form of \v 1,2,3, // and ranges in the form of \v 1b-3 and \v 2-4a and \v 2b-5a. { // Check whether there are any verses at all. If not, stop further // processing because the following code assumes there are verses. if (verses.empty()) { message(book, chapter, "1", _("Chapter has no verses")); return; } // Check for verses in chapter 0, which indicates the \c 1 marker wasn't there. if ((chapter == 0) && (verses.size() > 1)) { message(book, chapter, "1", _("Chapter marker missing")); } // Transform the verses in the internally used encoding, so as to accomodate // for sequences and ranges. vector < unsigned int >expanded_verses; vector < unsigned int >verses_pointers; for (unsigned int i = 0; i < verses.size(); i++) { // Do not work in the container, but on a copy. ustring vs(verses[i]); // If there is a range, take the beginning and the end and fill up in between. if (vs.find("-") != string::npos) { size_t position; position = vs.find("-"); ustring start_range, end_range; start_range = vs.substr(0, position); vs.erase(0, ++position); end_range = vs; int start_expanded_verse = 2 * convert_to_int(number_in_string(start_range)); if (start_range.find("b") != string::npos) start_expanded_verse++; // Checking on range start. if (start_range.find("a") != string::npos) message(book, chapter, verses[i], _("Range starts with \"a\"")); int end_expanded_verse = 2 * convert_to_int(number_in_string(end_range)); if (end_range.find("a") == string::npos) end_expanded_verse++; // Check on range end. if (end_range.find("b") != string::npos) message(book, chapter, verses[i], _("Range ends with \"b\"")); for (int i2 = start_expanded_verse; i2 <= end_expanded_verse; i2++) { expanded_verses.push_back(i2); verses_pointers.push_back(i); } } // If there is a sequence, take each verse in the sequence, and store it. else if (vs.find(",") != string::npos) { int iterations = 0; do { // In case of an unusual range formation, do not hang, but give message. iterations++; if (iterations > 50) { message(book, chapter, verses[i], _("Unusual verse sequence")); break; } size_t position = vs.find(","); ustring verse; if (position == string::npos) { verse = vs; vs.clear(); } else { verse = vs.substr(0, position); vs.erase(0, ++position); } store_expanded_verse(verse, i, expanded_verses, verses_pointers); } while (!vs.empty()); } // No range and no sequence: a "normal" verse. else { store_expanded_verse(vs, i, expanded_verses, verses_pointers); } } // See whether it starts at verse 0 or 1. if (expanded_verses[0] > 2) message(book, chapter, verses[0], "Verse 1 missing"); // See whether the verses are within the limit. for (unsigned int i = 0; i < expanded_verses.size(); i += 2) { unsigned int verse; verse = expanded_verses[i] / 2; if (verse > highest_verse) { message(book, chapter, convert_to_string(verse), _("Extra verse or wrong versification")); } } // See whether there are verses or bits out of sequence. int previous_verse = expanded_verses[0] - 1; for (unsigned int i = 0; i < expanded_verses.size(); i++) { ustring previous_verse_text; unsigned int pointer = verses_pointers[i]; if (pointer == 0) previous_verse_text = _("beginning"); else previous_verse_text = verses[pointer - 1]; if ((int)expanded_verses[i] != previous_verse + 1) { message(book, chapter, verses[pointer], _("Verse out of sequence following ") + previous_verse_text); } previous_verse = expanded_verses[i]; } // Check whether we have enough verses. int highverse = expanded_verses[expanded_verses.size() - 1]; highverse = highverse / 2; if (highverse < (int)highest_verse) { message(book, chapter, verses[verses.size() - 1], _("Not enough verses in chapter")); } // Clear storage. expanded_verses.clear(); verses_pointers.clear(); }
// Import raw $text into $bible $book $chapter. void bible_import_text (string text, string bible, int book, int chapter) { // Consecutive discoveries. bool discoveries_passed = true; // Split the input text into separate lines. vector <string> lines = filter_string_explode (text, '\n'); // Go through the lines. for (size_t i = 0; i < lines.size(); i++) { // Trim the line. lines[i] = filter_string_trim (lines[i]); // Skip empty line. if (lines[i].empty()) continue; // Remove chapter markup. if (lines[i].find("\\c") != string::npos) { lines[i].clear(); continue; } // Skip line starting with a backslash. The rationale is that this line already has markup. if (lines[i].substr(0, 1) == "\\") continue; // If the line is a number on its own, and the number agrees with the chapter number // that was set, it silently removes this line. But if it differs, an error comes up. if (discoveries_passed) { if (number_in_string(lines[i]) == lines[i]) { int number = convert_to_int (number_in_string (lines[i])); if (number == chapter) { lines[i].clear(); continue; } string msg = "The line that contains " + lines[i] + " looks like a chapter number, but the number differs from the chapter that was set"; Database_Logs::log (msg); discoveries_passed = false; } } // If the line has no number in it, // and it ends with some type of punctuation, // it is considered a a normal paragraph. // If no punctuation at the end, it is a section heading. if (discoveries_passed) { if (number_in_string(lines[i]).empty()) { string last_character = lines[i].substr(lines[i].length() -1, 1); if (unicode_string_is_punctuation (last_character)) { lines[i].insert(0, "\\p "); } else { lines[i].insert(0, "\\s "); } continue; } } // If a number is found in the line, then this is considered a verse number. // The first time a number is found, a \p is prefixed. bool paragraph_open = false; if (discoveries_passed) { string output; string number = number_in_string(lines[i]); // Setting for having the number only at the start of the line. bool treat_as_normal_paragraph = false; bool verses_at_start = true; if (verses_at_start) { if (lines[i].find (number) != 0) { number.clear(); treat_as_normal_paragraph = true; } } if (treat_as_normal_paragraph) { // Normal paragraph. lines[i].insert(0, "\\p "); } else { // Find all verse numbers. while (!number.empty()) { if (!paragraph_open) { output.append("\\p"); paragraph_open = true; } size_t pos = lines[i].find(number); if (pos > 0) { output.append(" " + lines[i].substr(0, pos)); lines[i].erase(0, pos); } output.append ("\n\\v "); output.append (number); output.append (" "); lines[i].erase (0, number.length()); lines[i] = filter_string_trim (lines[i]); number = number_in_string(lines[i]); // Setting for discovering only first number in a paragraph. if (verses_at_start) { number.clear(); } } } // Store line. output.append(lines[i]); lines[i] = output; } } // Make one block of text. string newtext; for (unsigned int i = 0; i < lines.size(); i++) { if (lines[i].empty()) continue; filter_string_str_replace (" ", " ", lines[i]); filter_string_str_replace (" \n", "\n", lines[i]); newtext.append(lines[i]); newtext.append("\n"); } // If no chapter marker is found, insert it at the top. if (newtext.find("\\c") == string::npos) { newtext.insert(0, "\\c " + convert_to_string(chapter) + "\n"); } // Import the text as USFM. bible_logic_store_chapter (bible, book, chapter, newtext); string book_name = Database_Books::getUsfmFromId (book); Database_Logs::log ("Imported " + book_name + " " + convert_to_string (chapter) + ": " + text); }
void CheckValidateReferences::check(const ustring & text) // Do the actual check of one verse. { // Bail out if the verse is empty. if (text.empty()) return; // Extract the references and check them all. ReferencesScanner refscanner(language, book, text); for (unsigned int i = 0; i < references.size(); i++) { // Check whether the reference fits within the limits of the versification system. bool reference_fits = true; unsigned int highest_chapter = 0; vector < unsigned int >chapters = versification_get_chapters(versification, refscanner.references[i].book_get()); if (!chapters.empty()) highest_chapter = chapters[chapters.size() - 1]; if (refscanner.references[i].chapter_get() > highest_chapter) reference_fits = false; unsigned int last_verse = convert_to_int(versification_get_last_verse(versification, refscanner.references[i].book_get(), refscanner.references[i].chapter_get())); unsigned int this_verse = convert_to_int(refscanner.references[i].verse_get()); if (this_verse > last_verse) reference_fits = false; if (!reference_fits) { message(refscanner.references[i].human_readable(language) + _(" does not fit in the versification system")); } // Check whether the reference exists in the project. if (reference_fits) { ustring versetext = project_retrieve_verse(myproject, refscanner.references[i]); if (versetext.empty()) { message(refscanner.references[i].human_readable(language) + _(" contains no text")); } } } // Look for chapter/verse pairs by pattern, and check on these. ustring mytext(text); while (mytext.length() > 5) { if (text_starts_chapter_verse(mytext)) { // This text starts a chapter/verse string. // Look for the dot or colon. size_t position = mytext.find_first_of(".:"); if (position != string::npos) { unsigned int mychapter = convert_to_int(mytext.substr(0, position)); mytext.erase(0, ++position); ustring myverse = number_in_string(mytext); mytext.erase(0, myverse.length()); bool referencefound = false; for (unsigned int i = 0; i < references.size(); i++) { if (refscanner.references[i].chapter_get() == mychapter) if (refscanner.references[i].verse_get() == myverse) referencefound = true; } if (!referencefound) { message(_("Unrecognized chapter ") + convert_to_string(mychapter) + _(" and verse ") + myverse); } } mytext.erase(0, 3); } else { // No chapter/verse string: erase one character and try again. mytext.erase(0, 1); } } }