From 998d7647a3433caec196a33ef8a4293050f16e9e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 22 Jun 2009 09:38:03 -0700 Subject: [PATCH 1/8] Fix #2688 (duplicate tag entries in tag database) and add PDB, RB to internally viewed formats --- src/calibre/gui2/__init__.py | 3 ++- src/calibre/gui2/dialogs/metadata_bulk.py | 28 +++++++++++------------ src/calibre/library/database2.py | 23 ++++++++++++------- 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/src/calibre/gui2/__init__.py b/src/calibre/gui2/__init__.py index a8b6f2d05b..af4ca16eac 100644 --- a/src/calibre/gui2/__init__.py +++ b/src/calibre/gui2/__init__.py @@ -48,7 +48,8 @@ def _config(): help=_('Defaults for conversion to LRF')) c.add_opt('LRF_ebook_viewer_options', default=None, help=_('Options for the LRF ebook viewer')) - c.add_opt('internally_viewed_formats', default=['LRF', 'EPUB', 'LIT', 'MOBI', 'PRC', 'HTML', 'FB2'], + c.add_opt('internally_viewed_formats', default=['LRF', 'EPUB', 'LIT', + 'MOBI', 'PRC', 'HTML', 'FB2', 'PDB', 'RB'], help=_('Formats that are viewed using the internal viewer')) c.add_opt('column_map', default=ALL_COLUMNS, help=_('Columns to be displayed in the book list')) diff --git a/src/calibre/gui2/dialogs/metadata_bulk.py b/src/calibre/gui2/dialogs/metadata_bulk.py index 7d388b077e..9b8810b3a4 100644 --- a/src/calibre/gui2/dialogs/metadata_bulk.py +++ b/src/calibre/gui2/dialogs/metadata_bulk.py @@ -12,7 +12,7 @@ from calibre.gui2.dialogs.tag_editor import TagEditor from calibre.ebooks.metadata import string_to_authors, authors_to_sort_string class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): - + def __init__(self, window, rows, db): QDialog.__init__(self, window) Ui_MetadataBulkDialog.__init__(self) @@ -22,33 +22,33 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.write_series = False self.write_rating = False self.changed = False - QObject.connect(self.button_box, SIGNAL("accepted()"), self.sync) + QObject.connect(self.button_box, SIGNAL("accepted()"), self.sync) QObject.connect(self.rating, SIGNAL('valueChanged(int)'), self.rating_changed) - + all_series = self.db.all_series() - + for i in all_series: id, name = i self.series.addItem(name) - + for f in self.db.all_formats(): self.remove_format.addItem(f) - + self.remove_format.setCurrentIndex(-1) - + self.series.lineEdit().setText('') QObject.connect(self.series, SIGNAL('currentIndexChanged(int)'), self.series_changed) QObject.connect(self.series, SIGNAL('editTextChanged(QString)'), self.series_changed) QObject.connect(self.tag_editor_button, SIGNAL('clicked()'), self.tag_editor) self.exec_() - + def tag_editor(self): d = TagEditor(self, self.db, None) d.exec_() if d.result() == QDialog.Accepted: tag_string = ', '.join(d.tags) self.tags.setText(tag_string) - + def sync(self): for id in self.ids: au = qstring_to_unicode(self.authors.text()) @@ -80,14 +80,14 @@ class MetadataBulkDialog(QDialog, Ui_MetadataBulkDialog): self.db.set_tags(id, tags, append=True, notify=False) if self.write_series: self.db.set_series(id, qstring_to_unicode(self.series.currentText()), notify=False) - + if self.remove_format.currentIndex() > -1: self.db.remove_format(id, unicode(self.remove_format.currentText()), index_is_id=True, notify=False) - + self.changed = True - + def series_changed(self): self.write_series = True - + def rating_changed(self): - self.write_rating = True \ No newline at end of file + self.write_rating = True diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index 0c5013880f..be6b46f690 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -224,6 +224,10 @@ class ResultCache(SearchQueryParser): id = row if row_is_id else self._map_filtered[row] self._data[id][col] = val + def get(self, row, col, row_is_id=False): + id = row if row_is_id else self._map_filtered[row] + return self._data[id][col] + def index(self, id, cache=False): x = self._map if cache else self._map_filtered return x.index(id) @@ -1105,6 +1109,14 @@ class LibraryDatabase2(LibraryDatabase): if notify: self.notify('metadata', [id]) + def get_tags(self, id): + result = self.conn.get( + 'SELECT name FROM tags WHERE id IN (SELECT tag FROM books_tags_link WHERE book=?)', + (id,), all=True) + if not result: + return set([]) + return set([r[0] for r in result]) + def set_tags(self, id, tags, append=False, notify=True): ''' @param tags: list of strings @@ -1113,7 +1125,8 @@ class LibraryDatabase2(LibraryDatabase): if not append: self.conn.execute('DELETE FROM books_tags_link WHERE book=?', (id,)) self.conn.execute('DELETE FROM tags WHERE (SELECT COUNT(id) FROM books_tags_link WHERE tag=tags.id) < 1') - for tag in set(tags): + otags = self.get_tags(id) + for tag in (set(tags)-otags): tag = tag.strip() if not tag: continue @@ -1138,13 +1151,7 @@ class LibraryDatabase2(LibraryDatabase): self.conn.execute('INSERT INTO books_tags_link(book, tag) VALUES (?,?)', (id, tid)) self.conn.commit() - try: - otags = [t.strip() for t in self.data[self.data.row(id)][FIELD_MAP['tags']].split(',')] - except AttributeError: - otags = [] - if not append: - otags = [] - tags = ','.join(otags+tags) + tags = ','.join(self.get_tags(id)) self.data.set(id, FIELD_MAP['tags'], tags, row_is_id=True) if notify: self.notify('metadata', [id]) From 2253d90e4c0140ceefce01e1949fe3f0c5232bd4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 22 Jun 2009 14:55:10 -0700 Subject: [PATCH 2/8] Splitting: Improve logic to preserve links when the split point is a descendant of an anchor --- src/calibre/ebooks/oeb/transforms/split.py | 46 ++++++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/calibre/ebooks/oeb/transforms/split.py b/src/calibre/ebooks/oeb/transforms/split.py index 0cc17bd14f..4b4fb95fb7 100644 --- a/src/calibre/ebooks/oeb/transforms/split.py +++ b/src/calibre/ebooks/oeb/transforms/split.py @@ -16,7 +16,7 @@ from lxml import etree from lxml.cssselect import CSSSelector from calibre.ebooks.oeb.base import OEB_STYLES, XPNSMAP as NAMESPACES, \ - urldefrag, rewrite_links, urlunquote + urldefrag, rewrite_links, urlunquote, barename from calibre.ebooks.epub import rules XPath = functools.partial(_XPath, namespaces=NAMESPACES) @@ -46,9 +46,10 @@ class Split(object): if self.page_breaks_xpath is not None: self.page_break_selectors = [(XPath(self.page_breaks_xpath), False)] - def __call__(self, oeb, context): + def __call__(self, oeb, opts): self.oeb = oeb self.log = oeb.log + self.opts = opts self.map = {} for item in list(self.oeb.manifest.items): if item.spine_position is not None and etree.iselement(item.data): @@ -62,7 +63,7 @@ class Split(object): page_breaks, page_break_ids = self.find_page_breaks(item) splitter = FlowSplitter(item, page_breaks, page_break_ids, - self.max_flow_size, self.oeb) + self.max_flow_size, self.oeb, self.opts) if splitter.was_split: am = splitter.anchor_map self.map[item.href] = collections.defaultdict( @@ -153,9 +154,11 @@ class Split(object): class FlowSplitter(object): 'The actual splitting logic' - def __init__(self, item, page_breaks, page_break_ids, max_flow_size, oeb): + def __init__(self, item, page_breaks, page_break_ids, max_flow_size, oeb, + opts): self.item = item self.oeb = oeb + self.opts = opts self.log = oeb.log self.page_breaks = page_breaks self.page_break_ids = page_break_ids @@ -221,6 +224,34 @@ class FlowSplitter(object): return None return body[0] + def adjust_split_point(self, root, path): + ''' + Move the split point up its ancestor chain if it has no textual content + before it. This handles the common case: +

Chapter 1

...
with a page break on the + h2. + ''' + sp = root.xpath(path)[0] + while True: + parent = sp.getparent() + if barename(parent.tag) in ('body', 'html'): + break + if parent.text and parent.text.strip(): + break + if parent.index(sp) > 0: + break + sp = parent + + npath = sp.getroottree().getpath(sp) + + if self.opts.verbose > 3 and npath != path: + self.log.debug('\t\t\tMoved split point %s to %s'%(path, npath)) + + + return npath + + + def do_split(self, tree, split_point, before): ''' Split ``tree`` into a *before* and *after* tree at ``split_point``, @@ -236,9 +267,11 @@ class FlowSplitter(object): root = tree.getroot() root2 = tree2.getroot() body, body2 = map(self.get_body, (root, root2)) + path = self.adjust_split_point(root, path) split_point = root.xpath(path)[0] split_point2 = root2.xpath(path)[0] + def nix_element(elem, top=True): parent = elem.getparent() index = parent.index(elem) @@ -254,9 +287,12 @@ class FlowSplitter(object): if elem is split_point: hit_split_point = True if before: + x = elem.get('id', None) nix_element(elem) + continue if hit_split_point: + x = elem.get('id', None) nix_element(elem) @@ -266,9 +302,11 @@ class FlowSplitter(object): if elem is split_point2: hit_split_point = True if not before: + x = elem.get('id', None) nix_element(elem, top=False) continue if not hit_split_point: + x = elem.get('id', None) nix_element(elem, top=False) return tree, tree2 From 22ec9df720473e045dc78481da8eb2538e3262ca Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 22 Jun 2009 15:26:52 -0700 Subject: [PATCH 3/8] Implement #2679 (Maintain author order for multi-author books) --- src/calibre/library/database2.py | 29 ++++++++++++++ src/calibre/library/sqlite.py | 68 ++++++++++++++++++++------------ 2 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/calibre/library/database2.py b/src/calibre/library/database2.py index be6b46f690..730ca364d5 100644 --- a/src/calibre/library/database2.py +++ b/src/calibre/library/database2.py @@ -561,6 +561,35 @@ class LibraryDatabase2(LibraryDatabase): ) + def upgrade_version_6(self): + 'Show authors in order' + self.conn.executescript(''' + BEGIN TRANSACTION; + DROP VIEW meta; + CREATE VIEW meta AS + SELECT id, title, + (SELECT sortconcat(bal.id, name) FROM books_authors_link AS bal JOIN authors ON(author = authors.id) WHERE book = books.id) authors, + (SELECT name FROM publishers WHERE publishers.id IN (SELECT publisher from books_publishers_link WHERE book=books.id)) publisher, + (SELECT rating FROM ratings WHERE ratings.id IN (SELECT rating from books_ratings_link WHERE book=books.id)) rating, + timestamp, + (SELECT MAX(uncompressed_size) FROM data WHERE book=books.id) size, + (SELECT concat(name) FROM tags WHERE tags.id IN (SELECT tag from books_tags_link WHERE book=books.id)) tags, + (SELECT text FROM comments WHERE book=books.id) comments, + (SELECT name FROM series WHERE series.id IN (SELECT series FROM books_series_link WHERE book=books.id)) series, + series_index, + sort, + author_sort, + (SELECT concat(format) FROM data WHERE data.book=books.id) formats, + isbn, + path, + lccn, + pubdate, + flags + FROM books; + END TRANSACTION; + ''') + + def last_modified(self): ''' Return last modified time as a UTC datetime object''' diff --git a/src/calibre/library/sqlite.py b/src/calibre/library/sqlite.py index 58a1cd8d91..f874796ade 100644 --- a/src/calibre/library/sqlite.py +++ b/src/calibre/library/sqlite.py @@ -40,10 +40,10 @@ def convert_timestamp(val): if tz is not None: h, m = map(int, tz.split(':')) delta = timedelta(minutes=mult*(60*h + m)) - tz = type('CustomTZ', (tzinfo,), {'utcoffset':lambda self, dt:delta, + tz = type('CustomTZ', (tzinfo,), {'utcoffset':lambda self, dt:delta, 'dst':lambda self,dt:timedelta(0)})() - val = datetime(year, month, day, hours, minutes, seconds, microseconds, + val = datetime(year, month, day, hours, minutes, seconds, microseconds, tzinfo=tz) if tz is not None: val = datetime(*(val.utctimetuple()[:6])) @@ -61,11 +61,11 @@ class Concatenate(object): def __init__(self, sep=','): self.sep = sep self.ans = '' - + def step(self, value): if value is not None: self.ans += value + self.sep - + def finalize(self): if not self.ans: return None @@ -73,8 +73,23 @@ class Concatenate(object): return self.ans[:-len(self.sep)] return self.ans +class SortedConcatenate(object): + '''String concatenation aggregator for sqlite, sorted by supplied index''' + def __init__(self, sep=','): + self.sep = sep + self.ans = {} + + def step(self, ndx, value): + if value is not None: + self.ans[ndx] = value + + def finalize(self): + if len(self.ans) == 0: + return None + return self.sep.join(map(self.ans.get, sorted(self.ans.keys()))) + class Connection(sqlite.Connection): - + def get(self, *args, **kw): ans = self.execute(*args) if not kw.get('all', True): @@ -83,12 +98,12 @@ class Connection(sqlite.Connection): ans = [None] return ans[0] return ans.fetchall() - + class DBThread(Thread): - + CLOSE = '-------close---------' - + def __init__(self, path, row_factory): Thread.__init__(self) self.setDaemon(True) @@ -98,14 +113,15 @@ class DBThread(Thread): self.requests = Queue(1) self.results = Queue(1) self.conn = None - + def connect(self): - self.conn = sqlite.connect(self.path, factory=Connection, + self.conn = sqlite.connect(self.path, factory=Connection, detect_types=sqlite.PARSE_DECLTYPES|sqlite.PARSE_COLNAMES) self.conn.row_factory = sqlite.Row if self.row_factory else lambda cursor, row : list(row) self.conn.create_aggregate('concat', 1, Concatenate) + self.conn.create_aggregate('sortconcat', 2, SortedConcatenate) self.conn.create_function('title_sort', 1, title_sort) - + def run(self): try: self.connect() @@ -124,7 +140,7 @@ class DBThread(Thread): self.unhandled_error = (err, traceback.format_exc()) class DatabaseException(Exception): - + def __init__(self, err, tb): tb = '\n\t'.join(('\tRemote'+tb).splitlines()) msg = unicode(err) +'\n' + tb @@ -146,41 +162,41 @@ def proxy(fn): raise DatabaseException(*res) return res return run - + class ConnectionProxy(object): - + def __init__(self, proxy): self.proxy = proxy - + def close(self): if self.proxy.unhandled_error is None: self.proxy.requests.put((self.proxy.CLOSE, [], {})) - + @proxy def get(self, query, all=True): pass - - @proxy + + @proxy def commit(self): pass - + @proxy def execute(self): pass - + @proxy def executemany(self): pass - + @proxy def executescript(self): pass - + @proxy def create_aggregate(self): pass - + @proxy def create_function(self): pass - + @proxy def cursor(self): pass - + def connect(dbpath, row_factory=None): conn = ConnectionProxy(DBThread(dbpath, row_factory)) conn.proxy.start() @@ -188,4 +204,4 @@ def connect(dbpath, row_factory=None): time.sleep(0.01) if conn.proxy.unhandled_error[0] is not None: raise DatabaseException(*conn.proxy.unhandled_error) - return conn \ No newline at end of file + return conn From 032c2b0fdcf7fc22d755b14624ac3b48a991eed6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 23 Jun 2009 07:42:30 -0700 Subject: [PATCH 4/8] Add option to control line length when preprocessing PDF input --- src/calibre/ebooks/conversion/plumber.py | 2 +- src/calibre/ebooks/conversion/preprocess.py | 6 ++++-- src/calibre/ebooks/html/input.py | 5 +++++ src/calibre/ebooks/pdf/input.py | 2 ++ src/calibre/trac/plugins/templates/linux.html | 5 +++++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/calibre/ebooks/conversion/plumber.py b/src/calibre/ebooks/conversion/plumber.py index e9b9051159..678c21f4ab 100644 --- a/src/calibre/ebooks/conversion/plumber.py +++ b/src/calibre/ebooks/conversion/plumber.py @@ -694,7 +694,7 @@ def create_oebbook(log, path_or_stream, opts, input_plugin, reader=None, ''' from calibre.ebooks.oeb.base import OEBBook html_preprocessor = HTMLPreProcessor(input_plugin.preprocess_html, - opts.preprocess_html) + opts.preprocess_html, getattr(opts, 'pdf_line_length', 0.5)) oeb = OEBBook(log, html_preprocessor, pretty_print=opts.pretty_print, input_encoding=encoding) if not populate: diff --git a/src/calibre/ebooks/conversion/preprocess.py b/src/calibre/ebooks/conversion/preprocess.py index a2794d94ec..cad247c48d 100644 --- a/src/calibre/ebooks/conversion/preprocess.py +++ b/src/calibre/ebooks/conversion/preprocess.py @@ -159,9 +159,11 @@ class HTMLPreProcessor(object): (re.compile('<]*?id=subtitle[^><]*?>(.*?)', re.IGNORECASE|re.DOTALL), lambda match : '

%s

'%(match.group(1),)), ] - def __init__(self, input_plugin_preprocess, plugin_preprocess): + def __init__(self, input_plugin_preprocess, plugin_preprocess, + pdf_line_length): self.input_plugin_preprocess = input_plugin_preprocess self.plugin_preprocess = plugin_preprocess + self.pdf_line_length = pdf_line_length def is_baen(self, src): return re.compile(r'
+

Note

+

+ If your kernel is compiled with CONFIG_SYSFS_DEPRECATED device detection may not work. +

+

Dependencies

${app} has the following dependencies (the listed version is the minimum version)

From e6ea2d1e596cb70d21e7131d6db21eb0090a8db6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 23 Jun 2009 08:33:36 -0700 Subject: [PATCH 5/8] Justify MOBI output by default. Fix bug that was causing automatic generation of TOC from links to fail --- src/calibre/ebooks/mobi/output.py | 4 ---- src/calibre/ebooks/oeb/transforms/structure.py | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/calibre/ebooks/mobi/output.py b/src/calibre/ebooks/mobi/output.py index 625bd7ff0a..301e0a5a67 100644 --- a/src/calibre/ebooks/mobi/output.py +++ b/src/calibre/ebooks/mobi/output.py @@ -39,10 +39,6 @@ class MOBIOutput(OutputFormatPlugin): ]) - recommendations = set([ - ('dont_justify', True, OptionRecommendation.HIGH), - ]) - def convert(self, oeb, output_path, input_plugin, opts, log): self.log, self.opts, self.oeb = log, opts, oeb from calibre.ebooks.mobi.writer import PALM_MAX_IMAGE_SIZE, \ diff --git a/src/calibre/ebooks/oeb/transforms/structure.py b/src/calibre/ebooks/oeb/transforms/structure.py index 4e653c212f..468ba61ff0 100644 --- a/src/calibre/ebooks/oeb/transforms/structure.py +++ b/src/calibre/ebooks/oeb/transforms/structure.py @@ -36,8 +36,8 @@ class DetectStructure(object): if self.oeb.toc.count() < 1: if not opts.no_chapters_in_toc and self.detected_chapters: self.create_toc_from_chapters() - if self.oeb.toc.count() < opts.toc_threshold: - self.create_toc_from_links() + if self.oeb.toc.count() < opts.toc_threshold: + self.create_toc_from_links() if self.oeb.toc.count() < 2 and orig_toc.count() > 2: self.oeb.toc = orig_toc else: From 521890f6559890c60052ccc9cff4a49bf67acf6b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 23 Jun 2009 10:34:16 -0700 Subject: [PATCH 6/8] Update DX profile as per information at http://kindleformatting.com/blog/2009/06/kindle-dx-image-test.php#links --- src/calibre/customize/profiles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calibre/customize/profiles.py b/src/calibre/customize/profiles.py index 8434773515..402dd35f45 100644 --- a/src/calibre/customize/profiles.py +++ b/src/calibre/customize/profiles.py @@ -242,9 +242,9 @@ class KindleDXOutput(OutputProfile): description = _('This profile is intended for the Amazon Kindle DX.') # Screen size is a best guess - screen_size = (824, 1200) + screen_size = (744, 1022) dpi = 150.0 - comic_screen_size = (775, 1128) + comic_screen_size = (744, 1022) @classmethod def tags_to_string(cls, tags): From e311bc02a842f1ee4914a662630adeb39bf047a7 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 23 Jun 2009 11:03:55 -0700 Subject: [PATCH 7/8] Implement #2690 (Various Belgian recipes) --- src/calibre/gui2/images/news/gva_be.png | Bin 0 -> 621 bytes src/calibre/gui2/images/news/hln.png | Bin 0 -> 295 bytes src/calibre/gui2/images/news/tijd.png | Bin 0 -> 381 bytes src/calibre/web/feeds/recipes/__init__.py | 1 + .../web/feeds/recipes/recipe_degentenaar.py | 75 ++++++++++++++++++ .../web/feeds/recipes/recipe_gva_be.py | 63 +++++++++++++++ src/calibre/web/feeds/recipes/recipe_hln.py | 52 ++++++++++++ src/calibre/web/feeds/recipes/recipe_tijd.py | 70 ++++++++++++++++ 8 files changed, 261 insertions(+) create mode 100644 src/calibre/gui2/images/news/gva_be.png create mode 100644 src/calibre/gui2/images/news/hln.png create mode 100644 src/calibre/gui2/images/news/tijd.png create mode 100644 src/calibre/web/feeds/recipes/recipe_degentenaar.py create mode 100644 src/calibre/web/feeds/recipes/recipe_gva_be.py create mode 100644 src/calibre/web/feeds/recipes/recipe_hln.py create mode 100644 src/calibre/web/feeds/recipes/recipe_tijd.py diff --git a/src/calibre/gui2/images/news/gva_be.png b/src/calibre/gui2/images/news/gva_be.png new file mode 100644 index 0000000000000000000000000000000000000000..ca753a5bbda65ec3b65a210ac62b352f56ee02d6 GIT binary patch literal 621 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*U87#OE{x;TbdoPK+0ueWre%<+%k-NgJKEpBI<#BTTW8n=IFE(td^>#nuenESp(}eBXbMD=IaOli!j+!Z<^qVW} z{V-bxq%u2T-L5TrKP~cb)X6p8Dx^MdtK|Djp3k~umg;QN_Z8_sl+u6f!uRuUj$E4Z z&*e*{iu!gl%hf)w_PN+Zt7L~tyv|X05FByuyue-!gBwB%Lc?FK)=r90-Db4Ek^in^ z*?OO4;lesO|D3oQgI5ait>Q7sbUE+4j<9oEyjQ`AX)jT!sIjP+o zjH{F+-exE)soZhWdd++(lk2PZyuUbc(KU^#IEBnp|AX1&7@IfDd#^vAwF($rswJ)w zCCNppi6yDJDL{h3$iTo-*T78I$T-B%z{=Fj%EVCDz}(8f;7Gf|LYRi!{FKbJN;D0I fAw~vPhQ?NgMi34D{J(^N8W=oX{an^LB{Ts5KJWJP literal 0 HcmV?d00001 diff --git a/src/calibre/gui2/images/news/hln.png b/src/calibre/gui2/images/news/hln.png new file mode 100644 index 0000000000000000000000000000000000000000..d7824d4ccc1d339ded30047d10438f11c4ebe109 GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*VRoB&T3#}JFt$q5pl8YU(_oB5vy1YWA`xCx|o z{P3BwtD%HBK~M2E!yG*aV@Y)fK6w%5ghuDj1`eBh_%=Ey%s&jXsRTH+c}l3bLUSdyxn0wfrW3=AxF4a{_nj6)0!tW3?UObm4m%&iOz tjgQu&X%Q~loCII{bQf2@E literal 0 HcmV?d00001 diff --git a/src/calibre/gui2/images/news/tijd.png b/src/calibre/gui2/images/news/tijd.png new file mode 100644 index 0000000000000000000000000000000000000000..fd55a4e5adc5e4e6b3777d7e209f5ea408ca7793 GIT binary patch literal 381 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b zK-vS0-A-oPfdtD69Mgd`SU*F|v9*VRoMoOajv*GOlT*UJ{y*=)n6Svjm>CGTdlo9` zA1z4EwG5nP(qt|9&ZegA6_a(bE*lWE&FQe4dz~aG9L5Asdx)=UwHLU@Kd5o8X1Qe8d#Z{S(zB>8kk!d7#wL=SP0XQo1c=IR*9y;FvQ5f b%E;Wx)B>X6zfJC4paup{S3j3^P6 Date: Tue, 23 Jun 2009 12:42:34 -0700 Subject: [PATCH 8/8] MOBI Output: First anchor offset should be just after opening tag instead of just before it --- src/calibre/ebooks/mobi/writer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/calibre/ebooks/mobi/writer.py b/src/calibre/ebooks/mobi/writer.py index 25ecfe7896..07bc713b94 100644 --- a/src/calibre/ebooks/mobi/writer.py +++ b/src/calibre/ebooks/mobi/writer.py @@ -218,8 +218,8 @@ class Serializer(object): def serialize_body(self): buffer = self.buffer - self.anchor_offset = buffer.tell() buffer.write('') + self.anchor_offset = buffer.tell() # CybookG3 'Start Reading' link if 'text' in self.oeb.guide: href = self.oeb.guide['text'].href