DuffPane now has the start of a unit test suite. Invoke it via 'ant

clean check'.  Right now there are tests to ensure that typing certain
sequences of keys in the Extended Wylie keyboard gives the expected
Extended Wylie back when "Tools/Convert Tibetan to Wylie" is invoked.

The syntactically illegal d.wa now converts to Tibetan and then back
to d.wa (not dwa, as it did); likewise with the illegal g.wa.  wa
doesn't take any prefixes, but I prefer clean end-to-end
behavior. (jeskd doesn't go end-to-end, though.)

Note that you cannot successfully run the DuffPane tests on a Linux
box unless your DISPLAY variable is set correctly.  Thus, my nightly
builds will fail with an Error (as opposed to a Failure).
This commit is contained in:
dchandler 2003-04-14 05:22:27 +00:00
parent d9b22a43d6
commit efa8fc1f25
8 changed files with 444 additions and 109 deletions

View File

@ -366,6 +366,16 @@
<param name="my.included.source.file"
value="org/thdl/tib/text/tshegbar/LegalTshegBarTest.java"/>
</antcall>
<antcall target="our-internal-javac-task">
<param name="mybin" value="${junitbin}"/>
<param name="my.included.source.file"
value="org/thdl/tib/input/DuffPaneTest.java"/>
</antcall>
<antcall target="copy-ini-files-to-bin-dir-for-jarring">
<param name="mybin" value="${junitbin}"/>
</antcall>
<antcall target="our-internal-javac-task">
<param name="mybin" value="${junitbin}"/>
<param name="my.included.source.file"

View File

@ -21,7 +21,11 @@
<ul>
<li>
See <a href="junit-noframes.html">here</a> for results of the
nightly JUnit tests.
nightly JUnit tests.&nbsp; Note that an error on DuffPaneTest is
quite normal; this test runs only when an X11 display can be
opened, and I'm too lazy to run the tests with a framebuffer X
display.&nbsp; Run 'ant clean check' manually and DuffPaneTest
should pass with flying colors.
</li>
<li>
Today's Javadocs: [<a href="docs/public">public</a> <a href="docs/public-javadocs-today.zip">(zip file)</a>]

View File

@ -34,13 +34,14 @@
<!-- This creates output files TEST* in the Jskad/ directory. -->
<target name="run-all-junit-tests"
description="Assuming that compilation of appropriate classes has been done, this target runs all the JUnit tests in the project.">
<junit fork="no" printsummary="yes" haltonfailure="yes" haltonerror="yes">
<junit fork="no" printsummary="yes" haltonfailure="yes" haltonerror="no">
<classpath>
<pathelement location="${junitbin}"/>
<path refid="entire.class.path"/>
</classpath>
<formatter type="xml"/><!-- If not XML, then 'ant -buildfile
build.xml check-report' will fail. -->
<test name="org.thdl.tib.input.DuffPaneTest"/>
<test name="org.thdl.util.ThdlLazyExceptionTest"/>
<test name="org.thdl.util.TrieTest"/>
<test name="org.thdl.tib.text.tshegbar.UnicodeUtilsTest"/>

View File

@ -26,6 +26,7 @@ import java.awt.font.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.text.rtf.*;
import org.thdl.tib.text.*;
@ -50,7 +51,6 @@ public class DuffPane extends TibetanPane implements FocusListener {
*/
private StatusBar statBar = null;
/**
* A central part of the Tibetan keyboard. As keys are typed, they are
* added to charList if they constitute a valid Wylie character. charList
@ -236,6 +236,20 @@ public class DuffPane extends TibetanPane implements FocusListener {
initialize(null, null, keyboardURL);
}
/** For testing purposes, it's useful to create a DuffPane and not
* hook it up to the UI. If this is true, this DuffPane will
* manage its document's caret rather than having the UI do
* it. */
private boolean manageCaret = false;
/** For testing purposes, it's useful to create a DuffPane and not
* hook it up to the UI. If you call htis, then this DuffPane
* will manage its document's caret rather than having the UI do
* it. */
void enableCaretManaging() {
manageCaret = true;
}
/** Sets the status bar to update with mode information. If sb is
null, no status bar will be updated. */
public void setStatusBar(StatusBar sb) {
@ -288,7 +302,7 @@ public class DuffPane extends TibetanPane implements FocusListener {
newDocument();
romanFontFamily = ThdlOptions.getStringOption("thdl.default.roman.font.face",
"Serif"); // FIXME write out this preference.
"Serif");
romanFontSize = defaultRomanFontSize();
setRomanAttributeSet(romanFontFamily, romanFontSize);
@ -305,6 +319,32 @@ public class DuffPane extends TibetanPane implements FocusListener {
setupKeymap();
}
/** Performs the keystroke key with selected ActionEvent-style
* modifiers modifiers. */
void performKeyStroke(int modifiers, String key) {
// FIXME: do this assertion: assert(key.length() == 1);
if (!isEditable()) return;
if (((modifiers & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) ||
((modifiers & ActionEvent.ALT_MASK) == ActionEvent.ALT_MASK) ||
((modifiers & ActionEvent.META_MASK) == ActionEvent.META_MASK)) {
initKeyboard();
return;
}
if (key != null) {
if (getSelectionStart() < getSelectionEnd())
replaceSelection("");
if (isTibetan) {
processTibetanChar(key.charAt(0));
} else {
processRomanChar(key, romanAttributeSet);
}
if (manageCaret) {
caret.setDot(getTibDoc().getLength());
}
}
}
/**
* This method sets up the keymap used by DuffPane editors.
* The keymap defines a default behavior for key presses
@ -313,30 +353,12 @@ public class DuffPane extends TibetanPane implements FocusListener {
private void setupKeymap() {
Action defaultAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if (!DuffPane.this.isEditable()) return;
if ( ((e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK) ||
((e.getModifiers() & ActionEvent.ALT_MASK) == ActionEvent.ALT_MASK) ||
((e.getModifiers() & ActionEvent.META_MASK) == ActionEvent.META_MASK)) {
DuffPane.this.initKeyboard();
return;
}
if (e.getActionCommand() != null) {
String key = e.getActionCommand();
if (DuffPane.this.getSelectionStart() < DuffPane.this.getSelectionEnd())
DuffPane.this.replaceSelection("");
if (key != null) {
if (isTibetan) processTibetanChar(key.charAt(0));
else {
//MutableAttributeSet inputAtts = DuffPane.this.getInputAttributes();
//inputAtts.addAttributes(romanAttributeSet);
processRomanChar(key, romanAttributeSet);//, inputAtts);
}
}
}
DuffPane.this.performKeyStroke(e.getModifiers(),
e.getActionCommand());
}
};
createActionTable(this);
Keymap keymap = addKeymap("DuffBindings", getKeymap());
Keymap keymap = addKeymap("DuffBindings", getKeymap());
keymap.setDefaultAction(defaultAction);
setKeymap(keymap);
}
@ -373,7 +395,7 @@ public class DuffPane extends TibetanPane implements FocusListener {
* respect to stacking, and concerning the differences between
* Tibetan and Sanskrit; and then it initializes the input method.
*/
public void setupKeyboard() {
private void setupKeyboard() {
if (TibetanMachineWeb.hasTibetanStackingKey()) {
if (TibetanMachineWeb.hasSanskritStackingKey()) {
isDefinitelyTibetan_default = false;
@ -459,10 +481,14 @@ public class DuffPane extends TibetanPane implements FocusListener {
// a small cursor, though most everything else will be normal,
// if you call setDocument(doc) at the end of this method.
setDocument(doc);
ThdlDebug.verify(getTibDoc() == doc);
Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
StyleConstants.setFontFamily(defaultStyle, "TibetanMachineWeb");
StyleConstants.setFontSize(defaultStyle, defaultTibFontSize());
newGlyphList.clear();
initKeyboard();
}
/**
@ -474,10 +500,10 @@ public class DuffPane extends TibetanPane implements FocusListener {
* backspacing, redrawing, etc.
*/
private void initKeyboard() {
updateStatus("Jskad is in its basic input mode");
charList.clear();
oldGlyphList.clear();
holdCurrent = new StringBuffer();
updateStatus("Jskad is in its basic input mode");
isTopHypothesis = false;
isTypingVowel = false;
@ -636,9 +662,13 @@ public class DuffPane extends TibetanPane implements FocusListener {
*/
private void backSpace(int k) {
try {
getTibDoc().remove(caret.getDot()-k, k);
}
catch (BadLocationException ble) {
int newEnd = caret.getDot()-k;
if (newEnd >= 0) {
getTibDoc().remove(newEnd, k);
if (manageCaret) caret.setDot(newEnd);
}
} catch (BadLocationException ble) {
ThdlDebug.noteIffyCode();
}
}
@ -894,66 +924,6 @@ public class DuffPane extends TibetanPane implements FocusListener {
appendStatus(" (because the window focus was lost)");
}
// FIXMEDOC
class RTFSelection implements ClipboardOwner, Transferable {
private DataFlavor[] supportedFlavor;
private ByteArrayOutputStream rtfOut;
private String plainText;
// FIXMEDOC
RTFSelection(StyledDocument sdoc, int offset, int length) {
supportedFlavor = new DataFlavor[2];
supportedFlavor[0] = rtfFlavor;
supportedFlavor[1] = DataFlavor.stringFlavor;
try {
//construct new document that contains only portion of text you want to copy
//this workaround is due to bug 4129911, which will not be fixed (see below after source code)
StyledDocument newDoc = new DefaultStyledDocument();
for (int i=offset; i<offset+length; i++) {
try {
String s = sdoc.getText(i,1);
AttributeSet as = sdoc.getCharacterElement(i).getAttributes();
newDoc.insertString(i-offset, s, as);
} catch (BadLocationException ble) {
ble.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
rtfOut = new ByteArrayOutputStream();
rtfEd.write(rtfOut, newDoc, 0, newDoc.getLength()); //last two parameters ignored, see bug below
plainText = getText(offset, length);
} catch (BadLocationException ble) {
ble.printStackTrace();
ThdlDebug.noteIffyCode();
} catch (IOException ioe) {
ioe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
// FIXMEDOC
public void lostOwnership(Clipboard clipboard, Transferable contents) {
}
// FIXMEDOC
public Object getTransferData(DataFlavor flavor) {
if (flavor.equals(rtfFlavor))
return new ByteArrayInputStream(rtfOut.toByteArray());
if (flavor.equals(DataFlavor.stringFlavor))
return plainText;
return null;
}
// FIXMEDOC
public DataFlavor[] getTransferDataFlavors() {
return supportedFlavor;
}
// FIXMEDOC
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (int i=0; i<supportedFlavor.length; i++)
if (flavor.equals(supportedFlavor[i]))
return true;
return false;
}
} // class RTFSelection
/** Copies the current selection to the system clipboard, unless
cut-and-paste operations are disabled. */
public void copy() {
@ -973,8 +943,8 @@ class RTFSelection implements ClipboardOwner, Transferable {
if (!this.isEditable())
return;
try
{
try {
ThdlDebug.verify(getDocument() == getTibDoc());
getDocument().remove(start, end-start);
} catch (BadLocationException ble) {
ble.printStackTrace();
@ -1000,6 +970,7 @@ class RTFSelection implements ClipboardOwner, Transferable {
int p1 = start;
int p2 = end;
if (p1 != p2) {
ThdlDebug.verify(getDocument() == getTibDoc());
RTFSelection rtfSelection = new RTFSelection((StyledDocument)getDocument(), p1, p2-p1);
try {
rtfBoard.setContents(rtfSelection, rtfSelection);
@ -1014,6 +985,7 @@ class RTFSelection implements ClipboardOwner, Transferable {
return;
try {
ThdlDebug.verify(getDocument() == getTibDoc());
getDocument().remove(p1, p2-p1);
} catch (BadLocationException ble) {
ble.printStackTrace();
@ -1287,7 +1259,7 @@ public void paste(int offset) {
initKeyboard();
changedStatus = true;
appendStatus(" (because you typed punctuation)");
break key_block; /* DLC is this right? */
break key_block;
}
if (charList.size()==0) { //add current character to charList if possible
@ -1677,4 +1649,67 @@ public void paste(int offset) {
return getTibDoc().getWylie();
}
// FIXMEDOC
class RTFSelection implements ClipboardOwner, Transferable {
private DataFlavor[] supportedFlavor;
private ByteArrayOutputStream rtfOut;
private String plainText;
// FIXMEDOC
RTFSelection(StyledDocument sdoc, int offset, int length) {
supportedFlavor = new DataFlavor[2];
supportedFlavor[0] = rtfFlavor;
supportedFlavor[1] = DataFlavor.stringFlavor;
try {
//construct new document that contains only portion of text you want to copy
//this workaround is due to bug 4129911, which will not be fixed (see below after source code)
StyledDocument newDoc = new DefaultStyledDocument();
for (int i=offset; i<offset+length; i++) {
try {
String s = sdoc.getText(i,1);
AttributeSet as = sdoc.getCharacterElement(i).getAttributes();
newDoc.insertString(i-offset, s, as);
} catch (BadLocationException ble) {
ble.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
rtfOut = new ByteArrayOutputStream();
rtfEd.write(rtfOut, newDoc, 0, newDoc.getLength()); //last two parameters ignored, see bug below
plainText = getText(offset, length);
} catch (BadLocationException ble) {
ble.printStackTrace();
ThdlDebug.noteIffyCode();
} catch (IOException ioe) {
ioe.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
// FIXMEDOC
public void lostOwnership(Clipboard clipboard, Transferable contents) {
}
// FIXMEDOC
public Object getTransferData(DataFlavor flavor) {
if (flavor.equals(rtfFlavor))
return new ByteArrayInputStream(rtfOut.toByteArray());
if (flavor.equals(DataFlavor.stringFlavor))
return plainText;
return null;
}
// FIXMEDOC
public DataFlavor[] getTransferDataFlavors() {
return supportedFlavor;
}
// FIXMEDOC
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (int i=0; i<supportedFlavor.length; i++)
if (flavor.equals(supportedFlavor[i]))
return true;
return false;
}
} // class RTFSelection
}

View File

@ -0,0 +1,274 @@
/*
The contents of this file are subject to the THDL Open Community License
Version 1.0 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License on the THDL web site
(http://www.thdl.org/).
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
License for the specific terms governing rights and limitations under the
License.
The Initial Developer of this software is the Tibetan and Himalayan Digital
Library (THDL). Portions created by the THDL are Copyright 2002-2003 THDL.
All Rights Reserved.
Contributor(s): ______________________________________.
*/
package org.thdl.tib.input;
import junit.framework.TestCase;
import javax.swing.Action;
import javax.swing.KeyStroke;
import org.thdl.util.ThdlOptions;
/**
* @author David Chandler
*
* Tests {@link org.thdl.tib.input.Duffpane} at the unit level to see
* that the various keyboards work as expected.
*/
public class DuffPaneTest extends TestCase {
/** A DuffPane that uses THDL's extended Wylie keyboard: */
private DuffPane dp;
/** Sets us up a DuffPane. */
protected void setUp() {
// We don't want to use options.txt:
ThdlOptions.forTestingOnlyInitializeWithoutDefaultOptionsFile();
// We don't want to load the TMW font files ourselves:
ThdlOptions.setUserPreference("thdl.rely.on.system.tmw.fonts", true);
ThdlOptions.setUserPreference("thdl.debug", true);
dp = new DuffPane();
dp.enableCaretManaging();
dp.registerKeyboard();
}
/** Tears us down a DuffPane. */
protected void tearDown() {
// let GC do its worst with dp. We're all set.
dp = null;
}
/**
* Plain vanilla constructor for DuffPaneTest.
* @param arg0
*/
public DuffPaneTest(String arg0) {
super(arg0);
}
/** Invokes a text UI and runs all this class's tests. */
public static void main(String[] args) {
junit.textui.TestRunner.run(DuffPaneTest.class);
}
/** After ensuring that the caret is at the very end of the
* DuffPane's text, and that nothing is selected, this tells the
* DuffPane that the user has pressed key. */
private void fireKeypressWithoutModifiers(char key) {
dp.performKeyStroke(0, new String(new char[] { key }));
}
private void fireKeysWithoutModifiers(String x) {
for (int i = 0; i < x.length(); i++) {
fireKeypressWithoutModifiers(x.charAt(i));
}
}
private void ensureKeysGiveCorrectWylie(String wylie) {
ensureKeysGiveCorrectWylie(wylie, wylie);
}
private void ensureKeysGiveCorrectWylie(String keys, String wylie) {
dp.newDocument(); // initialize to a blank canvas.
fireKeysWithoutModifiers(keys);
boolean passes = wylie.equals(dp.getWylie());
if (!passes) {
System.out.println("Congrats! These keys, \"" + keys
+ "\", give this wylie, \"" + dp.getWylie()
+ "\", not the expected \"" + wylie + "\"");
}
assertTrue(passes);
}
/** Tests performing a few keystrokes in the Extended Wylie
* keyboard, turning those into our internal representation (IR),
* and then converting the result to Extended Wylie. */
public void testWylieToIRToWylie() {
ensureKeysGiveCorrectWylie("nga ");
ensureKeysGiveCorrectWylie("nag");
ensureKeysGiveCorrectWylie("bkra shis bde legs/");
ensureKeysGiveCorrectWylie("bakra shisa bade legs/",
"bkra shis bde legs/");
ensureKeysGiveCorrectWylie("sgom pa'am ");
ensureKeysGiveCorrectWylie("sgom pe'am ");
ensureKeysGiveCorrectWylie("le'u'i'o");
ensureKeysGiveCorrectWylie("la'u'i'o");
ensureKeysGiveCorrectWylie("la'u'i'o/la'am/pa'ang/pa'am'ang/pe'ang");
ensureKeysGiveCorrectWylie("bskyar.d'am'ang");
ensureKeysGiveCorrectWylie("lar.d");
ensureKeysGiveCorrectWylie("lard",
"larda");
ensureKeysGiveCorrectWylie("lal.d");
ensureKeysGiveCorrectWylie("lald",
"lalda");
ensureKeysGiveCorrectWylie("las.d");
ensureKeysGiveCorrectWylie("lasd",
"lasda");
ensureKeysGiveCorrectWylie("b.lar.d");
ensureKeysGiveCorrectWylie("blar.d");
ensureKeysGiveCorrectWylie("blarad",
"blar.d");
ensureKeysGiveCorrectWylie("b.lard");
ensureKeysGiveCorrectWylie("b.lal.d");
ensureKeysGiveCorrectWylie("blald",
"blalda");
ensureKeysGiveCorrectWylie("b.lald");
ensureKeysGiveCorrectWylie("b.las.d");
ensureKeysGiveCorrectWylie("blasd",
"blasda");
ensureKeysGiveCorrectWylie("b.lasd");
ensureKeysGiveCorrectWylie("b.lag");
ensureKeysGiveCorrectWylie("blg",
"blga");
ensureKeysGiveCorrectWylie("b.las",
"bals");
ensureKeysGiveCorrectWylie("bl.s",
"blas");
ensureKeysGiveCorrectWylie("bls",
"bals");
ensureKeysGiveCorrectWylie("b.rag");
ensureKeysGiveCorrectWylie("brg",
"brga");
ensureKeysGiveCorrectWylie("bars");
ensureKeysGiveCorrectWylie("b.rs",
"bars");
ensureKeysGiveCorrectWylie("brs",
"bars");
ensureKeysGiveCorrectWylie("br.s",
"bras");
ensureKeysGiveCorrectWylie("bras");
ensureKeysGiveCorrectWylie("d.wa");
ensureKeysGiveCorrectWylie("dawa",
"d.wa");
ensureKeysGiveCorrectWylie("dwa");
ensureKeysGiveCorrectWylie("g.wa");
ensureKeysGiveCorrectWylie("gawa",
"g.wa");
ensureKeysGiveCorrectWylie("gwa");
ensureKeysGiveCorrectWylie("'.wa",
"'wa");
ensureKeysGiveCorrectWylie("'awa",
"'wa");
ensureKeysGiveCorrectWylie("'wa");
ensureKeysGiveCorrectWylie("gyg",
"g.yag");
ensureKeysGiveCorrectWylie("g.yag");
ensureKeysGiveCorrectWylie("gyag");
ensureKeysGiveCorrectWylie("gy.g",
"gyag");
ensureKeysGiveCorrectWylie("gys",
"g.yas");
ensureKeysGiveCorrectWylie("g.yas");
ensureKeysGiveCorrectWylie("gyas");
ensureKeysGiveCorrectWylie("gy.s",
"gyas");
// FIXME: shouldn't this give the four-glyph combo m-a-a-s?
ensureKeysGiveCorrectWylie("ma.a.asa",
"mas");
ensureKeysGiveCorrectWylie("'ka");
ensureKeysGiveCorrectWylie("'gas");
ensureKeysGiveCorrectWylie("gangs");
ensureKeysGiveCorrectWylie("gnags");
ensureKeysGiveCorrectWylie("'angs");
ensureKeysGiveCorrectWylie("'ag");
ensureKeysGiveCorrectWylie("'byung");
ensureKeysGiveCorrectWylie("'byungs");
ensureKeysGiveCorrectWylie("b.lags");
ensureKeysGiveCorrectWylie("blags");
// DLC add b-r-g-s, b-l-g-s,
ensureKeysGiveCorrectWylie("mngas",
"mangs");
ensureKeysGiveCorrectWylie("mangs");
ensureKeysGiveCorrectWylie("mn.gs",
"mnags");
ensureKeysGiveCorrectWylie("mnags");
ensureKeysGiveCorrectWylie("lmn.g",
"lamanaga");
ensureKeysGiveCorrectWylie("l.m.ng",
"lamanga");
ensureKeysGiveCorrectWylie("b.m.ng",
"bmang");
ensureKeysGiveCorrectWylie("bmang");
ensureKeysGiveCorrectWylie("gdams");
ensureKeysGiveCorrectWylie("g.d.m.s.",
"gdams");
ensureKeysGiveCorrectWylie("'gams");
ensureKeysGiveCorrectWylie("'.g.m.s",
"'gams");
{
// These are correctly handled in terms of
// makeIllegalTibetanGoEndToEnd:
ensureKeysGiveCorrectWylie("skalazasa");
ensureKeysGiveCorrectWylie("jskad",
"jaskada");
}
{
// These are incorrectly handled in terms of
// makeIllegalTibetanGoEndToEnd. DLC FIXME.
ensureKeysGiveCorrectWylie("jeskad",
"jeskd");
ensureKeysGiveCorrectWylie("jeskd");
ensureKeysGiveCorrectWylie("jesakada",
"jeskd");
}
}
}

View File

@ -493,7 +493,10 @@ public class Jskad extends JPanel implements DocumentListener {
toolBar.add(keyboards);
toolBar.add(Box.createHorizontalGlue());
JScrollPane sp = new JScrollPane(dp, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JScrollPane sp
= new JScrollPane(dp,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
dp.getDocument().addDocumentListener(this);
if (parentObject instanceof JFrame) {
@ -867,14 +870,8 @@ public class Jskad extends JPanel implements DocumentListener {
try {
BufferedReader in = new BufferedReader(new FileReader(txt_fileChosen));
DuffPane dp2;
// FIXME: why do we need a whole DuffPane to do this? we
// definitely don't need a status bar...
if (ThdlOptions.getBooleanOption(Jskad.enableKeypressStatusProp)) {
dp2 = new DuffPane(statusBar);
} else {
dp2 = new DuffPane();
}
// FIXME: why do we need a whole DuffPane to do this?
DuffPane dp2 = new DuffPane();
try {
String val = in.readLine();
@ -886,14 +883,12 @@ public class Jskad extends JPanel implements DocumentListener {
TibetanDocument t_doc = (TibetanDocument)dp2.getDocument();
t_doc.writeRTFOutputStream(new FileOutputStream(new File(rtf_fileName)));
}
catch (IOException ioe) {
} catch (IOException ioe) {
ThdlDebug.noteIffyCode();
System.out.println("problem reading or writing file");
}
}
catch (FileNotFoundException fnfe) {
ThdlDebug.noteIffyCode();
} catch (FileNotFoundException fnfe) {
ThdlDebug.noteIffyCode();
System.out.println("problem reading file");
}
}

View File

@ -612,10 +612,15 @@ public static boolean isVowel(String s) {
*/
public static boolean isAmbiguousWylie(String x, String y) {
// What about ambiguity between wa-zur and wa? dwa vs. d.wa, e.g.?
// Doesn't matter, because that's illegal. wa doesn't take any
// prefixes.
// Some would say it doesn't matter, because that's illegal. wa
// doesn't take any prefixes. But I want even illegal stuff to
// work well end-to-end (i.e., converting tibetan X to wylie Y to
// tibetan Z should get you X==Z in a perfect world), and it
// doesn't confuse the legal stuff.
return (("g".equals(x) && "y".equals(y))
|| ("g".equals(x) && "w".equals(y))
|| ("d".equals(x) && "w".equals(y))
|| ("b".equals(x) && "l".equals(y))
|| ("b".equals(x) && "r".equals(y)));
}

View File

@ -210,6 +210,17 @@ public final class ThdlOptions {
/** to avoid initializing twice */
private static boolean isInitialized = false;
/** Call this when you're testing some code that uses the
* preferences mechanism provided by this class, and you don't
* want to use options.txt etc. with that code. You'll be
* relying on the defaults encoded in the calls to
* getBooleanOption etc. If you call this twice, it will wipe
* out preferences stored programmatically on each call. */
public static void forTestingOnlyInitializeWithoutDefaultOptionsFile() {
userProperties = new Properties(); // empty
isInitialized = true;
}
/** Sets userProperties so that it represents the entire, chained
preferences hierarchy.