From 24403bb395330c475c98c8e8c9bfefcb65c7db75 Mon Sep 17 00:00:00 2001 From: dchandler Date: Sun, 27 Feb 2005 10:27:37 +0000 Subject: [PATCH] Jskad has two new menu items that are a shortcut for running a standalone TMW->Unicode conversion: 'Save as Unicode RTF...' and 'Save as Unicode UTF-8 Text...'. --- source/org/thdl/tib/input/DuffPane.java | 62 +++++++++- source/org/thdl/tib/input/Jskad.java | 116 ++++++++++++++---- .../org/thdl/tib/input/TibetanConverter.java | 3 +- source/org/thdl/tib/input/jskad_doc.html | 15 ++- 4 files changed, 165 insertions(+), 31 deletions(-) diff --git a/source/org/thdl/tib/input/DuffPane.java b/source/org/thdl/tib/input/DuffPane.java index fdc2819..3235eb1 100644 --- a/source/org/thdl/tib/input/DuffPane.java +++ b/source/org/thdl/tib/input/DuffPane.java @@ -566,6 +566,7 @@ public class DuffPane extends TibetanPane implements FocusListener { getTibDoc().insertString(offset, s, attr); } catch (BadLocationException ble) { + ThdlDebug.noteIffyCode(); } } @@ -1025,6 +1026,54 @@ public class DuffPane extends TibetanPane implements FocusListener { } } } + + /** Saves the TMW document underlying this DuffPane as Unicode. Has to copy + @param utf8_text true if you want to save as UTF-8-encoded + Unicode text, false if you want to save as Unicode in RTF + @param out an OutputStream that will be closed when we're done + in every case + @returns true on perfect success, false otherwise */ + public boolean saveAsUnicode(boolean utf8_text, OutputStream out) + throws IOException + { + boolean retval = true; + ThdlDebug.verify(getDocument() == getTibDoc()); + // construct new document so that we can use + // TibetanDocument.convertToUnicode(..). + TibetanDocument newDoc = new TibetanDocument(); + try { + for (int i = 0; i < getTibDoc().getLength(); i++) { + String s = getTibDoc().getText(i,1); + AttributeSet as + = getTibDoc().getCharacterElement(i).getAttributes(); + String fontName = StyleConstants.getFontFamily(as); + if (0 != TibetanMachineWeb.getTMFontNumber(fontName)) + retval = false; + newDoc.insertString(i, s, as); + } + } catch (BadLocationException ble) { + throw new Error("this cannot happen"); + } + if (newDoc.convertToUnicode(0, newDoc.getLength(), null, + ThdlOptions.getStringOption("thdl.tmw.to.unicode.font").intern(), + new long[] { 0 })) { + retval = false; + } + if (utf8_text) { + BufferedWriter bw + = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); + newDoc.writeTextOutput(bw); + bw.close(); + } else { + try { + rtfEd.write(out, newDoc, 0, newDoc.getLength()); + } catch (BadLocationException ble) { + throw new Error("this cannot happen either"); + } + out.close(); + } + return retval; + } /** Adds to the clipboard the Unicode you'd get if you used a TMW->Unicode conversion on the specified portion of the @@ -1038,8 +1087,8 @@ public class DuffPane extends TibetanPane implements FocusListener { // TibetanDocument.convertToUnicode(..). TibetanDocument newDoc = new TibetanDocument(); boolean warn_about_tm = false; - for (int i = start; i < end; i++) { - try { + try { + for (int i = start; i < end; i++) { String s = getTibDoc().getText(i,1); AttributeSet as = getTibDoc().getCharacterElement(i).getAttributes(); @@ -1047,10 +1096,10 @@ public class DuffPane extends TibetanPane implements FocusListener { if (0 != TibetanMachineWeb.getTMFontNumber(fontName)) warn_about_tm = true; newDoc.insertString(i - start, s, as); - } catch (BadLocationException ble) { - ble.printStackTrace(); - ThdlDebug.noteIffyCode(); } + } catch (BadLocationException ble) { + ble.printStackTrace(); + ThdlDebug.noteIffyCode(); } String unicode = "[Jskad: Converting to Unicode failed.]"; if (newDoc.convertToUnicode(0, newDoc.getLength(), null, null, @@ -1766,3 +1815,6 @@ class RTFSelection implements ClipboardOwner, Transferable { } // inner class DuffPane.RTFSelection } // class DuffPane + +// TODO(dchandler): search for 'catch (Throwable' and 'catch +// (Exception' and 'catch (Error'. These are rarely a good idea. diff --git a/source/org/thdl/tib/input/Jskad.java b/source/org/thdl/tib/input/Jskad.java index 04c2b02..e1d5bdd 100644 --- a/source/org/thdl/tib/input/Jskad.java +++ b/source/org/thdl/tib/input/Jskad.java @@ -195,20 +195,20 @@ public class Jskad extends JPanel implements DocumentListener { } } + private int numItemsOnFileMenuBeforeRecentlyOpened = 0; private void updateRecentlyOpenedFilesMenuItems() { - int ic = fileMenu.getItemCount(); - while (fileMenu.getItemCount() > 8) - fileMenu.remove(7); + int menu_loc = numItemsOnFileMenuBeforeRecentlyOpened; + while (fileMenu.getItemCount() > menu_loc + 2) + fileMenu.remove(menu_loc + 1); int N = RecentlyOpenedFilesDatabase.getNumberOfFilesToShow(); // Avoid adding duplicate entries: - boolean addedSeparator = false; for (int i = 0; i < N; i++) { final File recentlyOpenedFile = RecentlyOpenedFilesDatabase.getNthRecentlyOpenedFile(N-i-1); if (null != recentlyOpenedFile) { if (!addedSeparator) { - fileMenu.insertSeparator(6); + fileMenu.insertSeparator(menu_loc); addedSeparator = true; } JMenuItem item = new JMenuItem((N-i) + " " @@ -218,7 +218,7 @@ public class Jskad extends JPanel implements DocumentListener { openFile(recentlyOpenedFile); } }); - fileMenu.add(item, 7); + fileMenu.add(item, menu_loc + 1); } } } @@ -267,6 +267,8 @@ public class Jskad extends JPanel implements DocumentListener { fileChooser.addChoosableFileFilter(rtfFilter); fileMenu = new JMenu("File"); + numItemsOnFileMenuBeforeRecentlyOpened = 0; + JMenuItem newItem = new JMenuItem("New..."); // newItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N,java.awt.Event.CTRL_MASK)); //Ctrl-n @@ -275,6 +277,7 @@ public class Jskad extends JPanel implements DocumentListener { newFile(); } }); + ++numItemsOnFileMenuBeforeRecentlyOpened; fileMenu.add(newItem); JMenuItem openItem = new JMenuItem("Open..."); @@ -284,6 +287,7 @@ public class Jskad extends JPanel implements DocumentListener { openFile(); } }); + ++numItemsOnFileMenuBeforeRecentlyOpened; fileMenu.add(openItem); if (parentObject instanceof JFrame) { @@ -302,6 +306,7 @@ public class Jskad extends JPanel implements DocumentListener { } } }); + ++numItemsOnFileMenuBeforeRecentlyOpened; fileMenu.add(closeItem); } JMenuItem saveItem = new JMenuItem("Save"); @@ -309,23 +314,44 @@ public class Jskad extends JPanel implements DocumentListener { saveItem.addActionListener(new ThdlActionListener() { public void theRealActionPerformed(ActionEvent e) { if (fileName == null) - saveAsFile(); + saveAsFile("legacy rtf"); else saveFile(); } }); + ++numItemsOnFileMenuBeforeRecentlyOpened; fileMenu.addSeparator(); + ++numItemsOnFileMenuBeforeRecentlyOpened; fileMenu.add(saveItem); JMenuItem saveAsItem = new JMenuItem("Save as..."); saveAsItem.addActionListener(new ThdlActionListener() { public void theRealActionPerformed(ActionEvent e) { - saveAsFile(); + saveAsFile("legacy rtf"); } }); + ++numItemsOnFileMenuBeforeRecentlyOpened; fileMenu.add(saveAsItem); + JMenuItem saveAsUnicodeUtf8Item = new JMenuItem("Save as Unicode UTF-8 text..."); + saveAsUnicodeUtf8Item.addActionListener(new ThdlActionListener() { + public void theRealActionPerformed(ActionEvent e) { + saveAsFile("unicode utf8 text"); + } + }); + ++numItemsOnFileMenuBeforeRecentlyOpened; + fileMenu.add(saveAsUnicodeUtf8Item); + + JMenuItem saveAsUnicodeRtfItem = new JMenuItem("Save as Unicode RTF..."); + saveAsUnicodeRtfItem.addActionListener(new ThdlActionListener() { + public void theRealActionPerformed(ActionEvent e) { + saveAsFile("unicode rtf"); + } + }); + ++numItemsOnFileMenuBeforeRecentlyOpened; + fileMenu.add(saveAsUnicodeRtfItem); + if (parentObject instanceof JFrame) { JMenuItem exitItem = new JMenuItem("Exit"); exitItem.addActionListener(new ThdlActionListener() { @@ -1024,7 +1050,7 @@ public class Jskad extends JPanel implements DocumentListener { /** Returns true iff the save was successful. */ private boolean saveFile() { - String s = getSave(fileName); + String s = getSave("legacy rtf", fileName); if (null != s) { if (parentObject instanceof JFrame) { JFrame parentFrame = (JFrame)parentObject; @@ -1042,9 +1068,11 @@ public class Jskad extends JPanel implements DocumentListener { } } - /** Returns true iff the save was successful. */ - private boolean saveAsFile() { - String s = getSaveAs(); + /** Returns true iff the save was successful. + * @param fileType either "legacy rtf", "unicode utf8 text", or + * "unicode rtf" */ + private boolean saveAsFile(String fileType) { + String s = getSaveAs(fileType); if (null != s) { if (parentObject instanceof JFrame) { JFrame parentFrame = (JFrame)parentObject; @@ -1084,7 +1112,7 @@ public class Jskad extends JPanel implements DocumentListener { case JOptionPane.YES_OPTION: //save and continue if (fileName == null) - return saveAsFile(); + return saveAsFile("legacy rtf"); else return saveFile(); @@ -1093,14 +1121,35 @@ public class Jskad extends JPanel implements DocumentListener { } } - private String getSave(String f_name) { + private String getSave(String fileType, String f_name) { File fileChosen = new File(f_name); try { - BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileChosen)); - dp.rtfEd.write(out, dp.getDocument(), 0, dp.getDocument().getLength()); - out.flush(); - out.close(); + if (fileType == "legacy rtf") { + BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(fileChosen)); + dp.rtfEd.write(out, dp.getDocument(), 0, dp.getDocument().getLength()); + out.flush(); + out.close(); + } else if (fileType == "unicode utf8 text") { + if (!dp.saveAsUnicode(true, + new BufferedOutputStream(new FileOutputStream(fileChosen)))) { + JOptionPane.showMessageDialog(Jskad.this, + "Saving as UTF-8 Unicode text did not go perfectly. Try using the standalone converter if you want a perfect document.", + "Save As UTF-8 Warning", + JOptionPane.WARNING_MESSAGE); + } + } else if (fileType == "unicode rtf") { + if (!dp.saveAsUnicode(false, + new BufferedOutputStream(new FileOutputStream(fileChosen)))) { + JOptionPane.showMessageDialog(Jskad.this, + "Saving as Unicode RTF did not go perfectly. Try using the standalone converter if you want a perfect document.", + "Save As Unicode RTF Warning", + JOptionPane.WARNING_MESSAGE); + } + } else { + throw new IllegalArgumentException("fileType " + fileType + + " is not supported"); + } hasChanged = false; } catch (IOException exception) { JOptionPane.showMessageDialog(Jskad.this, @@ -1116,9 +1165,13 @@ public class Jskad extends JPanel implements DocumentListener { return f_name; } - private String getSaveAs() { + private String getSaveAs(String fileType) { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + if (fileType == "unicode utf8 text") { + fileChooser.removeChoosableFileFilter(rtfFilter); + fileChooser.addChoosableFileFilter(txtFilter); + } if (fileName == null) fileChooser.setSelectedFile(null); else @@ -1126,6 +1179,10 @@ public class Jskad extends JPanel implements DocumentListener { if (fileChooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + if (fileType == "unicode utf8 text") { + fileChooser.removeChoosableFileFilter(txtFilter); + fileChooser.addChoosableFileFilter(rtfFilter); + } return null; } @@ -1135,12 +1192,23 @@ public class Jskad extends JPanel implements DocumentListener { String fileName = fileChosen.getAbsolutePath(); int i = fileName.lastIndexOf('.'); - if (i < 0) - fileName += ".rtf"; - else - fileName = fileName.substring(0, i) + ".rtf"; + String ext = ((fileType == "unicode utf8 text") ? ".txt" : ".rtf"); - getSave(fileName); + if (i < 0) + fileName += ext; + else if (!fileName.regionMatches(true, i, ext, 0, ext.length()) + || fileName.length() != i + ext.length()) { + JOptionPane.showMessageDialog(Jskad.this, + "Filename chosen does not have the extension '" + + ext + "'", + "Save As Error", + JOptionPane.ERROR_MESSAGE); + + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + return null; + } + + getSave(fileType, fileName); fileChooser.rescanCurrentDirectory(); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); diff --git a/source/org/thdl/tib/input/TibetanConverter.java b/source/org/thdl/tib/input/TibetanConverter.java index 425a44a..ab2184c 100644 --- a/source/org/thdl/tib/input/TibetanConverter.java +++ b/source/org/thdl/tib/input/TibetanConverter.java @@ -466,7 +466,8 @@ public class TibetanConverter implements FontConverterConstants { if (TMW_TO_WYLIE_TEXT == ct || TMW_TO_ACIP_TEXT == ct) { try { BufferedWriter bw - = new BufferedWriter(new OutputStreamWriter(out)); + = new BufferedWriter(new OutputStreamWriter(out, + "UTF-8")); tdoc.writeTextOutput(bw); bw.flush(); } catch (IOException e) { diff --git a/source/org/thdl/tib/input/jskad_doc.html b/source/org/thdl/tib/input/jskad_doc.html index bc58cbd..e934cc0 100644 --- a/source/org/thdl/tib/input/jskad_doc.html +++ b/source/org/thdl/tib/input/jskad_doc.html @@ -143,7 +143,8 @@ documents.  In any case, if there is any text in the current Jskad window, a new window will be opened up.  To close a Jskad window, choose 'Close' or press the 'X' button.  To close all Jskad windows, choose 'Exit'.  You will be prompted to save if -you haven't already done so. +you haven't already done so.

@@ -152,6 +153,18 @@ other applications, 'Save' saves under the current name, while 'Save As...' lets you save under a new name.

+

+As a convenience, 'Save as Unicode RTF...' and 'Save as +Unicode UTF-8...' are provided.  An ordinary 'Save' or 'Save +As...' command saves as Rich Text Format using the legacy Tibetan +Machine Web font, but these two options convert the Tibetan Machine +Web to Unicode.  These are convenient, but if you encounter +problems you will need to take the long road by first saving normally +and then choosing 'Tools - Launch Converter...' and converting from +TMW to Unicode.  (A good Unicode font is Tibetan Machine Uni, by +the way.) +

+

The 'Edit' menu lets you cut, copy, and paste Tibetan text and set document preferences.  These topics are covered elsewhere, in