This commit is contained in:
Kovid Goyal 2011-08-02 23:00:40 -06:00
parent f929fe73df
commit 3693cc6aa8
3 changed files with 79 additions and 21 deletions

View File

@ -33,6 +33,8 @@ class CNCX(object): # {{{
self.strings[item.title] = 0 self.strings[item.title] = 0
if is_periodical: if is_periodical:
self.strings[item.klass] = 0 self.strings[item.klass] = 0
aut, desc = item.author, item.description
self.strings[item.author] = self.strings[item.description] = 0
self.records = [] self.records = []
offset = 0 offset = 0
@ -135,11 +137,10 @@ class IndexEntry(object):
RTAG_MAP = {v:k for k, v in TAG_VALUES.iteritems()} RTAG_MAP = {v:k for k, v in TAG_VALUES.iteritems()}
def __init__(self, offset, label_offset, depth=0, class_offset=None, def __init__(self, offset, label_offset):
control_byte_count=1):
self.offset, self.label_offset = offset, label_offset self.offset, self.label_offset = offset, label_offset
self.depth, self.class_offset = depth, class_offset self.depth, self.class_offset = 0, None
self.control_byte_count = control_byte_count self.control_byte_count = 1
self.length = 0 self.length = 0
self.index = 0 self.index = 0
@ -195,6 +196,16 @@ class IndexEntry(object):
et = self.entry_type et = self.entry_type
buf.write(bytes(bytearray([et]))) buf.write(bytes(bytearray([et])))
if self.control_byte_count == 2:
flags = 0
for attr in ('image_index', 'desc_offset', 'author_offset'):
val = getattr(self, attr)
if val is not None:
tag = self.RTAG_MAP[attr]
bm = TAGX.BITMASKS[tag]
flags |= bm
buf.write(bytes(bytearray([flags])))
for tag in self.tag_nums: for tag in self.tag_nums:
attr = self.RTAG_MAP[tag] attr = self.RTAG_MAP[tag]
val = getattr(self, attr) val = getattr(self, attr)
@ -203,18 +214,34 @@ class IndexEntry(object):
for x in val: for x in val:
buf.write(encint(x)) buf.write(encint(x))
if self.control_byte_count == 2:
for attr in ('image_index', 'desc_offset', 'author_offset'):
val = getattr(self, attr)
if val is not None:
buf.write(encint(val))
ans = buf.getvalue() ans = buf.getvalue()
return ans return ans
class PeriodicalIndexEntry(IndexEntry):
def __init__(self, offset, label_offset, class_offset, depth):
IndexEntry.__init__(offset, label_offset)
self.depth = depth
self.class_offset = class_offset
self.control_byte_count = 2
class SecondaryIndexEntry(IndexEntry): class SecondaryIndexEntry(IndexEntry):
INDEX_MAP = {'author':73, 'caption':72, 'credit':71, 'description':70, INDEX_MAP = {'author':73, 'caption':72, 'credit':71, 'description':70,
'mastheadImage':69} 'mastheadImage':69}
def __init__(self, index): def __init__(self, index):
IndexEntry.__init__(self, index, 0, 0) IndexEntry.__init__(self, index, 0)
tag = self.INDEX_MAP[index] tag = self.INDEX_MAP[index]
# The values for this index entry
self.secondary = [len(self.INDEX_MAP) if tag == min( self.secondary = [len(self.INDEX_MAP) if tag == min(
self.INDEX_MAP.itervalues()) else 0, 0, tag] self.INDEX_MAP.itervalues()) else 0, 0, tag]
@ -399,6 +426,7 @@ class Indexer(object): # {{{
self.text_size = (RECORD_SIZE * (self.number_of_text_records-1) + self.text_size = (RECORD_SIZE * (self.number_of_text_records-1) +
size_of_last_text_record) size_of_last_text_record)
self.masthead_offset = masthead_offset self.masthead_offset = masthead_offset
self.secondary_record_offset = None
self.oeb = oeb self.oeb = oeb
self.log = oeb.log self.log = oeb.log
@ -418,6 +446,17 @@ class Indexer(object): # {{{
self.records = [] self.records = []
if self.is_periodical:
# Ensure all articles have an author and description before
# creating the CNCX
for node in oeb.toc.iterdescendants():
if node.klass == 'article':
aut, desc = node.author, node.description
if not aut: aut = _('Unknown')
if not desc: desc = _('No details available')
node.author, node.description = aut, desc
self.cncx = CNCX(oeb.toc, self.is_periodical) self.cncx = CNCX(oeb.toc, self.is_periodical)
if self.is_periodical: if self.is_periodical:
@ -429,12 +468,17 @@ class Indexer(object): # {{{
self.records.insert(0, self.create_header()) self.records.insert(0, self.create_header())
self.records.extend(self.cncx.records) self.records.extend(self.cncx.records)
if is_periodical:
self.secondary_record_offset = len(self.records)
self.records.append(self.create_header(secondary=True))
self.records.append(self.create_index_record(secondary=True))
self.calculate_trailing_byte_sequences() self.calculate_trailing_byte_sequences()
def create_index_record(self): # {{{ def create_index_record(self, secondary=False): # {{{
header_length = 192 header_length = 192
buf = StringIO() buf = StringIO()
indices = self.indices indices = list(SecondaryIndexEntry.entries) if secondary else self.indices
# Write index entries # Write index entries
offsets = [] offsets = []
@ -474,9 +518,12 @@ class Indexer(object): # {{{
return ans return ans
# }}} # }}}
def create_header(self): # {{{ def create_header(self, secondary=False): # {{{
buf = StringIO() buf = StringIO()
tagx_block = (TAGX().periodical if self.is_periodical else if secondary:
tagx_block = TAGX().secondary
else:
tagx_block = (TAGX().periodical if self.is_periodical else
TAGX().flat_book) TAGX().flat_book)
header_length = 192 header_length = 192
@ -496,7 +543,7 @@ class Indexer(object): # {{{
buf.write(pack(b'>I', 0)) # Filled in later buf.write(pack(b'>I', 0)) # Filled in later
# Number of index records 24-28 # Number of index records 24-28
buf.write(pack(b'>I', len(self.records))) buf.write(pack(b'>I', 1 if secondary else len(self.records)))
# Index Encoding 28-32 # Index Encoding 28-32
buf.write(pack(b'>I', 65001)) # utf-8 buf.write(pack(b'>I', 65001)) # utf-8
@ -505,7 +552,8 @@ class Indexer(object): # {{{
buf.write(b'\xff'*4) buf.write(b'\xff'*4)
# Number of index entries 36-40 # Number of index entries 36-40
buf.write(pack(b'>I', len(self.indices))) indices = list(SecondaryIndexEntry.entries) if secondary else self.indices
buf.write(pack(b'>I', len(indices)))
# ORDT offset 40-44 # ORDT offset 40-44
buf.write(pack(b'>I', 0)) buf.write(pack(b'>I', 0))
@ -517,7 +565,7 @@ class Indexer(object): # {{{
buf.write(pack(b'>I', 0)) buf.write(pack(b'>I', 0))
# Number of CNCX records 52-56 # Number of CNCX records 52-56
buf.write(pack(b'>I', len(self.cncx.records))) buf.write(pack(b'>I', 0 if secondary else len(self.cncx.records)))
# Unknown 56-180 # Unknown 56-180
buf.write(b'\0'*124) buf.write(b'\0'*124)
@ -531,10 +579,12 @@ class Indexer(object): # {{{
# TAGX block # TAGX block
buf.write(tagx_block) buf.write(tagx_block)
num = len(self.indices) num = len(indices)
# The index of the last entry in the NCX # The index of the last entry in the NCX
buf.write(encode_number_as_hex(num-1)) idx = indices[-1].index
buf.write(encode_number_as_hex(idx) if isinstance(idx, int) else
idx.encode('ascii'))
# The number of entries in the NCX # The number of entries in the NCX
buf.write(pack(b'>H', num)) buf.write(pack(b'>H', num))
@ -612,11 +662,12 @@ class Indexer(object): # {{{
id_offsets = self.serializer.id_offsets id_offsets = self.serializer.id_offsets
periodical = IndexEntry(periodical_node_offset, periodical = PeriodicalIndexEntry(periodical_node_offset,
self.cncx[periodical_node.title], self.cncx[periodical_node.title],
class_offset=self.cncx[periodical_node.klass]) self.cncx[periodical_node.klass], 0)
periodical.length = periodical_node_size periodical.length = periodical_node_size
periodical.first_child_index = 1 periodical.first_child_index = 1
periodical.image_index = self.masthead_offset
seen_sec_offsets = set() seen_sec_offsets = set()
seen_art_offsets = set() seen_art_offsets = set()
@ -632,7 +683,7 @@ class Indexer(object): # {{{
if offset in seen_sec_offsets: if offset in seen_sec_offsets:
continue continue
seen_sec_offsets.add(offset) seen_sec_offsets.add(offset)
section = IndexEntry(offset, label, class_offset=klass, depth=1) section = PeriodicalIndexEntry(offset, label, klass, 1)
section.parent_index = 0 section.parent_index = 0
for art in sec: for art in sec:
try: try:
@ -644,9 +695,11 @@ class Indexer(object): # {{{
if offset in seen_art_offsets: if offset in seen_art_offsets:
continue continue
seen_art_offsets.add(offset) seen_art_offsets.add(offset)
article = IndexEntry(offset, label, class_offset=klass, article = PeriodicalIndexEntry(offset, label, klass, 2)
depth=2)
normalized_articles.append(article) normalized_articles.append(article)
article.author_offset = self.cncx[art.author]
article.desc_offset = self.cncx[art.description]
if normalized_articles: if normalized_articles:
normalized_articles.sort(key=lambda x:x.offset) normalized_articles.sort(key=lambda x:x.offset)
normalized_sections.append((section, normalized_articles)) normalized_sections.append((section, normalized_articles))

View File

@ -340,7 +340,12 @@ class MobiWriter(object):
record0.write(b'\xff' * 8) record0.write(b'\xff' * 8)
# 0x20 - 0x23 : Secondary index record # 0x20 - 0x23 : Secondary index record
record0.write(pack(b'>I', 0xffffffff)) sir = 0xffffffff
if (self.primary_index_record_idx is not None and
self.indexer.secondary_record_offset is not None):
sir = (self.primary_index_record_idx +
self.indexer.secondary_record_offset)
record0.write(pack(b'>I', sir))
# 0x24 - 0x3f : Unknown # 0x24 - 0x3f : Unknown
record0.write(b'\xff' * 28) record0.write(b'\xff' * 28)

View File

@ -508,7 +508,7 @@ There are three possible things I know of, that can cause this:
* You are using a Wacom branded mouse. There is an incompatibility between Wacom mice and the graphics toolkit |app| uses. Try using a non-Wacom mouse. * You are using a Wacom branded mouse. There is an incompatibility between Wacom mice and the graphics toolkit |app| uses. Try using a non-Wacom mouse.
* You have invalid files in your fonts folder. If this is the case, start |app| in debug mode as desribed in the previous answer and you will get messages about invalid files in :file:`C:\\Windows\\fonts`. Delete these files and you will be fine. * Sometimes if some software has installed lots of new files in your fonts folder, |app| can crash until it finishes indexing them. Just start |app|, then leave it alone for about 20 minutes, without clicking on anything. After that you should be able to use |app| as normal.
|app| is not starting on OS X? |app| is not starting on OS X?