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