--- a/src/eric7/QScintilla/Exporters/ExporterRTF.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/QScintilla/Exporters/ExporterRTF.py Wed Jul 13 14:55:47 2022 +0200 @@ -27,6 +27,7 @@ """ Class implementing an exporter for RTF. """ + RTF_HEADEROPEN = "{\\rtf1\\ansi\\deff0\\deftab720" RTF_HEADERCLOSE = "\n" RTF_FONTDEFOPEN = "{\\fonttbl" @@ -60,16 +61,16 @@ def __init__(self, editor, parent=None): """ Constructor - + @param editor reference to the editor object (QScintilla.Editor.Editor) @param parent parent object of the exporter (QObject) """ ExporterBase.__init__(self, editor, parent) - + def __GetRTFNextControl(self, pos, style): """ Private method to extract the next RTF control word from style. - + @param pos position to start search (integer) @param style style definition to search in (string) @return tuple of new start position and control word found @@ -78,18 +79,18 @@ # \f0\fs20\cf0\highlight0\b0\i0 if pos >= len(style): return pos, "" - + oldpos = pos - pos += 1 # implicit skip over leading '\' - while pos < len(style) and style[pos] != '\\': + pos += 1 # implicit skip over leading '\' + while pos < len(style) and style[pos] != "\\": pos += 1 return pos, style[oldpos:pos] - + def __GetRTFStyleChange(self, last, current): """ Private method to extract control words that are different between two styles. - + @param last least recently used style (string) @param current current style (string) @return string containing the delta between these styles (string) @@ -97,19 +98,18 @@ # \f0\fs20\cf0\highlight0\b0\i0 lastPos = 0 currentPos = 0 - delta = '' + delta = "" i = 0 while i < 6: lastPos, lastControl = self.__GetRTFNextControl(lastPos, last) - currentPos, currentControl = self.__GetRTFNextControl(currentPos, - current) + currentPos, currentControl = self.__GetRTFNextControl(currentPos, current) if lastControl != currentControl: delta += currentControl i += 1 - if delta != '': - delta += ' ' + if delta != "": + delta += " " return delta - + def exportSource(self): """ Public method performing the export. @@ -117,26 +117,30 @@ filename = self._getFileName(self.tr("RTF Files (*.rtf)")) if not filename: return - + self.editor.recolor(0, -1) tabs = Preferences.getEditorExporter("RTF/UseTabs") tabSize = self.editor.getEditorConfig("TabWidth") if tabSize == 0: tabSize = 4 - + with EricOverrideCursor(), open(filename, "w", encoding="utf-8") as f: try: styles, fontsize = self.__prepareStyles(f) - + lastStyle = ( - self.RTF_SETFONTFACE + "0" + - self.RTF_SETFONTSIZE + "{0:d}".format(fontsize) + - self.RTF_SETCOLOR + "0" + - self.RTF_SETBACKGROUND + "1" + - self.RTF_BOLD_OFF + - self.RTF_ITALIC_OFF + self.RTF_SETFONTFACE + + "0" + + self.RTF_SETFONTSIZE + + "{0:d}".format(fontsize) + + self.RTF_SETCOLOR + + "0" + + self.RTF_SETBACKGROUND + + "1" + + self.RTF_BOLD_OFF + + self.RTF_ITALIC_OFF ) - + lengthDoc = self.editor.length() prevCR = False column = 0 @@ -146,36 +150,35 @@ utf8 = self.editor.isUtf8() utf8Ch = b"" utf8Len = 0 - + while pos < lengthDoc: ch = self.editor.byteAt(pos) style = self.editor.styleAt(pos) if style != styleCurrent: - deltaStyle = self.__GetRTFStyleChange( - lastStyle, styles[style]) + deltaStyle = self.__GetRTFStyleChange(lastStyle, styles[style]) if deltaStyle: f.write(deltaStyle) styleCurrent = style lastStyle = styles[style] - - if ch == b'{': - f.write('\\{') - elif ch == b'}': - f.write('\\}') - elif ch == b'\\': - f.write('\\\\') - elif ch == b'\t': + + if ch == b"{": + f.write("\\{") + elif ch == b"}": + f.write("\\}") + elif ch == b"\\": + f.write("\\\\") + elif ch == b"\t": if tabs: f.write(self.RTF_TAB) else: ts = tabSize - (column % tabSize) - f.write(' ' * ts) + f.write(" " * ts) column += ts - 1 - elif ch == b'\n': + elif ch == b"\n": if not prevCR: f.write(self.RTF_EOLN) column -= 1 - elif ch == b'\r': + elif ch == b"\r": f.write(self.RTF_EOLN) column -= 1 else: @@ -191,12 +194,15 @@ column -= 1 # will be incremented again later elif len(utf8Ch) == utf8Len: - ch = utf8Ch.decode('utf8') - if ord(ch) <= 0xff: + ch = utf8Ch.decode("utf8") + if ord(ch) <= 0xFF: f.write("\\'{0:x}".format(ord(ch))) else: - f.write("\\u{0:d}\\'{1:x}".format( - ord(ch), ord(ch) & 0xFF)) + f.write( + "\\u{0:d}\\'{1:x}".format( + ord(ch), ord(ch) & 0xFF + ) + ) utf8Ch = b"" utf8Len = 0 else: @@ -204,11 +210,11 @@ # will be incremented again later else: f.write(ch.decode()) - + column += 1 - prevCR = ch == b'\r' + prevCR = ch == b"\r" pos += 1 - + f.write(self.RTF_BODYCLOSE) except OSError as err: EricMessageBox.critical( @@ -216,13 +222,14 @@ self.tr("Export source"), self.tr( """<p>The source could not be exported to""" - """ <b>{0}</b>.</p><p>Reason: {1}</p>""") - .format(filename, str(err))) - + """ <b>{0}</b>.</p><p>Reason: {1}</p>""" + ).format(filename, str(err)), + ) + def __prepareStyles(self, f): """ Private method to generate and store the different styles. - + @param f filepointer to the open RTF @type object @return styles, fontsize @@ -232,9 +239,9 @@ fonts = {} colors = {} lastStyle = "" - + lex = self.editor.getLexer() - + wysiwyg = Preferences.getEditorExporter("RTF/WYSIWYG") if wysiwyg: if lex: @@ -248,14 +255,14 @@ if fontsize == 0: fontsize = 10 << 1 characterset = QsciScintilla.SC_CHARSET_DEFAULT - + if lex: fgColour = lex.color(QsciScintilla.STYLE_DEFAULT) bgColour = lex.paper(QsciScintilla.STYLE_DEFAULT) else: fgColour = self.editor.color() bgColour = self.editor.paper() - + f.write(self.RTF_HEADEROPEN + self.RTF_FONTDEFOPEN) fonts[0] = fontface fontCount = 1 @@ -263,13 +270,13 @@ colors[0] = fgColour colors[1] = bgColour colorCount = 2 - + if lex: istyle = 0 while istyle <= QsciScintilla.STYLE_MAX: if ( - istyle < QsciScintilla.STYLE_DEFAULT or - istyle > QsciScintilla.STYLE_LASTPREDEFINED + istyle < QsciScintilla.STYLE_DEFAULT + or istyle > QsciScintilla.STYLE_LASTPREDEFINED ): if lex.description(istyle): font = lex.font(istyle) @@ -282,25 +289,26 @@ break else: fonts[fontCount] = font.family() - f.write(self.RTF_FONTDEF.format( - fontCount, characterset, - font.family())) + f.write( + self.RTF_FONTDEF.format( + fontCount, characterset, font.family() + ) + ) fontKey = fontCount fontCount += 1 - + lastStyle += "{0:d}".format(fontKey) else: lastStyle += "0" - + lastStyle += self.RTF_SETFONTSIZE if wysiwyg and QFontInfo(font).pointSize(): - lastStyle += ( - "{0:d}".format( - QFontInfo(font).pointSize() << 1) + lastStyle += "{0:d}".format( + QFontInfo(font).pointSize() << 1 ) else: lastStyle += "{0:d}".format(fontsize) - + sColour = lex.color(istyle) sColourKey = None for key, value in colors.items(): @@ -311,11 +319,8 @@ colors[colorCount] = sColour sColourKey = colorCount colorCount += 1 - lastStyle += ( - self.RTF_SETCOLOR + - "{0:d}".format(sColourKey) - ) - + lastStyle += self.RTF_SETCOLOR + "{0:d}".format(sColourKey) + sColour = lex.paper(istyle) sColourKey = None for key, value in colors.items(): @@ -326,12 +331,9 @@ colors[colorCount] = sColour sColourKey = colorCount colorCount += 1 - - lastStyle += ( - self.RTF_SETBACKGROUND + - "{0:d}".format(sColourKey) - ) - + + lastStyle += self.RTF_SETBACKGROUND + "{0:d}".format(sColourKey) + if font.bold(): lastStyle += self.RTF_BOLD_ON else: @@ -341,10 +343,9 @@ else: lastStyle += self.RTF_ITALIC_OFF styles[istyle] = lastStyle - + # get substyles - subs_start, subs_count = self.editor.getSubStyleRange( - istyle) + subs_start, subs_count = self.editor.getSubStyleRange(istyle) for subs_idx in range(subs_count): font = lex.font(subs_start + subs_idx) lastStyle = self.RTF_SETFONTFACE @@ -356,25 +357,26 @@ break else: fonts[fontCount] = font.family() - f.write(self.RTF_FONTDEF.format( - fontCount, characterset, - font.family())) + f.write( + self.RTF_FONTDEF.format( + fontCount, characterset, font.family() + ) + ) fontKey = fontCount fontCount += 1 - + lastStyle += "{0:d}".format(fontKey) else: lastStyle += "0" - + lastStyle += self.RTF_SETFONTSIZE if wysiwyg and QFontInfo(font).pointSize(): - lastStyle += ( - "{0:d}".format( - QFontInfo(font).pointSize() << 1) + lastStyle += "{0:d}".format( + QFontInfo(font).pointSize() << 1 ) else: lastStyle += "{0:d}".format(fontsize) - + sColour = lex.color(subs_start + subs_idx) sColourKey = None for key, value in colors.items(): @@ -385,11 +387,8 @@ colors[colorCount] = sColour sColourKey = colorCount colorCount += 1 - lastStyle += ( - self.RTF_SETCOLOR + - "{0:d}".format(sColourKey) - ) - + lastStyle += self.RTF_SETCOLOR + "{0:d}".format(sColourKey) + sColour = lex.paper(subs_start + subs_idx) sColourKey = None for key, value in colors.items(): @@ -400,12 +399,11 @@ colors[colorCount] = sColour sColourKey = colorCount colorCount += 1 - - lastStyle += ( - self.RTF_SETBACKGROUND + - "{0:d}".format(sColourKey) + + lastStyle += self.RTF_SETBACKGROUND + "{0:d}".format( + sColourKey ) - + if font.bold(): lastStyle += self.RTF_BOLD_ON else: @@ -415,41 +413,52 @@ else: lastStyle += self.RTF_ITALIC_OFF styles[subs_idx - subs_start] = lastStyle - + else: styles[istyle] = ( - self.RTF_SETFONTFACE + "0" + - self.RTF_SETFONTSIZE + - "{0:d}".format(fontsize) + - self.RTF_SETCOLOR + "0" + - self.RTF_SETBACKGROUND + "1" + - self.RTF_BOLD_OFF + - self.RTF_ITALIC_OFF + self.RTF_SETFONTFACE + + "0" + + self.RTF_SETFONTSIZE + + "{0:d}".format(fontsize) + + self.RTF_SETCOLOR + + "0" + + self.RTF_SETBACKGROUND + + "1" + + self.RTF_BOLD_OFF + + self.RTF_ITALIC_OFF ) - + istyle += 1 else: styles[0] = ( - self.RTF_SETFONTFACE + "0" + - self.RTF_SETFONTSIZE + - "{0:d}".format(fontsize) + - self.RTF_SETCOLOR + "0" + - self.RTF_SETBACKGROUND + "1" + - self.RTF_BOLD_OFF + - self.RTF_ITALIC_OFF + self.RTF_SETFONTFACE + + "0" + + self.RTF_SETFONTSIZE + + "{0:d}".format(fontsize) + + self.RTF_SETCOLOR + + "0" + + self.RTF_SETBACKGROUND + + "1" + + self.RTF_BOLD_OFF + + self.RTF_ITALIC_OFF ) - + f.write(self.RTF_FONTDEFCLOSE + self.RTF_COLORDEFOPEN) for value in colors.values(): - f.write(self.RTF_COLORDEF.format( - value.red(), value.green(), value.blue())) + f.write(self.RTF_COLORDEF.format(value.red(), value.green(), value.blue())) f.write(self.RTF_COLORDEFCLOSE) f.write(self.RTF_INFOOPEN + self.RTF_COMMENT) f.write(time.strftime(self.RTF_CREATED)) f.write(self.RTF_INFOCLOSE) - f.write(self.RTF_HEADERCLOSE + - self.RTF_BODYOPEN + self.RTF_SETFONTFACE + "0" + - self.RTF_SETFONTSIZE + "{0:d}".format(fontsize) + - self.RTF_SETCOLOR + "0 ") - + f.write( + self.RTF_HEADERCLOSE + + self.RTF_BODYOPEN + + self.RTF_SETFONTFACE + + "0" + + self.RTF_SETFONTSIZE + + "{0:d}".format(fontsize) + + self.RTF_SETCOLOR + + "0 " + ) + return styles, fontsize