Ejemplo n.º 1
0
 def new_guess(self):
     self.key = None
     while not self.key or not biblemgr.bible.mod.hasEntry(self.key):
         randomnum = random.randint(1, 31102)
         self.key = VK("Gen 1:%d" % randomnum)
     self.user_key = UserVK(self.key)
     self.reference_frame.SetReference(self.key.getText())
Ejemplo n.º 2
0
	def _get_document_parts_for_ref(self, module_name, ref, do_current_ref=True):
		t = default_timer()

		stylesheets = list(self.bible_stylesheets)
		scripts = self.standard_scripts + self.bible_scripts + ["highlight.js", "bpbible_html.js", "contrib/hyphenate.js", "columns.js"]

		book = biblemgr.get_module_book_wrapper(module_name)
		assert book, "Module wrapper not found for book " + module_name
		module = book.mod
		if book.chapter_view:
			scripts.append("bpbible_html_chapter_view.js")
			#stylesheets.append("bpbible_chapter_view.css")
			#stylesheets.append("bpbible://content/quotes_skin/")
		else:
			scripts.append("bpbible_html_page_view.js")
			stylesheets.append("bpbible_page_view.css")			
	
		if is_debugging():
			stylesheets.append("bpbible_html_debug.css")

		if book.is_verse_keyed:
			if book.chapter_view:
				if do_current_ref:
					c = book.GetChapter(ref, ref, config.current_verse_template)
				else:
					c = book.GetChapter(ref)

				ref_id = VK(ref).get_chapter_osis_ref()
				
			else:
				c = book.GetReference(ref, headings=True)
				ref_id = VK(ref).getOSISRef()


		elif book.is_dictionary:
			c = book.GetReference(ref)
			ref_id = ref

		elif book.is_genbook:
			c = book.GetReference(ref)
			ref_id = ref
		else:
			dprint(ERROR, "Book `%s' not found." % module_name)
			c = ''
		c = c.replace("<!P>", "</p><p>")

		clas = ""
		if not c:
			clas = " nocontent"

		lang = module.Lang() if module else "en",
		c = convert_language(c, lang)
		c = '<div class="segment%s" ref_id="%s">%s</div>' % (clas, urllib.quote(ref_id.encode("utf8")), c)

		return dict(
			module=module, content=c,
			bodyattrs=self._get_body_attrs(module),
			stylesheets=stylesheets,
			scripts=scripts,
			timer="<div class='timer'>Time taken: %.3f (ref_id %s)</div>" % (default_timer() - t, ref_id))
Ejemplo n.º 3
0
    def replace_bible_links(match):
        ref = match.group(1)
        #print "Replacing bible link", ref
        vk = VK(ref)

        return "href='book_%s.html#%s_start'" % (vk.getOSISBookName(),
                                                 vk.getOSISRef())
Ejemplo n.º 4
0
    def has_chapter(self, ref, mod=None):
        assert self.is_verse_keyed, "Calling has_chapter for non-verse keyed module."
        module = mod or self.mod
        if module is None:
            return False

        vk = VK(ref)
        if module.hasEntry(vk):
            return True

        vk.setVerse(1)
        if module.hasEntry(vk):
            return True

        module.setKey(vk)
        try:
            old_mod_skiplinks = module.getSkipConsecutiveLinks()
            module.setSkipConsecutiveLinks(True)
            module.increment()
            next_vk = VK.castTo(module.getKey())
            return (next_vk.Book() == vk.Book() and next_vk.Chapter()
                    == vk.Chapter() and next_vk.Testament()
                    == vk.Testament()) and not self.has_error(module)
        finally:
            module.setSkipConsecutiveLinks(old_mod_skiplinks)
Ejemplo n.º 5
0
	def new_guess(self):
		self.key = None
		while not self.key or not biblemgr.bible.mod.hasEntry(self.key):
			randomnum = random.randint(1, 31102)
			self.key = VK("Gen 1:%d" % randomnum)
		self.user_key = UserVK(self.key)
		self.reference_frame.SetReference(self.key.getText())
Ejemplo n.º 6
0
    def SetReference(self, ref, ref_to_scroll_to=None, settings_changed=False):
        """Sets reference. This is set up to be an observer of the main frame,
		so don't call internally. To set verse reference, use notify"""
        self.reference = GetVerseStr(ref)

        has_selected_new_verse = False
        # If the settings have changed we want to do a complete reload anyway
        # (since it could be something that requires a complete reload, such as changing version).
        if self.dom_loaded:
            if settings_changed:
                self.reference, ref_to_scroll_to = self.GetCurrentReferenceAndPosition(
                )
            else:
                osisRef = VK(self.reference).getOSISRef()
                has_selected_new_verse = self.ExecuteScriptWithResult(
                    'select_new_verse("%s")' % osisRef)
                has_selected_new_verse = (has_selected_new_verse == "true")

        if has_selected_new_verse:
            self.NewReferenceLoaded()
        elif self.CheckChapterInBook(ref):
            self.OpenURIForCurrentBook("bpbible://content/page/%s/%s" %
                                       (self.book.version, self.reference))

        if ref_to_scroll_to:
            self.scroll_to_osis_ref(ref_to_scroll_to)

        chapter = GetBookChapter(self.reference)
        self.header_bar.set_current_chapter(pysw.internal_to_user(chapter),
                                            chapter)

        self.update_title()
Ejemplo n.º 7
0
def _setupPassageLists(test):
    """Sets up the passage lists for the given test."""
    test._verse_list1 = VerseList(
        [VK(("gen 2:3", "gen 2:5")), "gen 3:4", "gen 5:2"])
    test._verse_list2 = VerseList(
        ["ex 2:2", "ex 3:5", VK(("ex 3:7", "ex 3:9"))])
    test._verse_list3 = VerseList([VK(("lev 2:3", "lev 2:5")), "lev 2:7"])
    test._verse_list4 = VerseList(["num 3:1", VK(("num 3:4", "num 3:5"))])
    test._list = PassageList.create_from_verse_list("abc", test._verse_list1)
    test._list2 = PassageList.create_from_verse_list("def", test._verse_list2)
    test._list3 = PassageList.create_from_verse_list("ghi", test._verse_list3)
    test._list4 = PassageList.create_from_verse_list("jkl", test._verse_list4)
    test._list2.add_subtopic(test._list4)
    test._list.add_subtopic(test._list2)
    test._list.add_subtopic(test._list3)
    test._manager = PassageListManager()
    test._manager.add_subtopic(test._list)
Ejemplo n.º 8
0
class GuessVerseFrame(xrcGuessVerseFrame):
    def __init__(self, parent):
        super(GuessVerseFrame, self).__init__(parent)

        # This call makes sure that the reference display frame is loaded
        # with an empty reference.
        # This means that all future references displayed will be shown with
        # Javascript, and so there won't be any focus bugs.
        self.reference_frame.RefreshUI()

        self.reference_frame.template = VerseTemplate(body=u"$text",
                                                      headings="")

        self.show_answer_button.Bind(wx.EVT_BUTTON, self.on_show_answer)
        self.guess_button.Bind(wx.EVT_BUTTON, self.on_guess)
        self.books.AppendItems([unicode(book) for book in UserVK.books])
        self.books.Selection = 0
        self.new_guess()
        self.Children[0].Fit()
        self.Fit()

    def new_guess(self):
        self.key = None
        while not self.key or not biblemgr.bible.mod.hasEntry(self.key):
            randomnum = random.randint(1, 31102)
            self.key = VK("Gen 1:%d" % randomnum)
        self.user_key = UserVK(self.key)
        self.reference_frame.SetReference(self.key.getText())

    def on_show_answer(self, event):
        Tooltip.do_not_show_tooltip = True
        wx.MessageBox(_("The verse was %s") % UserVK(self.key).getText(),
                      parent=self)
        Tooltip.do_not_show_tooltip = False

        self.new_guess()

    def on_guess(self, event):
        # XXX: We can't use the currently focused window trick to prevent
        # tooltips from grabbing focus when using a MessageBox, since it
        # gives the focused window as None.  Instead, we use this hack.
        Tooltip.do_not_show_tooltip = True
        won = self.user_key.getBookName() == self.books.StringSelection
        if won:
            wx.MessageBox(_("Yes, you are right. The verse was %s") %
                          UserVK(self.key).getText(),
                          _("Correct"),
                          parent=self)

            self.new_guess()
        else:
            wx.MessageBox(
                _("No, you are wrong. Try again."),
                _("Try again."),
                parent=self,
                style=wx.OK | wx.ICON_ERROR,
            )
        Tooltip.do_not_show_tooltip = False
Ejemplo n.º 9
0
 def __init__(self, parent, version=""):
     self.parent = parent
     self.mod = None
     self.observers = observerlist.ObserverList()
     self.cleanup_module = observerlist.ObserverList()
     self.template = VerseTemplate(body="$text")
     self.templatelist = [self.template]
     self.vk = VK()
     self.headings = False
     if self.ModuleExists(version):
         self.SetModule(version)
     else:
         mods = self.GetModuleList()
         if mods:
             self.SetModule(mods[0])
         else:
             dprint(WARNING, "No modules of type", self.type)
             self.SetModule(None)
Ejemplo n.º 10
0
def yield_verses(mod):
    from swlib.pysw import VK, TOP
    vk = VK()
    vk.Headings(1)
    vk.setPosition(TOP)
    #vk.setText("Matthew 1:1")
    vk.Persist(1)
    vk.thisown = False

    mod.setKey(vk)

    books = ("Genesis", "Matthew")  #"Exodus")
    while not vk.Error():
        #while vk.Testament() in '\x00\x01':
        #while vk.Testament() == '\x00' or vk.Book() == '\x00' or \
        #	vk.getBookName() in books:
        yield
        vk.increment(1)
Ejemplo n.º 11
0
	def testContainsVerseWorksWithRange(self):
		self.assert_(self._passage_entry2.contains_verse(VK("gen 3:5")))
		self.assert_(self._passage_entry2.contains_verse(VK("gen 3:6")))
		self.assert_(self._passage_entry2.contains_verse(VK("gen 3:9")))
		self.assert_(self._passage_entry2.contains_verse(VK("gen 3:10")))
		self.assert_(not self._passage_entry2.contains_verse(VK("gen 3:4")))
		self.assert_(not self._passage_entry2.contains_verse(VK("gen 3:11")))
Ejemplo n.º 12
0
	def cut_down_index(self, bottom, top):
		### not fully implemented for non-bibles
		vk1 = VK((self.bookname, self.bookname))
		vk = VK((bottom, top))
		vk_dn = vk.LowerBound()
		vk_up = vk.UpperBound()

		# the item we are currently looking for
		start_ref = None
		ret = []
		items = []
		
		self.old_text = self.text
		self.old_index = self.index

		for match in re.finditer("(?m)^.*$", self.text):
			if vk_dn <= vk1 <= vk_up:
				items.append(match.group())
			
			vk1.increment(1)
		
		self.text = '\n'.join(items)
		self.create_index_against_text(vk)
Ejemplo n.º 13
0
	def has_chapter(self, ref, mod=None):
		assert self.is_verse_keyed, "Calling has_chapter for non-verse keyed module."
		module = mod or self.mod
		if module is None:
			return False

		vk = VK(ref)
		if module.hasEntry(vk):
			return True

		vk.setVerse(1)
		if module.hasEntry(vk):
			return True

		module.setKey(vk)
		try:
			old_mod_skiplinks = module.getSkipConsecutiveLinks()
			module.setSkipConsecutiveLinks(True)
			module.increment()
			next_vk = VK.castTo(module.getKey())
			return (next_vk.Book() == vk.Book() and next_vk.Chapter() == vk.Chapter() and next_vk.Testament() == vk.Testament()) and not self.has_error(module)
		finally:
			module.setSkipConsecutiveLinks(old_mod_skiplinks)
Ejemplo n.º 14
0
        def insert_footnotes(match):
            #print "Inserting footnotes", match
            href = match.group(1)
            url = SW.URL(href.encode("utf8"))
            ftype = url.getParameterValue("type")  #x or n
            value = url.getParameterValue("value")  #number footnote in verse
            if ((not ftype) or (not value)):
                dprint(WARNING, "Not type or value in showNote", href)
                return ""

            module = biblemgr.get_module(url.getParameterValue("module"))
            passage = url.getParameterValue("passage")
            back_ref = VK(passage).getOSISRef()
            user_ref = book_fix(internal_to_user(passage))

            if not passage or not module:
                print "No passage/module?"
                return ""

            id = "footnote_data_%s_%s" % (back_ref, value)
            #print passage, id
            if ftype in ("n", "x"):
                data = sword_book.GetFootnoteData(module, passage, value,
                                                  "body")
                if footnotes[ftype] and footnotes[ftype][-1][0] == back_ref:
                    footnotes_group = footnotes[ftype][-1]
                else:
                    footnotes_group = [
                        back_ref,
                        "<div class='verse_footnotes footnote_%s' id='verse_footnote_%s_%s'>%s for "
                        "<a href='#%s_start'>%s</a>%%s</div>" %
                        (ftype, back_ref, ftype, footnote_types[ftype],
                         back_ref, user_ref)
                    ]

                    footnotes[ftype].append(footnotes_group)

                footnotes_group.append(
                    "<div class='footnote_data' id='%s'><span class='footnote_marker'>%s</span>: %s</div>"
                    % (id, match.group(3), data))
            else:
                print "Footnote type was", ftype

            id = "verse_footnote_%s_%s" % (back_ref, ftype)
            return 'href="#%s"%s' % (id, match.group(2))
Ejemplo n.º 15
0
	def __init__(self, parent, version = ""):
		self.parent = parent
		self.mod = None
		self.observers = observerlist.ObserverList()
		self.cleanup_module = observerlist.ObserverList()
		self.template = VerseTemplate(body = "$text")
		self.templatelist = [self.template]
		self.vk = VK()
		self.headings = False
		if self.ModuleExists(version):
			self.SetModule(version)
		else:
			mods = self.GetModuleList()
			if mods:
				self.SetModule(mods[0])
			else:
				dprint(WARNING, "No modules of type", self.type)
				self.SetModule(None)
Ejemplo n.º 16
0
    def get_verses_on_screen(self, verses):
        if not self.dom_loaded:
            return []

        osis_refs = [VK(verse).getOSISRef() for verse in verses]
        osis_refs_on_screen = self.ExecuteScriptWithResult("""
			(function(osis_refs) {
				var result = [];
				for (var index = 0; index < osis_refs.length; index++)	{
					var osisRef = osis_refs[index];
					var reference_found = $('[osisRef="' + osisRef + '"]').length > 0;
					if (reference_found)	{
						result.push(osisRef);
					}
				}
				return JSON.stringify(result);
			})(%s);
		""" % json.dumps(osis_refs))

        return json.loads(osis_refs_on_screen)
Ejemplo n.º 17
0
    def cut_down_index(self, bottom, top):
        ### not fully implemented for non-bibles
        vk1 = VK((self.bookname, self.bookname))
        vk = VK((bottom, top))
        vk_dn = vk.LowerBound()
        vk_up = vk.UpperBound()

        # the item we are currently looking for
        start_ref = None
        ret = []
        items = []

        self.old_text = self.text
        self.old_index = self.index

        for match in re.finditer("(?m)^.*$", self.text):
            if vk_dn <= vk1 <= vk_up:
                items.append(match.group())

            vk1.increment(1)

        self.text = '\n'.join(items)
        self.create_index_against_text(vk)
Ejemplo n.º 18
0
def yield_verses(mod):
	from swlib.pysw import VK, TOP
	vk = VK()
	vk.Headings(1)
	vk.setPosition(TOP)
	#vk.setText("Matthew 1:1")
	vk.Persist(1)
	vk.thisown = False
	
	mod.setKey(vk)

	books = ("Genesis", "Matthew")#"Exodus")
	while not vk.Error():
	#while vk.Testament() in '\x00\x01':
	#while vk.Testament() == '\x00' or vk.Book() == '\x00' or \
	#	vk.getBookName() in books:
		yield 
		vk.increment(1)
Ejemplo n.º 19
0
 def testVersesInMainTopicShouldBeContainedDirectly(self):
     self.assert_(self._list.contains_verse(VK("gen 3:4")))
Ejemplo n.º 20
0
 def random_verse(self):
     randomnum = random.randint(1, 31102)
     ref = VK("Gen 1:%d" % randomnum).text
     self.notify(ref, source=events.RANDOM_VERSE)
Ejemplo n.º 21
0
 def testVersesInSubtopicsShouldNotBeContainedDirectly(self):
     self.assert_(not self._list.contains_verse(VK("ex 2:2")))
     self.assert_(not self._list.contains_verse(VK("num 2:5")))
Ejemplo n.º 22
0
	def get_key(self, module):
		vk = VK((self.bookname, self.bookname))
		vk.Headings(0)
		vk.setPosition(TOP)
		return vk
Ejemplo n.º 23
0
 def current_segment_changed(self, new_segment_ref):
     self.reference = VK(new_segment_ref).getText()
     self.latest_reference = self.reference
     self.ChangeCurrentReference(self.reference)
     self.update_title()
Ejemplo n.º 24
0
 def get_ref_id(self, reference):
     osis_ref = VK(reference).getOSISRef()
     return super(LinkedFrame, self).get_ref_id(osis_ref)
Ejemplo n.º 25
0
 def testValuesAreRight(self):
     self.assertEquals(self._list.passages[0].passage, VK("gen 2:3"))
     self.assertEquals(self._list.passages[2].passage, VK("gen 2:7"))
Ejemplo n.º 26
0
class Book(object):
    is_verse_keyed = False
    is_dictionary = False
    is_genbook = False
    chapter_view = False
    type = None
    category = None
    categories_to_exclude = ()

    def __init__(self, parent, version=""):
        self.parent = parent
        self.mod = None
        self.observers = observerlist.ObserverList()
        self.cleanup_module = observerlist.ObserverList()
        self.template = VerseTemplate(body="$text")
        self.templatelist = [self.template]
        self.vk = VK()
        self.headings = False
        if self.ModuleExists(version):
            self.SetModule(version)
        else:
            mods = self.GetModuleList()
            if mods:
                self.SetModule(mods[0])
            else:
                dprint(WARNING, "No modules of type", self.type)
                self.SetModule(None)

    def SetModule(self, modname, notify=True):
        """Sets the module to modname"""
        oldmod = self.mod

        # No book at all
        if modname is None:
            self.mod = None

        elif isinstance(modname, SW.Module):
            self.mod = modname

        else:
            # look up the book
            new_mod = self.parent.get_module(modname)
            if not new_mod:
                return False

            self.mod = new_mod

        self.features = None

        if self.mod != oldmod and notify:
            self.observers(self.mod)

        return True

    def ModuleExists(self, modname):
        return modname in self.GetModuleList()

    @property
    def version(self):
        if self.mod:
            return self.mod.Name()

    def GetModuleList(self):
        return sorted([
            name for name, mod in self.parent.modules.iteritems()
            if (mod.Type() == self.type or self.type is None) and (
                not self.category or (self.category and mod.getConfigEntry(
                    "Category") == self.category)) and mod.getConfigEntry(
                        "Category") not in self.categories_to_exclude
        ],
                      key=lambda name: name.lower())

    def GetModules(self):
        return sorted([
            mod for name, mod in self.parent.modules.iteritems()
            if (mod.Type() == self.type or self.type is None) and (
                not self.category or (self.category and mod.getConfigEntry(
                    "Category") == self.category)) and mod.getConfigEntry(
                        "Category") not in self.categories_to_exclude
        ],
                      key=lambda mod: mod.Name().lower())

    @staticmethod
    def get_template_options():
        items = {
            "$": _("A $ sign"),
            "range": _("The range of verses"),
            "version": _("The version this is taken from"),
            "description": _("A description of the version"),
        }

        body_items = {
            "text": _("The text of a verse"),
            "versenumber": _("The verse number"),
            "reference": _("The reference for each verse"),
            "bookname": _("The name of the current book"),
            "bookabbrev": _("A shorter abbreviation of the book name"),
            "chapternumber": _("The number of the chapter in the book")
        }

        heading_items = {"heading": _("The text of the heading")}

        body_items.update(items)
        heading_items.update(body_items)

        return dict(body=body_items,
                    headings=heading_items,
                    header=items,
                    footer=items)

    def GetReference(self,
                     ref,
                     specialref="",
                     specialtemplate=None,
                     context="",
                     max_verses=177,
                     raw=False,
                     stripped=False,
                     template=None,
                     display_tags=None,
                     exclude_topic_tag=None,
                     end_ref=None,
                     headings=False,
                     verselist=None,
                     remove_extra_whitespace=False):
        """GetReference gets a reference from a Book.
		
		specialref is a ref (string) which will be specially formatted 
		according to specialtemplate.

		exclude_topic_tag: If this is not None, then it is a topic that
		should not have a tag generated, because it is obvious from the
		context (for example, the topic window for that topic).
		"""
        #only for bible keyed books
        if not self.mod:
            return None

        raw = raw or display_options.options["raw"]

        if template is None and self.templatelist:
            template = self.templatelist[-1]
        if context:
            lastverse = context
        else:
            lastverse = ""

        if display_tags is None:
            # if we don't have tags in, don't calculate them as it can be
            # expensive
            if "$tags" not in template.body.template:
                display_tags = False
            else:
                display_tags = passage_list.settings.display_tags

        assert not (verselist and end_ref), \
         "No end ref with a listkey!!!"

        if end_ref:
            ref += " - " + end_ref

        old_headings = self.vk.Headings(headings)

        if not verselist:
            verselist = self.vk.ParseVerseList(to_str(ref), to_str(lastverse),
                                               True)

        # if they pass in a verselist, they can also pass in the ref they
        # would like to go along with it. This can be useful if it also
        # includes headings that shouldn't be seen
        rangetext = GetBestRange(ref,
                                 context=context,
                                 userInput=False,
                                 userOutput=True,
                                 headings=headings)

        internal_rangetext = GetBestRange(ref,
                                          context=context,
                                          headings=headings)

        if rangetext == "":
            self.vk.Headings(old_headings)
            #if invalid reference, return empty string
            return u""

        if specialref:
            specialref = GetVerseStr(specialref)

        description = to_unicode(self.mod.Description(), self.mod)
        d = dict(range=rangetext,
                 internal_range=internal_rangetext,
                 version=self.mod.Name(),
                 description=description)

        text = template.header.safe_substitute(d)
        verses = []

        for body_dict, headings in self.GetReference_yield(
                verselist,
                max_verses,
                raw,
                stripped,
                exclude_topic_tag=exclude_topic_tag,
                display_tags=display_tags,
        ):
            # if we have exceeded the verse limit, body_dict will be None
            if body_dict is None:
                verses.append(config.MAX_VERSES_EXCEEDED() % max_verses)
                break

            body_dict.update(d)

            t = template

            if specialref == body_dict["internal_reference"]:
                t = specialtemplate

            verse = t.preverse.safe_substitute(body_dict)

            for heading_dict in headings:
                verse += t.headings.safe_substitute(heading_dict)

            verse += t.body.safe_substitute(body_dict)

            verses.append(verse)

        self.vk.Headings(old_headings)

        text += template.finalize(u''.join(verses))
        text += self.end_of_render
        text += template.footer.safe_substitute(d)
        return text

    def GetReference_yield(self,
                           verselist,
                           max_verses=177,
                           raw=False,
                           stripped=False,
                           module=None,
                           exclude_topic_tag=None,
                           display_tags=True,
                           skip_linked_verses=True):
        """GetReference_yield: 
			yield the body dictionary and headings dictinoary
			for each reference.

		Preconditions:
			one of module or self.mod is not None
			verselist is valid"""
        #only for bible keyed books
        verselist.setPosition(TOP)
        verselist.Persist(1)
        u_vk = pysw.UserVK()
        u_vk.Headings(1)
        versekey = SW.VerseKey()
        versekey.Headings(1)
        mod = module or self.mod
        old_mod_skiplinks = mod.getSkipConsecutiveLinks()
        mod.setSkipConsecutiveLinks(True)
        mod.SetKey(verselist)
        verses_left = max_verses

        render_text, render_start, render_end = self.get_rendertext(mod)
        if render_start: render_start()

        try:
            incrementer = mod if skip_linked_verses else verselist
            while not self.has_error(incrementer):
                if verses_left == 0:
                    yield None, None
                    break

                if not skip_linked_verses:
                    mod.SetKey(verselist)
                key = mod.getKey()
                #versekey = VK.castTo(key)
                versekey.setText(key.getText())
                #if(self.headings):
                #	versekey.Headings(1)
                osisRef = versekey.getOSISRef()
                internal_reference = versekey.getText()

                rawentry = mod.getRawEntryBuf()
                if skip_linked_verses and not rawentry.length():
                    # don't include empty text; typically this may be at the
                    # start of the chapter or something...
                    incrementer.increment(1)
                    continue

                start_verse = end_verse = versekey.Verse()

                # look forwards and backwards to see what the linked verse
                # number is (e.g. 3-5). Note: currently this won't cross
                # chapter boundaries
                vk = versekey.clone()
                vk = versekey.castTo(vk)
                vk.thisown = True
                vk.Headings(0)
                while (vk.Error() == '\x00'
                       and vk.Chapter() == versekey.Chapter()
                       and mod.isLinked(vk, versekey)):
                    end_verse = vk.Verse()
                    vk.increment(1)

                vk.copyFrom(versekey)
                vk.Headings(0)

                # hopefully we won't see anything backwards, but it is
                # possible (i.e. if we start in the middle of a linked
                # verse
                while (vk.Error() == '\x00'
                       and vk.Chapter() == versekey.Chapter()
                       and mod.isLinked(vk, versekey)):
                    start_verse = vk.Verse()

                    vk.decrement(1)

                if start_verse == end_verse:
                    verse = "%d" % start_verse
                else:
                    verse = "%d-%d" % (start_verse, end_verse)

                u_vk.setText(internal_reference)
                if internal_reference.endswith(":0"):
                    if start_verse != end_verse:
                        print "WARNING: unhandled linked verse with verse 0"

                    if versekey.Chapter() == 0:
                        reference = u_vk.getBookName()
                    else:
                        reference = u_vk.get_book_chapter()

                else:
                    reference = u_vk.get_book_chapter()
                    reference += ":" + verse

                body_dict = dict(
                    # text comes later
                    versenumber=process_digits(verse, userOutput=True),
                    chapternumber=process_digits(str(versekey.Chapter()),
                                                 userOutput=True),
                    booknumber=ord(versekey.Book()),
                    bookabbrev=versekey.getBookAbbrev(),
                    bookname=versekey.getBookName(),
                    reference=reference,
                    internal_reference=internal_reference,
                    osisRef=osisRef,
                )

                # usually RenderText flushes this out, but we haven't called
                # that yet - but we definitely don't want extraneous headings
                mod.getEntryAttributesMap().clear()

                # we want to do our pre-verse content first, but we can't
                # without running it through the optionFilter first.
                # we'll then have to run it through again after, otherwise our
                # entryattributes may go walkabout
                if raw: rawentry_str = rawentry.c_str()
                mod.optionFilter(rawentry, versekey)
                if raw: option_filtered = rawentry.c_str()

                headings = self.get_headings(internal_reference, mod)
                #versekey = VK.castTo(key)
                heading_dicts = []
                raw_headings = []
                for heading, canonical in headings:
                    # the new-style pre-verse content lives wrapped up in
                    # <div>'s - it will contain the <title>, but the div will
                    # be stripped out.
                    # the old-style pre-verse content lives in <title>'s,
                    # which will also be stripped out. Unfortunately, it isn't
                    # that easy to tell whether it did have a title, so we
                    # employ a heuristic - if it starts with an <, it is a new
                    # one...
                    nh = heading.startswith("<")
                    if stripped:
                        heading = mod.StripText(heading).decode(
                            "utf8", "replace")
                    else:
                        heading = render_text(heading).decode(
                            "utf8", "replace")

                    if not nh:
                        cls = " canonical" if (canonical
                                               and canonical == "true") else ""
                        heading = '<h2 class="heading%s">%s</h2>\n' % (cls,
                                                                       heading)

                    if raw:
                        raw_headings.append(heading)
                    heading_dict = dict(heading=heading, canonical=canonical)
                    heading_dict.update(body_dict)
                    heading_dicts.append(heading_dict)

                if stripped:
                    text = mod.StripText(rawentry.c_str(),
                                         rawentry.length()).decode(
                                             "utf-8", "replace")

                else:
                    # we can't use rawentry due to a static local buffer in
                    # swmodule.c; breaks gospel harmonies
                    text = (
                        render_text(  #rawentry.c_str(), rawentry.length()
                        ).decode("utf8", "replace"))

                # get our actual text
                if raw:
                    text = self.process_raw(rawentry_str, text, versekey, mod,
                                            raw_headings, option_filtered)

                user_comments = self.get_user_comments(osisRef, versekey)

                # XXX: This needs to be done better than this.  Move into
                # subclass somehow.
                if isinstance(self, Bible) and display_tags:
                    tags = self.insert_tags(osisRef, versekey,
                                            exclude_topic_tag)
                else:
                    tags = ""

                body_dict.update(
                    dict(text=text, tags=tags, usercomments=user_comments))

                yield body_dict, heading_dicts

                incrementer.increment(1)
                verses_left -= 1

        finally:
            mod.setKey(SW.Key())
            mod.setSkipConsecutiveLinks(old_mod_skiplinks)

        self.end_of_render = ""
        if render_end:
            self.end_of_render = render_end()

    def get_user_comments(self, osis_ref, verse_key):
        if not isinstance(self, Bible):
            return u""

        manager = passage_list.get_primary_passage_list_manager()

        comments = u"".join(
            self.get_user_comment_div(passage_entry) for passage_entry in
            manager.get_all_passage_entries_for_verse(verse_key)
            if (self.get_tag_type_to_show(passage_entry) == "usercomment"))
        return u'<span class="usercomment_container" osisRef="%s">%s</span>' % (
            osis_ref, comments)

    def get_user_comment_div(self, passage):
        passage_id = passage.get_id()
        return '<a class="usercomment" href="usercomment://%(passage_id)d" passageEntryId="%(passage_id)d"><sup>&dagger;</sup></a>' % locals(
        )

    def insert_tags(self, osis_ref, verse_key, exclude_topic_tag):
        """Generates and returns all the passage tags for the given verse."""
        manager = passage_list.get_primary_passage_list_manager()
        passage_tags = "".join(
            self.get_passage_topic_div(passage)
            for passage in manager.get_all_passage_entries_for_verse(verse_key)
            if (self.get_tag_type_to_show(passage, exclude_topic_tag) ==
                "passage_tag"))
        return u'<span class="passage_tag_container" osisRef="%s">%s</span>' % (
            osis_ref, passage_tags)

    def get_tag_type_to_show(self, passage, exclude_topic_tag=None):
        topic = passage.parent
        if (topic is not None and topic.parent is not None
                and topic is not exclude_topic_tag):
            if topic.can_display_tag:
                return "passage_tag"
            elif topic is passage_list.get_primary_passage_list_manager(
            ).comments_special_topic:
                return "usercomment"

        return None

    def get_passage_topic_div(self, passage):
        from gui import passage_tag
        topic_text = " > ".join(passage.parent.topic_trail)
        look, colour = passage.parent.resolve_tag_look()
        topic_id = passage.parent.get_id()
        passage_id = passage.get_id()
        return """
			<a href="passagetag://passage/%(topic_id)d/%(passage_id)d"
				class="passage_tag passage_tag_%(colour)d_%(look)d" passageEntryId="%(passage_id)d">
				<div>
					%(topic_text)s
				</div>
			</a>
		""" % locals()

    def get_headings(self, ref, mod=None):
        """Gets an array of the headings for the current verse. Must have just
		called RenderText on the verse you want headings for"""
        mod = mod or self.mod

        heading = SW.Buf("Heading")
        preverse = SW.Buf("Preverse")
        interverse = SW.Buf("Interverse")
        canonical = SW.Buf("canonical")
        headings = []
        heading_types = [preverse, interverse]
        attrmap = mod.getEntryAttributesMap()  #[SW.Buf("Heading")
        if heading in attrmap:
            h = attrmap[heading]
            if preverse in h:
                i = 0
                p = h[preverse]
                while True:
                    is_canonical = "false"
                    i_buf = SW.Buf(str(i))

                    # try to see if this is a canonical heading
                    # unfortunately, if there happens to be a interverse
                    # heading after a canonical heading, it will overwrite it
                    # so we may not get the correct answer. This oughtn't to
                    # matter overly much
                    if i_buf in h:
                        attributes = h[i_buf]
                        if (canonical in attributes
                                and attributes[canonical].c_str() == "true"):
                            is_canonical = "true"

                    if i_buf in p:
                        headings.append((p[i_buf].c_str(), is_canonical))

                    else:
                        break
                    i += 1

                if not headings:
                    dprint(WARNING, "no heading found for", ref)

        return headings

    def GetReferences(self, ref, context="", max_verses=-1):
        """Gets a list of references.
		
		In: ref - list of references
			context: context of first in list
		Out: A list of verses
		"""
        # TODO: If we have a list passed in like this:
        # ref= ['104:6', '8, 10, 105:1', '3'], context = 'PS 104:14'
        # for second item, GetVerseStr will return Psalms 104:8, instead
        # of Psalms 105:1, so the third retrieved will be 104:3, not 105:3
        # Fixes:
        # Make GetVerseStr take last in list, not first as optional parameter
        results = []
        lastref = context
        for j in ref:
            #get text
            results.append(
                self.GetReference(j, context=lastref, max_verses=max_verses))
            # set context for next ref
            lastref = GetVerseStr(j, lastref)

        return results

    def GetFootnoteData(self, mod, passage, number, field):
        if mod != self.mod:
            if not isinstance(mod, SW.Module):
                mod = self.parent.get_module(mod)
                if mod is None:
                    return None

        else:
            mod = self.mod

        vk = SW.Key(passage)
        mod.SetKey(vk)  #set passage
        mod.RenderText()  # force entry attributes to get set
        data = mod.getEntryAttributesMap()[SW.Buf("Footnote")] \
         [SW.Buf(number)][SW.Buf(field)].c_str()

        # put it through the render filter before returning it
        return mod.RenderText(data).decode("utf8", "replace")

    def GetReferenceFromMod(self, mod, ref, max_verses=-1):
        oldmod = self.mod
        if not self.SetModule(mod, notify=False): return None
        try:
            verses = self.GetReference(ref, max_verses=max_verses)
        finally:
            self.SetModule(oldmod, notify=False)

        return verses

    def GetReferencesFromMod(self, mod, ref, context="", max_verses=-1):
        oldmod = self.mod
        if not self.SetModule(mod, notify=False): return None

        try:
            verses = self.GetReferences(ref, context, max_verses=max_verses)
        finally:
            self.SetModule(oldmod, notify=False)

        return verses

    def GetChapter(self,
                   ref,
                   specialref="",
                   specialtemplate=None,
                   context="",
                   raw=False):
        self.vk.setText(to_str(ref, self.mod))

        #get first ref
        text = self.vk.getText()

        match = re.match("([\w\s]+) (\d+):(\d+)", text)
        if match:
            book, chapter, verse = match.group(1, 2, 3)

            # include introductions - book introduction if necessary
            ref = "%s %s" % (book, chapter)
            text = "%s %s:0-%s %s" % (book, chapter, book, chapter)
            vk = SW.VerseKey()
            vk.Headings(1)
            list = vk.ParseVerseList(text, "", True)
            if chapter == "1":
                vk.setText("%s 0:0" % book)
                list.add(vk)
                #text = "%s 0:0-%s %s" % (book, book, chapter)

                if book == "Genesis":
                    vk.Testament(0)
                    list.add(vk)
                    vk.Testament(1)
                    list.add(vk)

                elif book == "Matthew":
                    # set it to 0 first so that we come back to the testament
                    # heading
                    vk.Testament(0)
                    vk.Testament(2)
                    list.add(vk)

                list.sort()

        else:
            dprint(ERROR, "Couldn't parse verse text", text)
            return ""

        return self.GetReference(ref,
                                 specialref,
                                 specialtemplate,
                                 context,
                                 raw=raw,
                                 headings=True,
                                 verselist=list)

    def get_rendertext(self, mod=None):
        """Return the text render function.

		This makes sure that plaintext modules render whitespace properly"""
        module = mod or self.mod
        render_text = module.RenderText

        start = finish = None
        if module.getConfigEntry("SourceType") in (None, "Plaintext"):

            def render_text(*args):
                text = module.RenderText(*args)
                text = cgi.escape(text)
                return '<span class="plaintext">%s</span>' % text

        else:
            if ord(module.Markup()) == SW.FMT_OSIS:
                start = osisparser.p.block_start
                finish = osisparser.p.block_end

        return render_text, start, finish

    def has_feature(self, feature, module=None):
        if module is not None:
            oldmod = self.mod
            try:
                self.SetModule(module, notify=False)
                return self.has_feature(feature)
            finally:
                self.SetModule(oldmod, notify=False)

        if not self.mod:
            return False

        if self.features is None:
            self.features = []
            mod = self.mod

            map = mod.getConfigMap()
            feature_buf = SW.Buf("Feature")
            featureBegin = map.lower_bound(feature_buf)
            featureEnd = map.upper_bound(feature_buf)
            while featureBegin != featureEnd:
                v = featureBegin.value()
                self.features.append(v[1].c_str())

                featureBegin += 1

        return feature in self.features

    def get_cipher_code(self, mod):
        """Return the cipher key for the module.
		This will be empty if locked, non-empty if unlocked and None if not
		enciphered"""
        return mod.getConfigEntry("CipherKey")

    def unlock(self, mod, key):
        assert self.get_cipher_code(mod) != None
        cm = mod.getConfigMap()
        cm[SW.Buf("CipherKey")] = SW.Buf(key)

        mgr = self.get_mgr(mod)
        mgr.setCipherKey(mod.Name(), key)

        conf = self.get_config(mod)
        conf.set(mod.Name(), "CipherKey", key)
        conf.Save()

        # send a refresh through for this book
        # TODO: do this better
        self.observers(self.mod)

        conf = self.get_config(mod)
        if conf.get(mod.Name(), "CipherKey") != key:
            raise FileSaveException(
                _("Couldn't save cipher key. You will have to set it again when you restart"
                  ))

    def has_chapter(self, ref, mod=None):
        assert self.is_verse_keyed, "Calling has_chapter for non-verse keyed module."
        module = mod or self.mod
        if module is None:
            return False

        vk = VK(ref)
        if module.hasEntry(vk):
            return True

        vk.setVerse(1)
        if module.hasEntry(vk):
            return True

        module.setKey(vk)
        try:
            old_mod_skiplinks = module.getSkipConsecutiveLinks()
            module.setSkipConsecutiveLinks(True)
            module.increment()
            next_vk = VK.castTo(module.getKey())
            return (next_vk.Book() == vk.Book() and next_vk.Chapter()
                    == vk.Chapter() and next_vk.Testament()
                    == vk.Testament()) and not self.has_error(module)
        finally:
            module.setSkipConsecutiveLinks(old_mod_skiplinks)

    def get_mgr(self, mod):
        for path, mgr, modules in self.parent.mgrs:
            if mod in [m for name, m in modules]:
                return mgr

        return None

    def get_config(self, mod):
        pp = mod.getConfigEntry("PrefixPath")
        pp += "mods.d/%s.conf" % mod.Name().lower()

        # make sure it exists
        os.stat(pp)

        return SW.Config(pp)

    def process_raw(self,
                    text,
                    rendered_text,
                    key,
                    module,
                    headings=(),
                    option_filtered=""):
        kt = key.getOSISRefRangeText() or key.getText()
        kt = to_unicode(kt, module)
        if headings:
            headings = "<ul class='raw-headings'>%s</ul>" % ('\n'.join(
                "<li>%s</li>" % cgi.escape(heading) for heading in headings))
        else:
            headings = ""

        if option_filtered:
            option_filtered = "<pre class='raw-option-filtered'>%s</pre>" % cgi.escape(
                option_filtered.decode("utf-8", "replace"))
        return u"""
%s
<div class='debug-raw-details' key='%s'>
	<pre class='raw-rendered'>%s</pre>
	%s
	<pre class='raw'>%s</pre>
	%s
</div>""" % (rendered_text, cgi.escape(kt), cgi.escape(rendered_text),
             headings, cgi.escape(text.decode("utf-8",
                                              "replace")), option_filtered)

    @staticmethod
    def has_error(module):
        ERR_OK = chr(0)
        return (module.Error() != ERR_OK)
Ejemplo n.º 27
0
 def testVersesInSubtopicsShouldBeContainedRecursively(self):
     self.assert_(self._list.contains_verse(VK("ex 2:2"), recursive=True))
     self.assert_(self._list.contains_verse(VK("num 3:5"), recursive=True))
Ejemplo n.º 28
0
	def replace_bible_links(match):
		ref = match.group(1)
		#print "Replacing bible link", ref
		vk = VK(ref)
		
		return "href='book_%s.html#%s_start'" % (vk.getOSISBookName(), vk.getOSISRef())
Ejemplo n.º 29
0
def get_book(sword_book, bible_book, verse_per_line=False):
    print "fetching", bible_book, "from", sword_book
    bookname = str(bible_book)
    chapter_bookname = book_fix(bookname)

    osis_bookname = VK(bookname).getOSISBookName()
    filename = "book_%s.html" % osis_bookname

    preverse = '<span id="${osisRef}_start" />'

    # templates
    verse_number = u'''<span class="vnumber $numbertype%s"
		   id="${osisRef}_number">
		   $versenumber<span class="post_versenumber_space">&nbsp;</span></span>'''

    # TODO - reinstate  $usercomments $tags after $text?
    body = (u'''%s<span class="zwnj">&zwnj;</span>$text''') % verse_number
    #		<a id="${osisRef}_end" osisRef="$osisRef"></a>''') % verse_number

    bible_template = SmartVerseTemplate(body=body % (''), preverse=preverse)
    bible_template.body.verse_per_line = verse_per_line

    toc = []
    chapters = []
    footnotes = {
        'n': [],
        'x': [],
    }
    footnote_types = {
        'n': "Footnotes",
        'x': "Cross-references",
    }

    for chapter in bible_book.chapters:
        if chapter.chapter_number % 10 == 0:
            print osis_bookname, chapter
            if RESTRICTED:
                break

        chapter_id = "%s_%s_start" % (osis_bookname, chapter)
        chapter_link = '<a class="chapter_link" href="#intro">%s</a>' % chapter_bookname
        toc.append(
            '''<a class="toc_chapter_link" href="#chapter_%s">%s</a>''' %
            (chapter_id, chapter))

        ref = "%s %s" % (osis_bookname, chapter)
        content = sword_book.GetReference(ref,
                                          end_ref=ref,
                                          template=bible_template,
                                          max_verses=-1)
        #		content = re.sub(r'<(/?)h2([^>]*)>', r'<\1h4\2>', content)

        chapter_marker = '<span class="vnumber chapternumber'
        # always a chance
        new_content = content.replace(chapter_marker,
                                      chapter_link + chapter_marker)

        osisRef = "%s.%s.%s" % (osis_bookname, chapter, 1)
        if new_content == content:
            print "No chapter intro link found for %s %s" % (osis_bookname,
                                                             chapter)
            new_content = (chapter_link + (verse_number % '').replace(
                "$numbertype", "chapternumber").replace(
                    "${osisRef}", osisRef).replace("${versenumber}", "%s" %
                                                   (chapter)))

        content = new_content
        expected_start = preverse.replace("${osisRef}", osisRef) + chapter_link
        if not content.startswith(expected_start):
            print "pre-content chapter intro link found for %s %s" % (
                osis_bookname, chapter)
            #print "Sample starter content: " + content[:100]
            content = content.replace(chapter_link, "<br / >" + chapter_link)

            # now take it back out if write after a lg
            q = '<blockquote class="lg" width="0">'
            content = content.replace(q + '<br / >', q)

        # check - did we have a closing or opening <p> last?
        if 0:
            # note, it's only epubcheck which complains about this. kindlegen
            # complains as this support isn't perfect so it sees some unclosed
            # <p> tags
            add_p = True
            for a in re.findall("<(/?)p>", content):
                add_p = not (a)

            if add_p:
                content += '</p>'

        def insert_footnotes(match):
            #print "Inserting footnotes", match
            href = match.group(1)
            url = SW.URL(href.encode("utf8"))
            ftype = url.getParameterValue("type")  #x or n
            value = url.getParameterValue("value")  #number footnote in verse
            if ((not ftype) or (not value)):
                dprint(WARNING, "Not type or value in showNote", href)
                return ""

            module = biblemgr.get_module(url.getParameterValue("module"))
            passage = url.getParameterValue("passage")
            back_ref = VK(passage).getOSISRef()
            user_ref = book_fix(internal_to_user(passage))

            if not passage or not module:
                print "No passage/module?"
                return ""

            id = "footnote_data_%s_%s" % (back_ref, value)
            #print passage, id
            if ftype in ("n", "x"):
                data = sword_book.GetFootnoteData(module, passage, value,
                                                  "body")
                if footnotes[ftype] and footnotes[ftype][-1][0] == back_ref:
                    footnotes_group = footnotes[ftype][-1]
                else:
                    footnotes_group = [
                        back_ref,
                        "<div class='verse_footnotes footnote_%s' id='verse_footnote_%s_%s'>%s for "
                        "<a href='#%s_start'>%s</a>%%s</div>" %
                        (ftype, back_ref, ftype, footnote_types[ftype],
                         back_ref, user_ref)
                    ]

                    footnotes[ftype].append(footnotes_group)

                footnotes_group.append(
                    "<div class='footnote_data' id='%s'><span class='footnote_marker'>%s</span>: %s</div>"
                    % (id, match.group(3), data))
            else:
                print "Footnote type was", ftype

            id = "verse_footnote_%s_%s" % (back_ref, ftype)
            return 'href="#%s"%s' % (id, match.group(2))

        content = re.sub(
            r'href="newbible://content/(passagestudy\.jsp\?action=showNote&type=[nx]&value=\d+&module=\w+&passage=(?:[^"]+))"(>([^<]*)</a>)',
            insert_footnotes, content)

        chapters.append('''
			<div class="chapter" id="chapter_%s">
			<!-- <p> -->
			%s
			</div>
			<hr />
			''' % (chapter_id, content))

    footnotes_html = ''
    for ftype in "nx":
        if footnotes[ftype]:
            footnotes_html += '<div class="book_footnotes"><h3>%s for %s</h3>%s</div>' % (
                footnote_types[ftype], bookname, '<hr />\n'.join(
                    [f[1] % ('\n\t'.join(f[2:])) for f in footnotes[ftype]]))

    html_content = '''<?xml version='1.0' encoding='utf-8'?>
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>%s</title>
    	<link type="text/css" rel="stylesheet" href="bpbible_epub.css" />
	</head>
	<body>
		<div id="intro">
			<h3>%s</h3>
			<div class="book_toc">%s</div>
			<hr style="clear:both" />
			<div style="clear:both">
			Return to <a href="toc.html">Table of Contents</a>
			</div>
		</div>
		<hr class="pagebreak" />
		<div class="chapterview">
		%s
		</div>
		%s
	</body>
</html>
		''' % (bookname, bookname, '\n'.join(toc), '\n'.join(chapters),
         footnotes_html)

    # TODO: sword:// links, any others?
    print "Resolving bible links for", bookname

    def replace_bible_links(match):
        ref = match.group(1)
        #print "Replacing bible link", ref
        vk = VK(ref)

        return "href='book_%s.html#%s_start'" % (vk.getOSISBookName(),
                                                 vk.getOSISRef())

    html_content = re.sub(r'href="bible:([^"]*)"', replace_bible_links,
                          html_content)

    return (
        osis_bookname,
        filename,
        bookname,
        html_content.encode("utf8"),
    )
Ejemplo n.º 30
0
 def testVersesInVerseRangeShouldBeContained(self):
     self.assert_(self._list.contains_verse(VK("gen 2:5")))
     self.assert_(self._list.contains_verse(VK("gen 2:4")))
Ejemplo n.º 31
0
	def get_document(self, path):
		module_name, rest = path.split("/", 1)
		ref, direction = rest.rsplit("/", 1)
		assert direction in ("next", "previous")

		dir = {"next": 1, "previous": -1}[direction]
		book = biblemgr.get_module_book_wrapper(module_name)
		mod = book.mod		
		no_more = False
		if book.is_verse_keyed:
			vk = VK(ref, headings=not book.chapter_view)
			if book.chapter_view:
				vk.chapter += dir
				if vk.Error():
					print "No more in that direction", dir
					no_more = True
				else:
				
					# go back just a little, so that when we go forward on the module
					# we won't overshoot... (at least, that is our plan - we hope it
					# won't be baffled...)
					vk.Verse(vk.Verse() - dir)
					if vk.Error():
						print "VK had an error taking away a verse", dir
	
			if not no_more:
				old_mod_skiplinks = mod.getSkipConsecutiveLinks()
				mod.setSkipConsecutiveLinks(True)
				try:
					vk.Persist(1)
					mod.setKey(vk)
					#print repr(mod.Error())
					mod.increment(dir)

					if mod.Error() != '\x00':
						print "Mod had an error"
						no_more = True
					else:
						if book.chapter_view:
							new_ref = vk.get_chapter_osis_ref()
						else:
							new_ref = vk.getOSISRef()
				finally:
					mod.setKey(SW.Key())
					mod.setSkipConsecutiveLinks(old_mod_skiplinks)
		
		elif book.is_dictionary:
			# XXX: Would using an index rather than a reference (as the XUL code did) be more efficient?
			book.snap_text(ref)
			book.mod.increment(dir)
			if mod.Error() == '\x00' and book.mod.getKey().getText():
				new_ref = to_unicode(mod.getKey().getText(), mod)
			else:
				no_more = True
			
		elif book.is_genbook:
			ref = "/" + ref
			tk = book.GetKey()
			tk.Persist(1)
			assert tk.thisown
			newtk = book.GetKey()
			newtk.thisown = True
			mod.setKey(tk)
			print "Getting next for", ref
			tk.set_text(ref)
			print tk.getText()
			if mod.Error() != '\x00':
				print "Error on initial set?"
			mod.increment(dir)
			if mod.Error() == '\x00' and tk.getText():
				new_ref = to_unicode(tk.getText(), mod)[1:] # trim off the leading /
			else:
				no_more = True
			
			mod.setKey(newtk)
		else:
			print "Book type not handled", module_name
		
		if no_more:
			message = (_("You are at the start of this book.") if dir == -1
				else _("You are at the end of this book."))
			class_name = "book-%s" % ("start" if dir == -1 else "end")
			return '''
			<div class="page_segment" empty="true">
				<div class='no_more_text %(class_name)s'>
					%(message)s
				</div>
			</div>''' % locals()
		
		return '<div class="page_segment">%(content)s%(timer)s</div>' % self._get_document_parts_for_ref(module_name, new_ref, do_current_ref=False)
Ejemplo n.º 32
0
 def testVersesNotInVerseRangeShouldNotBeContained(self):
     self.assert_(not self._list.contains_verse(VK("deut 3:5")))
     self.assert_(
         not self._list.contains_verse(VK("deut 3:5"), recursive=True))
Ejemplo n.º 33
0
    def _get_document_parts_for_ref(self,
                                    module_name,
                                    ref,
                                    do_current_ref=True):
        t = default_timer()

        stylesheets = list(self.bible_stylesheets)
        scripts = self.standard_scripts + self.bible_scripts + [
            "highlight.js", "bpbible_html.js", "contrib/hyphenate.js",
            "columns.js"
        ]

        book = biblemgr.get_module_book_wrapper(module_name)
        assert book, "Module wrapper not found for book " + module_name
        module = book.mod
        if book.chapter_view:
            scripts.append("bpbible_html_chapter_view.js")
            #stylesheets.append("bpbible_chapter_view.css")
            #stylesheets.append("bpbible://content/quotes_skin/")
        else:
            scripts.append("bpbible_html_page_view.js")
            stylesheets.append("bpbible_page_view.css")

        if is_debugging():
            stylesheets.append("bpbible_html_debug.css")

        if book.is_verse_keyed:
            if book.chapter_view:
                if do_current_ref:
                    c = book.GetChapter(ref, ref,
                                        config.current_verse_template)
                else:
                    c = book.GetChapter(ref)

                ref_id = VK(ref).get_chapter_osis_ref()

            else:
                c = book.GetReference(ref, headings=True)
                ref_id = VK(ref).getOSISRef()

        elif book.is_dictionary:
            c = book.GetReference(ref)
            ref_id = ref

        elif book.is_genbook:
            c = book.GetReference(ref)
            ref_id = ref
        else:
            dprint(ERROR, "Book `%s' not found." % module_name)
            c = ''
        c = c.replace("<!P>", "</p><p>")

        clas = ""
        if not c:
            clas = " nocontent"

        lang = module.Lang() if module else "en",
        c = convert_language(c, lang)
        c = '<div class="segment%s" ref_id="%s">%s</div>' % (
            clas, urllib.quote(ref_id.encode("utf8")), c)

        return dict(
            module=module,
            content=c,
            bodyattrs=self._get_body_attrs(module),
            stylesheets=stylesheets,
            scripts=scripts,
            timer="<div class='timer'>Time taken: %.3f (ref_id %s)</div>" %
            (default_timer() - t, ref_id))
Ejemplo n.º 34
0
	def testContainsVerseWorksWithSingleVerse(self):
		self.assert_(self._passage_entry.contains_verse(VK("gen 2:2")))
		self.assert_(not self._passage_entry.contains_verse(VK("gen 2:1")))
Ejemplo n.º 35
0
    def get_document(self, path):
        module_name, rest = path.split("/", 1)
        ref, direction = rest.rsplit("/", 1)
        assert direction in ("next", "previous")

        dir = {"next": 1, "previous": -1}[direction]
        book = biblemgr.get_module_book_wrapper(module_name)
        mod = book.mod
        no_more = False
        if book.is_verse_keyed:
            vk = VK(ref, headings=not book.chapter_view)
            if book.chapter_view:
                vk.chapter += dir
                if vk.Error():
                    print "No more in that direction", dir
                    no_more = True
                else:

                    # go back just a little, so that when we go forward on the module
                    # we won't overshoot... (at least, that is our plan - we hope it
                    # won't be baffled...)
                    vk.Verse(vk.Verse() - dir)
                    if vk.Error():
                        print "VK had an error taking away a verse", dir

            if not no_more:
                old_mod_skiplinks = mod.getSkipConsecutiveLinks()
                mod.setSkipConsecutiveLinks(True)
                try:
                    vk.Persist(1)
                    mod.setKey(vk)
                    #print repr(mod.Error())
                    mod.increment(dir)

                    if mod.Error() != '\x00':
                        print "Mod had an error"
                        no_more = True
                    else:
                        if book.chapter_view:
                            new_ref = vk.get_chapter_osis_ref()
                        else:
                            new_ref = vk.getOSISRef()
                finally:
                    mod.setKey(SW.Key())
                    mod.setSkipConsecutiveLinks(old_mod_skiplinks)

        elif book.is_dictionary:
            # XXX: Would using an index rather than a reference (as the XUL code did) be more efficient?
            book.snap_text(ref)
            book.mod.increment(dir)
            if mod.Error() == '\x00' and book.mod.getKey().getText():
                new_ref = to_unicode(mod.getKey().getText(), mod)
            else:
                no_more = True

        elif book.is_genbook:
            ref = "/" + ref
            tk = book.GetKey()
            tk.Persist(1)
            assert tk.thisown
            newtk = book.GetKey()
            newtk.thisown = True
            mod.setKey(tk)
            print "Getting next for", ref
            tk.set_text(ref)
            print tk.getText()
            if mod.Error() != '\x00':
                print "Error on initial set?"
            mod.increment(dir)
            if mod.Error() == '\x00' and tk.getText():
                new_ref = to_unicode(tk.getText(),
                                     mod)[1:]  # trim off the leading /
            else:
                no_more = True

            mod.setKey(newtk)
        else:
            print "Book type not handled", module_name

        if no_more:
            message = (_("You are at the start of this book.")
                       if dir == -1 else _("You are at the end of this book."))
            class_name = "book-%s" % ("start" if dir == -1 else "end")
            return '''
			<div class="page_segment" empty="true">
				<div class='no_more_text %(class_name)s'>
					%(message)s
				</div>
			</div>''' % locals()

        return '<div class="page_segment">%(content)s%(timer)s</div>' % self._get_document_parts_for_ref(
            module_name, new_ref, do_current_ref=False)
Ejemplo n.º 36
0
    def get_tree_item(self):
        root = self.tree.GetRootItem()

        text = self.GetValue()
        was_book = False
        for book in UserVK.books:
            if ("%s" % book) == text:
                was_book = True
                self.currentverse = book.bookname
                break
        else:
            try:
                # try updating verse based on user text
                # if we fail, just use old text (assuming there is any)
                self.currentverse = GetVerseStr(text,
                                                self.currentverse,
                                                raiseError=True,
                                                userInput=True,
                                                userOutput=False)

            except VerseParsingError:
                if not self.currentverse:
                    return self.tree.GetFirstChild(root)[0]

        verse_key = UserVK(VK(self.currentverse))
        single_chapter_book = verse_key.getChapterMax() == 1

        book, chapter = verse_key.getBookName(), verse_key.Chapter()
        verse = verse_key.Verse()
        chapter = process_digits(str(chapter), userOutput=True)
        verse = process_digits(str(verse), userOutput=True)
        if single_chapter_book:
            chapter = verse

        item, cookie = self.tree.GetFirstChild(root)
        while item:
            if self.tree.GetItemText(item) == book:
                break

            item, cookie = self.tree.GetNextChild(root, cookie)

        assert item, book + " not found!"

        if was_book or (single_chapter_book and not self.with_verses):
            return item

        self.tree.Expand(item)

        item2, cookie = self.tree.GetFirstChild(item)

        while item2:
            data = unicode(self.get_data(item2))
            if data == chapter:
                # if : isn't in there, we take it as a chapter reference
                if not self.with_verses or  ":" not in text \
                  or single_chapter_book:
                    return item2
                else:
                    break

            item2, cookie = self.tree.GetNextChild(item, cookie)

        assert item2, "Chapter '%s' not found in %s" % (chapter, book)
        assert not single_chapter_book, "Single chapter books, but chapterMax == 1?!?"

        self.tree.Expand(item2)

        item3, cookie = self.tree.GetFirstChild(item2)

        while item3:
            data = unicode(self.get_data(item3))
            if data == verse:
                return item3

            item3, cookie = self.tree.GetNextChild(item2, cookie)

        assert item3, "Verse '%s' not found in %s %s" % (verse, book, chapter)
Ejemplo n.º 37
0
 def chapter_move(self, number):
     vk = VK(self.reference)
     vk.chapter += number
     if not vk.Error():
         self.notify(vk.text, source=events.CHAPTER_MOVE)
Ejemplo n.º 38
0
 def get_key(self, module):
     vk = VK((self.bookname, self.bookname))
     vk.Headings(0)
     vk.setPosition(TOP)
     return vk
Ejemplo n.º 39
0
 def verse_move(self, number):
     vk = VK(self.reference)
     vk += number
     self.notify(vk.text, source=events.VERSE_MOVE)
Ejemplo n.º 40
0
class GuessVerseFrame(xrcGuessVerseFrame):
	def __init__(self, parent):
		super(GuessVerseFrame, self).__init__(parent)
		
		# This call makes sure that the reference display frame is loaded
		# with an empty reference.
		# This means that all future references displayed will be shown with
		# Javascript, and so there won't be any focus bugs.
		self.reference_frame.RefreshUI()

		self.reference_frame.template = VerseTemplate(
			body=u"$text", headings=""
		)

		self.show_answer_button.Bind(wx.EVT_BUTTON, self.on_show_answer)
		self.guess_button.Bind(wx.EVT_BUTTON, self.on_guess)
		self.books.AppendItems([unicode(book) for book in UserVK.books])
		self.books.Selection = 0
		self.new_guess()
		self.Children[0].Fit()
		self.Fit()
	
	def new_guess(self):
		self.key = None
		while not self.key or not biblemgr.bible.mod.hasEntry(self.key):
			randomnum = random.randint(1, 31102)
			self.key = VK("Gen 1:%d" % randomnum)
		self.user_key = UserVK(self.key)
		self.reference_frame.SetReference(self.key.getText())

	def on_show_answer(self, event):
		Tooltip.do_not_show_tooltip = True
		wx.MessageBox(
			_("The verse was %s") % UserVK(self.key).getText(),
			parent=self
		)
		Tooltip.do_not_show_tooltip = False

		self.new_guess()

	def on_guess(self, event):
		# XXX: We can't use the currently focused window trick to prevent
		# tooltips from grabbing focus when using a MessageBox, since it
		# gives the focused window as None.  Instead, we use this hack.
		Tooltip.do_not_show_tooltip = True
		won = self.user_key.getBookName() == self.books.StringSelection
		if won:
			wx.MessageBox(
				_("Yes, you are right. The verse was %s")
					% UserVK(self.key).getText(),
				_("Correct"),
				parent=self
			)

			self.new_guess()
		else:
			wx.MessageBox(
				_("No, you are wrong. Try again."), 
				_("Try again."),
				parent=self,
				style=wx.OK | wx.ICON_ERROR,
			)
		Tooltip.do_not_show_tooltip = False
Ejemplo n.º 41
0
class Book(object):
	is_verse_keyed = False
	is_dictionary = False
	is_genbook = False
	chapter_view = False
	type = None
	category = None
	categories_to_exclude = ()
	def __init__(self, parent, version = ""):
		self.parent = parent
		self.mod = None
		self.observers = observerlist.ObserverList()
		self.cleanup_module = observerlist.ObserverList()
		self.template = VerseTemplate(body = "$text")
		self.templatelist = [self.template]
		self.vk = VK()
		self.headings = False
		if self.ModuleExists(version):
			self.SetModule(version)
		else:
			mods = self.GetModuleList()
			if mods:
				self.SetModule(mods[0])
			else:
				dprint(WARNING, "No modules of type", self.type)
				self.SetModule(None)

	def SetModule(self, modname, notify=True):
		"""Sets the module to modname"""
		oldmod = self.mod

		# No book at all
		if modname is None:
			self.mod = None

		elif isinstance(modname, SW.Module):
			self.mod = modname
		
		else:
			# look up the book
			new_mod = self.parent.get_module(modname)	
			if not new_mod:
				return False
			
			self.mod = new_mod
				
		self.features = None
		
		if self.mod != oldmod and notify:
			self.observers(self.mod)

		return True
	
	def ModuleExists(self, modname):
		return modname in self.GetModuleList()

	@property
	def version(self):
		if self.mod:
			return self.mod.Name()

	def GetModuleList(self):
		return sorted([name for name, mod in self.parent.modules.iteritems()
				if (mod.Type() == self.type or self.type is None) and
				(not self.category or (self.category and mod.getConfigEntry("Category") == self.category)) and
				mod.getConfigEntry("Category") not in self.categories_to_exclude], 
				key=lambda name:name.lower())
	
	def GetModules(self):
		return sorted([mod for name, mod in self.parent.modules.iteritems()
				if (mod.Type() == self.type or self.type is None) and
				(not self.category or (self.category and mod.getConfigEntry("Category") == self.category)) and
				mod.getConfigEntry("Category") not in self.categories_to_exclude], 
				key = lambda mod: mod.Name().lower())
	
	@staticmethod
	def get_template_options():
		items = {
			"$":			_("A $ sign"), 
			"range":		_("The range of verses"), 
			"version":		_("The version this is taken from"),
			"description":	_("A description of the version"),
		}

		body_items = {			
			"text":			_("The text of a verse"),
			"versenumber":	_("The verse number"),
			"reference": 	_("The reference for each verse"),
			"bookname":		_("The name of the current book"),
			"bookabbrev":	_("A shorter abbreviation of the book name"),
			"chapternumber":_("The number of the chapter in the book")
		}

		heading_items = {
			"heading":		_("The text of the heading")
		}

		body_items.update(items)
		heading_items.update(body_items)

		return dict(body=body_items, headings=heading_items, 
					header=items, footer=items)

	
	def GetReference(self, ref, specialref="",
			specialtemplate=None, context="", max_verses=177, raw=False,
			stripped=False, template=None, display_tags=None,
			exclude_topic_tag=None, end_ref=None, headings=False,
			verselist=None, remove_extra_whitespace=False):
		"""GetReference gets a reference from a Book.
		
		specialref is a ref (string) which will be specially formatted 
		according to specialtemplate.

		exclude_topic_tag: If this is not None, then it is a topic that
		should not have a tag generated, because it is obvious from the
		context (for example, the topic window for that topic).
		"""
		#only for bible keyed books
		if not self.mod:
			return None

		raw = raw or display_options.options["raw"]
		
		if template is None and self.templatelist:
			template = self.templatelist[-1]
		if context:
			lastverse = context
		else:
			lastverse = ""

		if display_tags is None:
			# if we don't have tags in, don't calculate them as it can be
			# expensive
			if "$tags" not in template.body.template:
				display_tags = False
			else:
				display_tags = passage_list.settings.display_tags
	
		assert not (verselist and end_ref), \
			"No end ref with a listkey!!!"

		if end_ref:
			ref += " - " + end_ref

		old_headings = self.vk.Headings(headings)

		if not verselist:
			verselist = self.vk.ParseVerseList(to_str(ref), to_str(lastverse), True)

		# if they pass in a verselist, they can also pass in the ref they
		# would like to go along with it. This can be useful if it also
		# includes headings that shouldn't be seen
		rangetext = GetBestRange(ref, context=context,
			userInput=False, userOutput=True, headings=headings)

		internal_rangetext = GetBestRange(ref, context=context, headings=headings)
			
		if rangetext == "":
			self.vk.Headings(old_headings)
			#if invalid reference, return empty string
			return u""
			
		
		if specialref:
			specialref = GetVerseStr(specialref)
		
		description = to_unicode(self.mod.Description(), self.mod)
		d = dict(range=rangetext, 
				 internal_range=internal_rangetext,
				 version=self.mod.Name(), 
				 description=description)

		text = template.header.safe_substitute(d)
		verses = []
		
		
		for body_dict, headings in self.GetReference_yield(
			verselist, max_verses, raw, stripped,
			exclude_topic_tag=exclude_topic_tag,
			display_tags=display_tags,
		):
			# if we have exceeded the verse limit, body_dict will be None
			if body_dict is None:
				verses.append(config.MAX_VERSES_EXCEEDED() % max_verses)
				break

			body_dict.update(d)
			
			t = template

			if specialref == body_dict["internal_reference"]:
				t = specialtemplate

			verse = t.preverse.safe_substitute(body_dict)

			for heading_dict in headings:
				verse += t.headings.safe_substitute(heading_dict)
			
			verse += t.body.safe_substitute(body_dict)

			verses.append(verse)
		
		self.vk.Headings(old_headings)

		text += template.finalize(u''.join(verses))
		text += self.end_of_render
		text += template.footer.safe_substitute(d)
		return text
		
			
	def GetReference_yield(self, verselist, max_verses=177, 
			raw=False, stripped=False, module=None, exclude_topic_tag=None,
			display_tags=True, skip_linked_verses=True):
		"""GetReference_yield: 
			yield the body dictionary and headings dictinoary
			for each reference.

		Preconditions:
			one of module or self.mod is not None
			verselist is valid"""
		#only for bible keyed books
		verselist.setPosition(TOP)
		verselist.Persist(1)
		u_vk = pysw.UserVK()
		u_vk.Headings(1)
		versekey = SW.VerseKey()
		versekey.Headings(1)
		mod = module or self.mod
		old_mod_skiplinks = mod.getSkipConsecutiveLinks()
		mod.setSkipConsecutiveLinks(True)
		mod.SetKey(verselist)
		verses_left = max_verses

		render_text, render_start, render_end = self.get_rendertext(mod)
		if render_start: render_start()

		try:
			incrementer = mod if skip_linked_verses else verselist
			while not self.has_error(incrementer):
				if verses_left == 0:
					yield None, None
					break
				
				if not skip_linked_verses:
					mod.SetKey(verselist)
				key = mod.getKey()
				#versekey = VK.castTo(key)
				versekey.setText(key.getText())
				#if(self.headings):
				#	versekey.Headings(1)
				osisRef = versekey.getOSISRef()
				internal_reference = versekey.getText()
				
				rawentry = mod.getRawEntryBuf()
				if skip_linked_verses and not rawentry.length():
					# don't include empty text; typically this may be at the
					# start of the chapter or something...
					incrementer.increment(1)
					continue

				start_verse = end_verse = versekey.Verse()
				
				# look forwards and backwards to see what the linked verse
				# number is (e.g. 3-5). Note: currently this won't cross
				# chapter boundaries
				vk = versekey.clone()
				vk = versekey.castTo(vk)
				vk.thisown=True
				vk.Headings(0)
				while(vk.Error() == '\x00' 
					and vk.Chapter() == versekey.Chapter() 
					and mod.isLinked(vk, versekey)):
					end_verse = vk.Verse()
					vk.increment(1)
				
				vk.copyFrom(versekey)
				vk.Headings(0)

				# hopefully we won't see anything backwards, but it is
				# possible (i.e. if we start in the middle of a linked
				# verse
				while(vk.Error() == '\x00'
					and vk.Chapter() == versekey.Chapter() 
					and mod.isLinked(vk, versekey)):				
					start_verse = vk.Verse()

					vk.decrement(1)
				
				if start_verse == end_verse:
					verse = "%d" % start_verse
				else:
					verse = "%d-%d" % (start_verse, end_verse)
				
				u_vk.setText(internal_reference)				
				if internal_reference.endswith(":0"):
					if start_verse != end_verse:
						print "WARNING: unhandled linked verse with verse 0"
						
					if versekey.Chapter() == 0:
						reference = u_vk.getBookName()
					else:
						reference = u_vk.get_book_chapter()

				else:
					reference = u_vk.get_book_chapter()
					reference += ":" + verse
					
				body_dict = dict(
					# text comes later
					versenumber = process_digits(verse,
						userOutput=True), 
					chapternumber = process_digits(
						str(versekey.Chapter()),
						userOutput=True),
					booknumber = ord(versekey.Book()),
					bookabbrev = versekey.getBookAbbrev(),
					bookname = versekey.getBookName(),
					reference = reference,
					internal_reference = internal_reference,
					osisRef = osisRef,
				)	
				
				# usually RenderText flushes this out, but we haven't called
				# that yet - but we definitely don't want extraneous headings
				mod.getEntryAttributesMap().clear()

				# we want to do our pre-verse content first, but we can't
				# without running it through the optionFilter first.
				# we'll then have to run it through again after, otherwise our
				# entryattributes may go walkabout
				if raw: rawentry_str = rawentry.c_str()
				mod.optionFilter(rawentry, versekey)
				if raw: option_filtered = rawentry.c_str()
				
				headings = self.get_headings(internal_reference, mod)
				#versekey = VK.castTo(key)
				heading_dicts = []
				raw_headings = []
				for heading, canonical in headings:
					# the new-style pre-verse content lives wrapped up in
					# <div>'s - it will contain the <title>, but the div will
					# be stripped out.
					# the old-style pre-verse content lives in <title>'s,
					# which will also be stripped out. Unfortunately, it isn't
					# that easy to tell whether it did have a title, so we
					# employ a heuristic - if it starts with an <, it is a new
					# one...
					nh = heading.startswith("<")
					if stripped:
						heading = mod.StripText(heading).decode(
							"utf8",
							"replace"
						)
					else:
						heading = render_text(heading).decode("utf8", "replace")

					if not nh:
						cls = " canonical" if (canonical and canonical == "true") else ""
						heading = '<h2 class="heading%s">%s</h2>\n' % (cls, heading)

					if raw:
						raw_headings.append(heading)
					heading_dict = dict(heading=heading, canonical=canonical)
					heading_dict.update(body_dict)
					heading_dicts.append(heading_dict)
					



				
				if stripped:
					text = mod.StripText(rawentry.c_str(), rawentry.length()).decode("utf-8", "replace")			

				else:
					# we can't use rawentry due to a static local buffer in
					# swmodule.c; breaks gospel harmonies
					text = (render_text(#rawentry.c_str(), rawentry.length()
									   ).decode("utf8", "replace"))
				
				# get our actual text
				if raw:
					text = self.process_raw(rawentry_str, text, versekey, mod,
						raw_headings, option_filtered)

				user_comments = self.get_user_comments(osisRef, versekey)

				# XXX: This needs to be done better than this.  Move into
				# subclass somehow.
				if isinstance(self, Bible) and display_tags:
					tags = self.insert_tags(osisRef, versekey, exclude_topic_tag)
				else:
					tags = ""
				
				body_dict.update(dict(text=text,
									  tags=tags,
									  usercomments=user_comments))

						  
				yield body_dict, heading_dicts

				incrementer.increment(1)
				verses_left -= 1

		finally:
			mod.setKey(SW.Key())
			mod.setSkipConsecutiveLinks(old_mod_skiplinks)
		
		self.end_of_render = ""
		if render_end:
			self.end_of_render = render_end()

	def get_user_comments(self, osis_ref, verse_key):
		if not isinstance(self, Bible):
			return u""

		manager = passage_list.get_primary_passage_list_manager()

		comments = u"".join(
			self.get_user_comment_div(passage_entry)
			for passage_entry in manager.get_all_passage_entries_for_verse(verse_key)
			if (self.get_tag_type_to_show(passage_entry) == "usercomment")
		)
		return u'<span class="usercomment_container" osisRef="%s">%s</span>' % (osis_ref, comments)

	def get_user_comment_div(self, passage):
		passage_id = passage.get_id()
		return '<a class="usercomment" href="usercomment://%(passage_id)d" passageEntryId="%(passage_id)d"><sup>&dagger;</sup></a>' % locals()
	
	def insert_tags(self, osis_ref, verse_key, exclude_topic_tag):
		"""Generates and returns all the passage tags for the given verse."""
		manager = passage_list.get_primary_passage_list_manager()
		passage_tags = "".join(
			self.get_passage_topic_div(passage)
			for passage in manager.get_all_passage_entries_for_verse(verse_key)
			if (self.get_tag_type_to_show(passage, exclude_topic_tag) == "passage_tag")
		)
		return u'<span class="passage_tag_container" osisRef="%s">%s</span>' % (osis_ref, passage_tags)

	def get_tag_type_to_show(self, passage, exclude_topic_tag=None):
		topic = passage.parent
		if (topic is not None
				and topic.parent is not None
				and topic is not exclude_topic_tag):
			if topic.can_display_tag:
				return "passage_tag"
			elif topic is passage_list.get_primary_passage_list_manager().comments_special_topic:
				return "usercomment"

		return None

	def get_passage_topic_div(self, passage):
		from gui import passage_tag
		topic_text = " > ".join(passage.parent.topic_trail)
		look, colour = passage.parent.resolve_tag_look()
		topic_id = passage.parent.get_id()
		passage_id = passage.get_id()
		return """
			<a href="passagetag://passage/%(topic_id)d/%(passage_id)d"
				class="passage_tag passage_tag_%(colour)d_%(look)d" passageEntryId="%(passage_id)d">
				<div>
					%(topic_text)s
				</div>
			</a>
		""" % locals()
	
	def get_headings(self, ref, mod=None):
		"""Gets an array of the headings for the current verse. Must have just
		called RenderText on the verse you want headings for"""
		mod = mod or self.mod

		heading = SW.Buf("Heading")
		preverse = SW.Buf("Preverse")
		interverse = SW.Buf("Interverse")
		canonical = SW.Buf("canonical")
		headings = []
		heading_types = [preverse, interverse]
		attrmap = mod.getEntryAttributesMap()#[SW.Buf("Heading")
		if heading in attrmap:
			h = attrmap[heading]
			if preverse in h:
				i = 0
				p = h[preverse]
				while True:
					is_canonical = "false"
					i_buf = SW.Buf(str(i))

					# try to see if this is a canonical heading
					# unfortunately, if there happens to be a interverse
					# heading after a canonical heading, it will overwrite it
					# so we may not get the correct answer. This oughtn't to
					# matter overly much
					if i_buf in h:
						attributes = h[i_buf]
						if(canonical in attributes and
							attributes[canonical].c_str() == "true"):
							is_canonical = "true"
						
					if i_buf in p:
						headings.append((p[i_buf].c_str(), is_canonical))

					else: break
					i += 1
			
				if not headings:
					dprint(WARNING, "no heading found for", ref)

		return headings
				
	def GetReferences(self, ref, context="", max_verses = -1):
		"""Gets a list of references.
		
		In: ref - list of references
			context: context of first in list
		Out: A list of verses
		"""
		# TODO: If we have a list passed in like this:
		# ref= ['104:6', '8, 10, 105:1', '3'], context = 'PS 104:14'
		# for second item, GetVerseStr will return Psalms 104:8, instead
		# of Psalms 105:1, so the third retrieved will be 104:3, not 105:3
		# Fixes:
		# Make GetVerseStr take last in list, not first as optional parameter
		results = []
		lastref = context
		for j in ref:
			#get text
			results.append(self.GetReference(j, context=lastref, 
							max_verses = max_verses))
			# set context for next ref
			lastref = GetVerseStr(j, lastref)

		return results

	def GetFootnoteData(self, mod, passage, number, field):
		if mod != self.mod:
			if not isinstance(mod, SW.Module):
				mod = self.parent.get_module(mod)
				if mod is None:
					return None

		else:
			mod = self.mod

		vk = SW.Key(passage)
		mod.SetKey(vk) #set passage
		mod.RenderText() # force entry attributes to get set	
		data = mod.getEntryAttributesMap()[SW.Buf("Footnote")] \
			[SW.Buf(number)][SW.Buf(field)].c_str()

		# put it through the render filter before returning it
		return mod.RenderText(data).decode("utf8", "replace")


	def GetReferenceFromMod(self, mod, ref, max_verses = -1):
		oldmod = self.mod
		if not self.SetModule(mod, notify=False): return None
		try:
			verses = self.GetReference(ref, max_verses=max_verses)
		finally:
			self.SetModule(oldmod, notify=False)

		return verses


	def GetReferencesFromMod(self, mod, ref, context="", max_verses=-1):
		oldmod = self.mod
		if not self.SetModule(mod, notify=False): return None
		
		try:
			verses = self.GetReferences(ref, context, max_verses = max_verses)
		finally:
			self.SetModule(oldmod, notify=False)
		
		return verses

	def GetChapter(self, ref, specialref="", specialtemplate = None, 
			context="", raw=False):
		self.vk.setText(to_str(ref, self.mod))
		
		#get first ref
		text = self.vk.getText()

		match = re.match("([\w\s]+) (\d+):(\d+)", text)
		if match:
			book, chapter, verse = match.group(1, 2, 3)

			# include introductions - book introduction if necessary
			ref = "%s %s" % (book, chapter)
			text = "%s %s:0-%s %s" % (book, chapter, book, chapter)
			vk = SW.VerseKey()
			vk.Headings(1)
			list = vk.ParseVerseList(text, "", True)
			if chapter == "1":
				vk.setText("%s 0:0" % book)
				list.add(vk)
				#text = "%s 0:0-%s %s" % (book, book, chapter)
			
				if book == "Genesis":
					vk.Testament(0)
					list.add(vk)
					vk.Testament(1)
					list.add(vk)

				elif book == "Matthew":
					# set it to 0 first so that we come back to the testament
					# heading
					vk.Testament(0)
					vk.Testament(2)
					list.add(vk)

				list.sort()

		else:
			dprint(ERROR, "Couldn't parse verse text", text)
			return ""

		return self.GetReference(ref, specialref, specialtemplate, context,
				raw=raw, headings=True, verselist=list)

	def get_rendertext(self, mod=None):
		"""Return the text render function.

		This makes sure that plaintext modules render whitespace properly"""
		module = mod or self.mod
		render_text = module.RenderText

		start = finish = None
		if module.getConfigEntry("SourceType") in (None, "Plaintext"):
			def render_text(*args):
				text = module.RenderText(*args)
				text = cgi.escape(text)
				return '<span class="plaintext">%s</span>' % text

		else:
			if ord(module.Markup()) == SW.FMT_OSIS:
				start = osisparser.p.block_start
				finish = osisparser.p.block_end


		return render_text, start, finish
	
	def has_feature(self, feature, module=None):
		if module is not None:
			oldmod = self.mod			
			try:
				self.SetModule(module, notify=False)
				return self.has_feature(feature)
			finally:
				self.SetModule(oldmod, notify=False)
			
		if not self.mod:
			return False
		
		if self.features is None:
			self.features = []
			mod = self.mod
		
			map = mod.getConfigMap()
			feature_buf = SW.Buf("Feature")
			featureBegin = map.lower_bound(feature_buf)
			featureEnd = map.upper_bound(feature_buf)
			while featureBegin != featureEnd:
				v = featureBegin.value()
				self.features.append(v[1].c_str())

				featureBegin += 1

		return feature in self.features
	
	def get_cipher_code(self, mod):
		"""Return the cipher key for the module.
		This will be empty if locked, non-empty if unlocked and None if not
		enciphered"""
		return mod.getConfigEntry("CipherKey")

	def unlock(self, mod, key):
		assert self.get_cipher_code(mod) != None
		cm = mod.getConfigMap()
		cm[SW.Buf("CipherKey")] = SW.Buf(key)

		mgr = self.get_mgr(mod)
		mgr.setCipherKey(mod.Name(), key)

		conf = self.get_config(mod)
		conf.set(mod.Name(), "CipherKey", key)
		conf.Save()

		# send a refresh through for this book
		# TODO: do this better
		self.observers(self.mod)
		
		conf = self.get_config(mod)
		if conf.get(mod.Name(), "CipherKey") != key:
			raise FileSaveException(
				_("Couldn't save cipher key. You will have to set it again when you restart"))

	def has_chapter(self, ref, mod=None):
		assert self.is_verse_keyed, "Calling has_chapter for non-verse keyed module."
		module = mod or self.mod
		if module is None:
			return False

		vk = VK(ref)
		if module.hasEntry(vk):
			return True

		vk.setVerse(1)
		if module.hasEntry(vk):
			return True

		module.setKey(vk)
		try:
			old_mod_skiplinks = module.getSkipConsecutiveLinks()
			module.setSkipConsecutiveLinks(True)
			module.increment()
			next_vk = VK.castTo(module.getKey())
			return (next_vk.Book() == vk.Book() and next_vk.Chapter() == vk.Chapter() and next_vk.Testament() == vk.Testament()) and not self.has_error(module)
		finally:
			module.setSkipConsecutiveLinks(old_mod_skiplinks)
		
	def get_mgr(self, mod):
		for path, mgr, modules in self.parent.mgrs:
			if mod in [m for name, m in modules]:
				return mgr

		return None
	
	def get_config(self, mod):
		pp = mod.getConfigEntry("PrefixPath")
		pp += "mods.d/%s.conf" % mod.Name().lower()
		
		# make sure it exists
		os.stat(pp)
		
		return SW.Config(pp)
	
	def process_raw(self, text, rendered_text, key, module, 
		headings=(), option_filtered=""):
		kt = key.getOSISRefRangeText() or key.getText()
		kt = to_unicode(kt, module)
		if headings:
			headings = "<ul class='raw-headings'>%s</ul>" % (
				'\n'.join("<li>%s</li>" % cgi.escape(heading) for heading in headings))
		else:
			headings = ""

		if option_filtered:
			option_filtered = "<pre class='raw-option-filtered'>%s</pre>" % cgi.escape(option_filtered.decode("utf-8", "replace"))
		return u"""
%s
<div class='debug-raw-details' key='%s'>
	<pre class='raw-rendered'>%s</pre>
	%s
	<pre class='raw'>%s</pre>
	%s
</div>""" % (rendered_text, cgi.escape(kt), cgi.escape(rendered_text), headings, cgi.escape(text.decode("utf-8", "replace")), option_filtered)

	@staticmethod
	def has_error(module):
		ERR_OK = chr(0)
		return (module.Error() != ERR_OK)