Fix #6208 (RTF to EPUB loses hard linebreaks)

This commit is contained in:
Kovid Goyal 2010-07-25 17:34:46 -06:00
commit ca6691887e
5 changed files with 421 additions and 37 deletions

View File

@ -262,7 +262,7 @@
</xsl:if>
<xsl:if test="@line-spacing">
<xsl:text>line-height:</xsl:text>
<xsl:value-of select="@line-height"/>
<xsl:value-of select="@line-spacing"/>
<xsl:text>pt;</xsl:text>
</xsl:if>
<xsl:if test="(@align = 'just')">
@ -412,6 +412,10 @@
<xsl:attribute name="style">page-break-after:always</xsl:attribute>
</xsl:element>
</xsl:template>
<xsl:template match="rtf:hardline-break">
<xsl:element name="br"/>
</xsl:template>
<xsl:template match="rtf:rtf-definition|rtf:font-table|rtf:color-table|rtf:style-table|rtf:page-definition|rtf:list-table|rtf:override-table|rtf:override-list|rtf:list-text"/>

View File

@ -90,8 +90,8 @@ class ParseRtf:
out_file = '',
out_dir = None,
dtd = '',
debug = 0,
deb_dir=None,
#debug = 0, #why? calibre
deb_dir = None,
convert_symbol = None,
convert_wingdings = None,
convert_zapf = None,
@ -132,7 +132,7 @@ class ParseRtf:
self.__dtd_path = dtd
self.__check_file(in_file,"file_to_parse")
self.__char_data = char_data
self.__debug_dir = debug
self.__debug_dir = deb_dir #self.__debug_dir = debug calibre
self.__check_dir(self.__temp_dir)
self.__copy = self.__check_dir(self.__debug_dir)
self.__convert_caps = convert_caps

View File

@ -1,4 +1,4 @@
import sys, os, tempfile
import sys, os, tempfile
from calibre.ebooks.rtf2xml import copy
"""
States.
@ -51,6 +51,7 @@ class Inline:
'tx<ut<__________' : self.__found_text_func,
'mi<mk<inline-fld' : self.__found_text_func,
'text' : self.__found_text_func,
'cw<nu<hard-lineb' : self.__found_text_func, #calibre
'cb<nu<clos-brack' : self.__close_bracket_func,
'mi<mk<par-end___' : self.__end_para_func,
'mi<mk<footnt-ope' : self.__end_para_func,
@ -62,6 +63,7 @@ class Inline:
'tx<hx<__________' : self.__found_text_func,
'tx<ut<__________' : self.__found_text_func,
'text' : self.__found_text_func,
'cw<nu<hard-lineb' : self.__found_text_func, #calibre
'mi<mk<inline-fld' : self.__found_text_func,
'ob<nu<open-brack': self.__found_open_bracket_func,
'mi<mk<par-end___' : self.__end_para_func,
@ -80,32 +82,32 @@ class Inline:
self.__inline_list = self.__body_inline_list
self.__in_para = 0 # not in paragraph
self.__char_dict = {
# character info => ci
'annotation' : 'annotation',
'blue______' : 'blue',
'bold______' : 'bold',
'caps______' : 'caps',
'char-style' : 'character-style',
'dbl-strike' : 'double-strike-through',
'emboss____' : 'emboss',
'engrave___' : 'engrave',
'font-color' : 'font-color',
'font-down_' : 'subscript',
'font-size_' : 'font-size',
'font-style' : 'font-style',
'font-up___' : 'superscript',
'footnot-mk' : 'footnote-marker',
'green_____' : 'green',
'hidden____' : 'hidden',
'italics___' : 'italics',
'outline___' : 'outline',
'red_______' : 'red',
'shadow____' : 'shadow',
'small-caps' : 'small-caps',
'strike-thr' : 'strike-through',
'subscript_' : 'subscript',
'superscrip' : 'superscript',
'underlined' : 'underlined',
# character info => ci
'annotation' : 'annotation',
'blue______' : 'blue',
'bold______' : 'bold',
'caps______' : 'caps',
'char-style' : 'character-style',
'dbl-strike' : 'double-strike-through',
'emboss____' : 'emboss',
'engrave___' : 'engrave',
'font-color' : 'font-color',
'font-down_' : 'subscript',
'font-size_' : 'font-size',
'font-style' : 'font-style',
'font-up___' : 'superscript',
'footnot-mk' : 'footnote-marker',
'green_____' : 'green',
'hidden____' : 'hidden',
'italics___' : 'italics',
'outline___' : 'outline',
'red_______' : 'red',
'shadow____' : 'shadow',
'small-caps' : 'small-caps',
'strike-thr' : 'strike-through',
'subscript_' : 'subscript',
'superscrip' : 'superscript',
'underlined' : 'underlined',
}
self.__caps_list = ['false']
def __set_list_func(self, line):
@ -133,11 +135,13 @@ class Inline:
Returns:
nothing
Logic:
Write if not hardline break
"""
action = self.__default_dict.get(self.__token_info)
if action:
action(line)
self.__write_obj.write(line)
if self.__token_info != 'cw<nu<hard-lineb': #calibre
self.__write_obj.write(line)
def __found_open_bracket_func(self, line):
"""
Requires:
@ -164,7 +168,7 @@ class Inline:
Use the dictionary to get the approriate function.
Always print out the line.
"""
if line[0:2] == 'cw':
if line[0:5] == 'cw<ci': #calibre: bug in original function no diff between cw<ci and cw<pf
self.__handle_control_word(line)
else:
action = self.__after_open_bracket_dict.get(self.__token_info)
@ -247,12 +251,13 @@ class Inline:
Return:
nothing
Logic:
Two cases:
Three cases:
1. in a list. Simply write inline
2. Not in a list
Text can mark the start of a paragraph.
If already in a paragraph, check to see if any groups are waiting
to be added. If so, use another method to write these groups.
3. If not check if hardline break, then write
"""
if self.__place == 'in_list':
self.__write_inline()
@ -261,8 +266,11 @@ class Inline:
self.__in_para = 1
self.__start_para_func(line)
else:
if self.__token_info == 'cw<nu<hard-lineb': #calibre
self.__write_obj.write('mi<tg<empty_____<hardline-break\n')
if self.__groups_in_waiting[0] != 0:
self.__write_inline()
def __write_inline(self):
"""
Required:
@ -279,7 +287,7 @@ class Inline:
Get the keys in each dictionary. If 'font-style' is in the keys,
write a marker tag. (I will use this marker tag later when conerting
hext text to utf8.)
Write a tag for the inline vaues.
Write a tag for the inline values.
"""
if self.__groups_in_waiting[0] != 0:
last_index = -1 * self.__groups_in_waiting[0]

View File

@ -73,7 +73,8 @@ class ProcessTokens:
'backslash' : ('nu', '\\', self.text_func),
'ob' : ('nu', '{', self.text_func),
'cb' : ('nu', '}', self.text_func),
'line' : ('nu', ' ', self.text_func),
'line' : ('nu', 'hard-lineb', self.default_func), #calibre
#'line' : ('nu', ' ', self.text_func), calibre
# paragraph formatting => pf
'page' : ('pf', 'page-break', self.default_func),
'par' : ('pf', 'par-end___', self.default_func),

View File

@ -2462,7 +2462,378 @@ utf8enc2latex_mapping = {
u'\U0001d7fc': '$\\mathtt{6}$',
u'\U0001d7fd': '$\\mathtt{7}$',
u'\U0001d7fe': '$\\mathtt{8}$',
u'\U0001d7ff': '$\\mathtt{9}$'
u'\U0001d7ff': '$\\mathtt{9}$',
#Items from simple list
u'\u0106': "{\\a\\'C}",
u'\u0408': '{\\CYRJE}',
u'\u20ac': '{\\texteuro}',
u'\u2191': '{\\textuparrow}',
u'\u0493': '{\\cyrghcrs}',
u'\u2116': '{\\textnumero}',
u'\u0418': '{\\CYRI}',
u'\u04a3': '{\\cyrndsc}',
u'\u2126': '{\\textohm}',
u'\u0428': '{\\CYRSH}',
u'\u04b3': '{\\cyrhdsc}',
u'\u0438': '{\\cyri}',
u'\u03bd': '{$\\nu$}',
u'\u04c3': '{\\CYRKHK}',
u'\u0448': '{\\cyrsh}',
u'\xcb': '{\\"E}',
u'\u0458': '{\\cyrje}',
u'\xdb': '{\\^U}',
u'\xeb': '{\\"e}',
u'\xfb': '{\\^u}',
u'\u0413': '{\\CYRG}',
u'\u0498': '{\\CYRZDSC}',
u'\xa0': '{~}',
u'\u0423': '{\\CYRU}',
u'\u04a8': '{\\CYRABHHA}',
u'\u0433': '{\\cyrg}',
u'\u04b8': '{\\CYRCHVCRS}',
u'\u203b': '{\\textreferencemark}',
u'\u211e': '{\\textrecipe}',
u'\xc0': '{\\`A}',
u'\u0443': '{\\cyru}',
u'\u04c8': '{\\cyrnhk}',
u'\u0151': '{\\H o}',
u'\u04d8': '{\\CYRSCHWA}',
u'\u0161': '{\\v s}',
u'\xe0': '{\\`a}',
u'\u0463': '{\\cyryat}',
u'\u04e8': '{\\CYROTLD}',
u'\u0171': '{\\H u}',
u'\u0473': '{\\cyrfita}',
u'\u20ab': '{\\textdong}',
u'\u2103': '{\\textcelsius}',
u'\u040e': '{\\CYRUSHRT}',
u'\u2212': '{\\textminus}',
u'\u2016': '{\\textbardbl}',
u'\u0499': '{\\cyrzdsc}',
u'\u041e': '{\\CYRO}',
u'\u2120': '{\\textservicemark}',
u'\u03a7': '{$\\chi$}',
u'\u2026': '{\\textellipsis}',
u'\u04a9': '{\\cyrabhha}',
u'\u042e': '{\\CYRYU}',
u'\xb1': '{\\textpm}',
u'\u0130': '{\\.I}',
u'\u04b9': '{\\cyrchvcrs}',
u'\u043e': '{\\cyro}',
u'\xc1': "{\\'A}",
u'\u044e': '{\\cyryu}',
u'\xd1': '{\\~N}',
u'\u0150': '{\\H O}',
u'\u04d9': '{\\cyrschwa}',
u'\u02dd': '{\\textacutedbl}',
u'\u045e': '{\\cyrushrt}',
u'\xe1': "{\\'a}",
u'\u0160': '{\\v S}',
u'\u04e9': '{\\cyrotld}',
u'\u266a': '{\\textmusicalnote}',
u'\xf1': '{\\~n}',
u'\u0170': '{\\H U}',
u'\u0409': '{\\CYRLJE}',
u'\u048e': '{\\CYRRTICK}',
u'\u2190': '{\\leftarrow}',
u'\u0419': '{\\CYRISHRT}',
u'\u011b': '{\\v e}',
u'\u049e': '{\\CYRKHCRS}',
u'\u0429': '{\\CYRSHCH}',
u'\u04ae': '{\\CYRY}',
u'\u0439': '{\\cyrishrt}',
u'\u04be': '{\\CYRABHCHDSC}',
u'\u0449': '{\\cyrshch}',
u'\u04ce': '{\\cyrmdsc}',
u'\xd6': '{\\"O}',
u'\u0459': '{\\cyrlje}',
u'\u015b': "{\\'s}",
u'\u20a6': '{\\textnaira}',
u'\xf6': '{\\"o}',
u'\u017b': '{\\.Z}',
u'\u0102': '{\\u A}',
u'\u0404': '{\\CYRIE}',
u'\u200c': '{\\textcompwordmark}',
u'\u048f': '{\\cyrrtick}',
u'\u0414': '{\\CYRD}',
u'\u049f': '{\\cyrkhcrs}',
u'\u0424': '{\\CYRF}',
u'\u04af': '{\\cyry}',
u'\u0434': '{\\cyrd}',
u'\xb7': '{\\textperiodcentered}',
u'\u04bf': '{\\cyrabhchdsc}',
u'\u0444': '{\\cyrf}',
u'\xc7': '{\\c C}',
u'\u0454': '{\\cyrie}',
u'\u0162': '{\\c T}',
u'\xe7': '{\\c c}',
u'\u0474': '{\\CYRIZH}',
u'\xf7': '{\\textdiv}',
u'\u010d': '{\\v c}',
u'\u040f': '{\\CYRDZHE}',
u'\u0192': '{\\textflorin}',
u'\u0494': '{\\CYRGHK}',
u'\u041f': '{\\CYRP}',
u'\u04a4': '{\\CYRNG}',
u'\xac': '{\\textlnot}',
u'\u042f': '{\\CYRYA}',
u'\u04b4': '{\\CYRTETSE}',
u'\u013d': '{\\v L}',
u'\u043f': '{\\cyrp}',
u'\u04c4': '{\\cyrkhk}',
u'\xcc': '{\\`I}',
u'\u044f': '{\\cyrya}',
u'\u2422': '{\\textblank}',
u'\u04d4': '{\\CYRAE}',
u'\xdc': '{\\"U}',
u'\u045f': '{\\cyrdzhe}',
u'\xec': '{\\`i}',
u'\u017d': '{\\v Z}',
u'\xfc': '{\\"u}',
u'\u040a': '{\\CYRNJE}',
u'\u010c': '{\\v C}',
u'\u0495': '{\\cyrghk}',
u'\u041a': '{\\CYRK}',
u'\u04a5': '{\\cyrng}',
u'\u042a': '{\\CYRHRDSN}',
u'\u2032': '{$\\prime$}',
u'\u04b5': '{\\cyrtetse}',
u'\u043a': '{\\cyrk}',
u'\u04c5': '{\\CYRLDSC}',
u'\u044a': '{\\cyrhrdsn}',
u'\xcd': "{\\'I}",
u'\u2052': '{\\textdiscount}',
u'\u04d5': '{\\cyrae}',
u'\u045a': '{\\cyrnje}',
u'\xdd': "{\\'Y}",
u'\u046a': '{\\CYRBYUS}',
u'\xed': "{\\'\\i}",
u'\u25ef': '{\\textbigcircle}',
u'\xfd': "{\\'y}",
u'\u017c': '{\\.z}',
u'\u0405': '{\\CYRDZE}',
u'\u0107': "{\\'c}",
u'\u0415': '{\\CYRE}',
u'\u2117': '{\\textcircledP}',
u'\u049a': '{\\CYRKDSC}',
u'\u0425': '{\\CYRH}',
u'\u2127': '{\\textmho}',
u'\u04aa': '{\\CYRSDSC}',
u'\xb2': '{\\texttwosuperior}',
u'\u0435': '{\\cyre}',
u'\u04ba': '{\\CYRSHHA}',
u'\u203d': '{\\textinterrobang}',
u'\xc2': '{\\^A}',
u'\u0445': '{\\cyrh}',
u'\u0147': '{\\v N}',
u'\u02c6': '{\\textasciicircum}',
u'\xd2': '{\\`O}',
u'\u0455': '{\\cyrdze}',
u'\u2261': '{$\\equiv$}',
u'\xe2': '{\\^a}',
u'\xf2': '{\\`o}',
u'\u0475': '{\\cyrizh}',
u'\u010e': '{\\v D}',
u'\u0410': '{\\CYRA}',
u'\u2018': '{\\textquoteleft}',
u'\u049b': '{\\cyrkdsc}',
u'\u011e': '{\\u G}',
u'\u0420': '{\\CYRR}',
u'\u04ab': '{\\cyrsdsc}',
u'\u232a': '{\\textrangle}',
u'\u212e': '{\\textestimated}',
u'\u0430': '{\\cyra}',
u'\xb3': '{\\textthreesuperior}',
u'\u04bb': '{\\cyrshha}',
u'\u013e': '{\\v l}',
u'\u0440': '{\\cyrr}',
u'\xc3': '{\\~A}',
u'\u04cb': '{\\CYRCHLDSC}',
u'\xd3': "{\\'O}",
u'\u015e': '{\\c S}',
u'\xe3': '{\\~a}',
u'\u016e': '{\\r U}',
u'\xf3': "{\\'o}",
u'\u017e': '{\\v z}',
u'\u040b': '{\\CYRTSHE}',
u'\u0490': '{\\CYRGUP}',
u'\u0119': '{\\k e}',
u'\u041b': '{\\CYRL}',
u'\u04a0': '{\\CYRKBEAK}',
u'\u042b': '{\\CYRERY}',
u'\u04b0': '{\\CYRYHCRS}',
u'\u0e37': '{\\textbaht}',
u'\u0139': "{\\'L}",
u'\xb8': '{\\c\\ }',
u'\u043b': '{\\cyrl}',
u'\u04c0': '{\\CYRpalochka}',
u'\xc8': '{\\`E}',
u'\u044b': '{\\cyrery}',
u'\u0159': '{\\v r}',
u'\u045b': '{\\cyrtshe}',
u'\u04e0': '{\\CYRABHDZE}',
u'\u25e6': '{\\textopenbullet}',
u'\xe8': '{\\`e}',
u'\u046b': '{\\cyrbyus}',
u'\u0179': "{\\'Z}",
u'\u0406': '{\\CYRII}',
u'\u0491': '{\\cyrgup}',
u'\u2193': '{\\textdownarrow}',
u'\u2192': '{\\textrightarrow}',
u'\u0416': '{\\CYRZH}',
u'\u0118': '{\\k E}',
u'\u201e': '{\\quotedblbase}',
u'\u04a1': '{\\cyrkbeak}',
u'\u0426': '{\\CYRC}',
u'\u04b1': '{\\cyryhcrs}',
u'\u0436': '{\\cyrzh}',
u'\xb9': '{\\textonesuperior}',
u'\u0446': '{\\cyrc}',
u'\xc9': "{\\'E}",
u'\u0148': '{\\v n}',
u'\u204e': '{\\textasteriskcentered}',
u'\u0456': '{\\cyrii}',
u'\xd9': '{\\`U}',
u'\u0158': '{\\v R}',
u'\u04e1': '{\\cyrabhdze}',
u'\xe9': "{\\'e}",
u'\xf9': '{\\`u}',
u'\u0178': '{\\"Y}',
u'\u0401': '{\\CYRYO}',
u'\u0103': '{\\u a}',
u'\u0411': '{\\CYRB}',
u'\u0496': '{\\CYRZHDSC}',
u'\u2019': '{\\textquoteright}',
u'\u0421': '{\\CYRS}',
u'\u04a6': '{\\CYRPHK}',
u'\u0431': '{\\cyrb}',
u'\u04b6': '{\\CYRCHRDSC}',
u'\u0441': '{\\cyrs}',
u'\u0143': "{\\'N}",
u'\u04c6': '{\\cyrldsc}',
u'\u02ca': '{\\textasciitilde}',
u'\xce': '{\\^I}',
u'\u0451': '{\\cyryo}',
u'\u0163': '{\\c t}',
u'\xee': '{\\^\\i}',
u'\u0497': '{\\cyrzhdsc}',
u'\u011a': '{\\v E}',
u'\u041c': '{\\CYRM}',
u'\u04a7': '{\\cyrphk}',
u'\u042c': '{\\CYRSFTSN}',
u'\u04b7': '{\\cyrchrdsc}',
u'\u013a': "{\\'l}",
u'\u043c': '{\\cyrm}',
u'\u2044': '{\\textfractionsolidus}',
u'\u04c7': '{\\CYRNHK}',
u'\u044c': '{\\cyrsftsn}',
u'\xcf': '{\\"I}',
u'\u015a': "{\\'S}",
u'\xef': '{\\"\\i}',
u'\u017a': "{\\'z}",
u'\xff': '{\\"y}',
u'\u0105': '{\\k a}',
u'\u0407': '{\\CYRYI}',
u'\u048c': '{\\CYRSEMISFTSN}',
u'\u0417': '{\\CYRZ}',
u'\u049c': '{\\CYRKVCRS}',
u'\u0427': '{\\CYRCH}',
u'\u2329': '{\\textlangle}',
u'\u04ac': '{\\CYRTDSC}',
u'\u0437': '{\\cyrz}',
u'\u04bc': '{\\CYRABHCH}',
u'\u20a1': '{\\textcolonmonetary}',
u'\xc4': '{\\"A}',
u'\u0447': '{\\cyrch}',
u'\u04cc': '{\\cyrchldsc}',
u'\u0155': "{\\'r}",
u'\xd4': '{\\^O}',
u'\u0457': '{\\cyryi}',
u'\u0165': '{\\v t}',
u'\xe4': '{\\"a}',
u'\u20a9': '{\\textwon}',
u'\xf4': '{\\^o}',
u'\u0402': '{\\CYRDJE}',
u'\u0104': '{\\k A}',
u'\u048d': '{\\cyrsemisftsn}',
u'\u0412': '{\\CYRV}',
u'\u201a': '{\\quotesinglbase}',
u'\u049d': '{\\cyrkvcrs}',
u'\u20b1': '{\\textpeso}',
u'\u0422': '{\\CYRT}',
u'\u04ad': '{\\cyrtdsc}',
u'\u0432': '{\\cyrv}',
u'\xb5': '{\\textmu}',
u'\u04bd': '{\\cyrabhch}',
u'\u0442': '{\\cyrt}',
u'\xc5': '{\\r A}',
u'\u0144': "{\\'n}",
u'\u04cd': '{\\CYRMDSC}',
u'\u0452': '{\\cyrdje}',
u'\xd5': '{\\~O}',
u'\u0154': "{\\'R}",
u'\u0462': '{\\CYRYAT}',
u'\xe5': '{\\r a}',
u'\u0164': '{\\v T}',
u'\u0472': '{\\CYRFITA}',
u'\xf5': '{\\~o}',
u'\u010f': '{\\v d}',
u'\u0492': '{\\CYRGHCRS}',
u'\u041d': '{\\CYRN}',
u'\u011f': '{\\u g}',
u'\u04a2': '{\\CYRNDSC}',
u'\u042d': '{\\CYREREV}',
u'\u04b2': '{\\CYRHDSC}',
u'\u043d': '{\\cyrn}',
u'\xca': '{\\^E}',
u'\u044d': '{\\cyrerev}',
u'\xda': "{\\'U}",
u'\u015f': '{\\c s}',
u'\u20a4': '{\\textlira}',
u'\xea': '{\\^e}',
u'\u016f': '{\\r u}',
u'\xfa': "{\\'u}"
#Items to add at a latter date (check first)
#u'\u0000': r'{$\alpha$}',
#u'\u0000': r'{$\beta$}',
#u'\u0000': r'{$\gamma$}',
#u'\u0000': r'{$\delta$}',
#u'\u0000': r'{$\epsilon$}',
#u'\u0000': r'{$\varepsilon$}',
#u'\u0000': r'{$\zeta$}',
#u'\u0000': r'{$\eta$}',
#u'\u0000': r'{$\theta$}',
#u'\u0000': r'{$\vartheta$}',
#u'\u0000': r'{$\iota$}',
#u'\u0000': r'{$\kappa$}',
#u'\u0000': r'{$\lambda$}',
#u'\u0000': r'{$\mu$}',
#u'\u0000': r'{$\xi$}',
#u'\u0000': r'{$\pi$}',
#u'\u0000': r'{$\varpi$}',
#u'\u0000': r'{$\rho$}',
#u'\u0000': r'{$\varrho$}',
#u'\u0000': r'{$\sigma$}',
#u'\u0000': r'{$\varsigma$}',
#u'\u0000': r'{$\tau$}',
#u'\u0000': r'{$\upsilon$}',
#u'\u0000': r'{$\phi$}',
#u'\u0000': r'{$\varphi$}',
#u'\u0000': r'{$\psi$}',
#u'\u0000': r'{$\omega$}',
#u'\u0000': r'{$\Gamma$}',
#u'\u0000': r'{$\Delta$}',
#u'\u0000': r'{$\Theta$}',
#u'\u0000': r'{$\Lambda$}',
#u'\u0000': r'{$\Xi$}',
#u'\u0000': r'{$\Pi$}',
#u'\u0000': r'{$\Sigma$}',
#u'\u0000': r'{$\Upsilon$}',
#u'\u0000': r'{$\Phi$}',
#u'\u0000': r'{$\Psi$}',
#u'\u0000': r'{$\Omega$}',
}
entity_mapping = {