2002-09-30 03:10:00 +00:00
|
|
|
/*
|
|
|
|
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 2001 THDL.
|
|
|
|
All Rights Reserved.
|
|
|
|
|
|
|
|
Contributor(s): ______________________________________.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package org.thdl.tib.input;
|
|
|
|
|
This may well be a fix to the "Improper line wrapping" bug. The fix
is basically that we use our own special ViewFactory, with a new
subclass of LabelView (the view RTFEditorKit uses for the nitty
gritty) that is aware of Tibetan.
There are a couple of nasty hacks still here, and Swing's
documentation for doing what I did was quite poor. I searched the web
for hours, read the Javadocs and the tutorials, and consulted a Swing
reference book, but I still don't have tremendous confidence in this
solution. If it fundamentally doesn't work, though, we have to define
our own first-class Document, Element hierarchy, ViewFactory, Views,
and EditorKit. So let's hope it *does* work fundamentally.
I can't say for sure if this even works, as I have yet to run this
code on a machine where Jskad works properly. I had major trouble
installing the TMW fonts on Linux, and have yet to resolve it, even
after verifying via xlsfonts that the fonts were installed and then
changing TibetanMachineWeb.java to look for them. Because I haven't
tested this yet, a lot of nasty code is tagged 'DLC' and commented
out.
2002-10-28 03:08:04 +00:00
|
|
|
import java.io.*;
|
2002-09-30 03:10:00 +00:00
|
|
|
import java.util.*;
|
|
|
|
import java.awt.*;
|
|
|
|
import java.awt.datatransfer.*;
|
|
|
|
import java.awt.font.*;
|
|
|
|
import java.awt.event.*;
|
|
|
|
import javax.swing.*;
|
|
|
|
import javax.swing.text.*;
|
|
|
|
import javax.swing.text.rtf.*;
|
|
|
|
|
This may well be a fix to the "Improper line wrapping" bug. The fix
is basically that we use our own special ViewFactory, with a new
subclass of LabelView (the view RTFEditorKit uses for the nitty
gritty) that is aware of Tibetan.
There are a couple of nasty hacks still here, and Swing's
documentation for doing what I did was quite poor. I searched the web
for hours, read the Javadocs and the tutorials, and consulted a Swing
reference book, but I still don't have tremendous confidence in this
solution. If it fundamentally doesn't work, though, we have to define
our own first-class Document, Element hierarchy, ViewFactory, Views,
and EditorKit. So let's hope it *does* work fundamentally.
I can't say for sure if this even works, as I have yet to run this
code on a machine where Jskad works properly. I had major trouble
installing the TMW fonts on Linux, and have yet to resolve it, even
after verifying via xlsfonts that the fonts were installed and then
changing TibetanMachineWeb.java to look for them. Because I haven't
tested this yet, a lot of nasty code is tagged 'DLC' and commented
out.
2002-10-28 03:08:04 +00:00
|
|
|
import org.thdl.tib.text.*;
|
2002-10-06 18:23:27 +00:00
|
|
|
import org.thdl.util.ThdlDebug;
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
import org.thdl.util.ThdlOptions;
|
2002-10-13 19:22:56 +00:00
|
|
|
import org.thdl.util.StatusBar;
|
2002-10-06 18:23:27 +00:00
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
/**
|
|
|
|
* Enables input of Tibetan text
|
|
|
|
* using Tibetan Computer Company's free cross-platform TibetanMachineWeb fonts.
|
|
|
|
* Two modes of text entry are allowed. In Tibetan mode, keystrokes are intercepted
|
|
|
|
* and reinterpreted according to the Tibetan keyboard installed. The result, of
|
|
|
|
* course, is Tibetan text, in the TibetanMachineWeb encoding. In Roman mode,
|
|
|
|
* keystrokes are not intercepted, and the font defaults to a Roman or user-defined font.
|
|
|
|
* @author Edward Garrett, Tibetan and Himalayan Digital Library
|
|
|
|
* @version 1.0
|
|
|
|
*/
|
|
|
|
public class DuffPane extends JTextPane implements KeyListener, FocusListener {
|
2002-10-13 19:22:56 +00:00
|
|
|
/**
|
|
|
|
* The status bar to update with messages about the current input mode.
|
|
|
|
* Are we expecting a vowel? a subscript? et cetera.
|
|
|
|
*/
|
|
|
|
private StatusBar statBar = null;
|
|
|
|
|
|
|
|
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* A central part of the Tibetan keyboard. As keys are typed, they are
|
|
|
|
* added to charList if they constitute a valid Wylie character. charList
|
|
|
|
* is added to in this manner until the user types punctuation, a vowel,
|
|
|
|
* or some action or function key. Later, when glyphs are printed to the
|
2002-10-28 04:49:24 +00:00
|
|
|
* screen, the {@link #newGlyphList} is computed on the basis of charList.
|
2002-09-30 03:10:00 +00:00
|
|
|
*/
|
2002-10-13 01:07:38 +00:00
|
|
|
private java.util.ArrayList charList;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* This field holds a copy of the last {@link #newGlyphList}.
|
|
|
|
* Then, when a key is pressed, {@link #charList} is updated, a new
|
|
|
|
* newGlyphList is computed, and the newGlyphList is compared against
|
|
|
|
* this field. The text on the screen is then modified to reflect
|
|
|
|
* the new newGlyphList.
|
|
|
|
*/
|
|
|
|
private java.util.List oldGlyphList;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* A central component of the Tibetan input method. While {@link #charList charList}
|
|
|
|
* keeps track of the characters that have been entered, it does not organize them
|
|
|
|
* correctly into the proper glyphs. For example, charList might have four characters
|
|
|
|
* in it, 'b', 's', 'g', and 'r', but it does not know that they should be drawn as
|
|
|
|
* two glyphs, 'b' and 's-g-r'. newGlyphList is a list of glyphs
|
2002-10-14 00:19:30 +00:00
|
|
|
* ({@link org.thdl.tib.text.DuffCode DuffCodes}) which is formed by
|
2002-09-30 03:10:00 +00:00
|
|
|
* @link #recomputeGlyphs(boolean areStacksOnRight, boolean definitelyTibetan, boolean definitelySanskrit) recomputeGlyphs},
|
|
|
|
* which constructs an optimal arrangement of glyphs from the charList.
|
|
|
|
*/
|
|
|
|
private java.util.List newGlyphList;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* This field keeps track of what is currently being typed, to account
|
|
|
|
* for characters (such as Wylie 'tsh') which correspond to more than one
|
|
|
|
* keystroke in the keyboard. It is cleared or readjusted when it is clear
|
|
|
|
* that the user has moved on to a different character. For example, after the
|
|
|
|
* user types 'khr', holdCurrent will contain only 'r', since 'khr' is not
|
|
|
|
* a valid character.
|
|
|
|
*/
|
|
|
|
private StringBuffer holdCurrent;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
|
|
|
* This field says whether or not the character atop {@link #charList}
|
|
|
|
* has been finalized, and therefore whether subsequent keystrokes are
|
|
|
|
* allowed to displace this character. For example, if 'k' is at the
|
|
|
|
* top of charList, and isTopHypothesis is true, then typing 'h' would
|
|
|
|
* replace 'k' with 'kh'. On the other hand, were isTopHypothesis
|
|
|
|
* false, then typing 'h' would add 'h' to the top of charList instead.
|
|
|
|
* In short, is the top character on {@link #charList} a fact or just a
|
|
|
|
* hypothesis?
|
2002-09-30 03:10:00 +00:00
|
|
|
*/
|
|
|
|
private boolean isTopHypothesis;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* Is the user in the process of typing a vowel?
|
|
|
|
*/
|
|
|
|
private boolean isTypingVowel;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* Is it definitely the case that the user is typing Tibetan, rather than
|
|
|
|
* Sanskrit?
|
|
|
|
*/
|
|
|
|
private boolean isDefinitelyTibetan;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* According to the active keyboard, what value
|
|
|
|
* {@link #isDefinitelyTibetan} should be assigned by default when the
|
|
|
|
* keyboard is initialized by {@link #initKeyboard() initKeyboard}
|
2002-09-30 03:10:00 +00:00
|
|
|
*/
|
|
|
|
private boolean isDefinitelyTibetan_default;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* According to the active keyboard, what value {@link
|
|
|
|
* #isDefinitelyTibetan} should be assigned if the user has initiated a
|
|
|
|
* stack by typing a stack key. For example, in the Wylie keyboard,
|
|
|
|
* there is a Sanskrit stacking key ('+'), but no Tibetan stacking key.
|
|
|
|
* Therefore, if the user is stacking with '+', this field should be
|
|
|
|
* false, since what the user is typing must be Sanskrit, not Tibetan. */
|
2002-09-30 03:10:00 +00:00
|
|
|
private boolean isDefinitelyTibetan_withStackKey;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* True iff it is definitely the case that the user is typing Sanskrit
|
|
|
|
* (for example a Sanskrit stack), rather than Tibetan
|
2002-09-30 03:10:00 +00:00
|
|
|
*/
|
|
|
|
private boolean isDefinitelySanskrit;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* According to the active keyboard, the value {@link
|
|
|
|
* #isDefinitelySanskrit} should be assigned by default when the
|
|
|
|
* keyboard is initialized by {@link #initKeyboard() initKeyboard}
|
2002-09-30 03:10:00 +00:00
|
|
|
*/
|
|
|
|
private boolean isDefinitelySanskrit_default;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* According to the active keyboard, the value that should
|
2002-09-30 03:10:00 +00:00
|
|
|
* be assigned to {@link #isDefinitelySanskrit} if the
|
2002-10-14 00:19:30 +00:00
|
|
|
* user has initiated a stack by typing a stack key.
|
2002-09-30 03:10:00 +00:00
|
|
|
* For example, in the Wylie keyboard, there is a Sanskrit
|
|
|
|
* stacking key ('+'), but no Tibetan stacking key.
|
|
|
|
* Therefore, if the user is stacking with '+', this field
|
|
|
|
* should be true, since what the user is typing must
|
|
|
|
* be Sanskrit, not Tibetan.
|
|
|
|
*/
|
|
|
|
private boolean isDefinitelySanskrit_withStackKey;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* True iff consonant stacking is allowed at the moment. In the Wylie
|
2002-09-30 03:10:00 +00:00
|
|
|
* keyboard, consonant stacking is usually on, since stacking
|
|
|
|
* is automatic. However, in the TCC and Sambhota keyboards,
|
|
|
|
* stacking is off by default, since you can only stack when
|
|
|
|
* you've pressed a stacking key.
|
|
|
|
*/
|
|
|
|
private boolean isStackingOn;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* True iff, according to the active keyboard, stacking is on by
|
|
|
|
* default assuming no stack key has been pressed.
|
2002-09-30 03:10:00 +00:00
|
|
|
*/
|
|
|
|
private boolean isStackingOn_default;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* Automatic stacking in Wylie is from right to left. For
|
|
|
|
* example, if the user types 'brg', the resulting glyph
|
|
|
|
* sequence is 'b' plus 'rg', not 'br' plus 'g'. If
|
|
|
|
* stacking results from the use of a stack key,
|
|
|
|
* it is from left to right.
|
|
|
|
*/
|
|
|
|
private boolean isStackingRightToLeft;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* used for tracking changes in Wylie to TMW conversion
|
|
|
|
*/
|
|
|
|
private int lastStart;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* true iff the user is in Tibetan typing mode. This is true
|
|
|
|
* by default.
|
2002-09-30 03:10:00 +00:00
|
|
|
*/
|
|
|
|
private boolean isTibetan = true;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-10-14 00:19:30 +00:00
|
|
|
* true iff the user is allowed to type non-Tibetan. This is true
|
2002-09-30 03:10:00 +00:00
|
|
|
* by default
|
|
|
|
*/
|
|
|
|
private boolean isRomanEnabled = true;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* The document displayed by this object.
|
|
|
|
*/
|
|
|
|
private TibetanDocument doc;
|
2002-10-13 18:40:07 +00:00
|
|
|
/**
|
2002-09-30 03:10:00 +00:00
|
|
|
* The caret of {@link #doc}, used to keep track of the
|
|
|
|
* current entry/edit/deletion position.
|
|
|
|
*/
|
|
|
|
private Caret caret;
|
|
|
|
// private StyledEditorKit editorKit;
|
|
|
|
private StyleContext styleContext;
|
|
|
|
private Style rootStyle;
|
|
|
|
private boolean skipUpdate = false;
|
|
|
|
private boolean isCutAndPasteEnabled = true;
|
|
|
|
|
|
|
|
private String romanFontFamily;
|
|
|
|
private int romanFontSize;
|
|
|
|
private MutableAttributeSet romanAttributeSet;
|
|
|
|
|
|
|
|
public Clipboard rtfBoard;
|
|
|
|
public DataFlavor rtfFlavor;
|
|
|
|
public RTFEditorKit rtfEd = null;
|
|
|
|
|
2002-10-22 03:53:33 +00:00
|
|
|
/** Initializes this object. All constructors should call
|
|
|
|
this. */
|
|
|
|
private void initialize(StatusBar sb,
|
|
|
|
TibetanKeyboard keyboard,
|
|
|
|
java.net.URL keyboardURL)
|
|
|
|
{
|
|
|
|
if (null != keyboard)
|
|
|
|
TibetanMachineWeb.setKeyboard(keyboard);
|
|
|
|
if (null != keyboardURL)
|
|
|
|
TibetanMachineWeb.setKeyboard(keyboardURL);
|
|
|
|
setupKeyboard();
|
|
|
|
setupEditor();
|
|
|
|
if (null != sb)
|
|
|
|
setStatusBar(sb);
|
|
|
|
// this(new StyledEditorKit(), keyboardURL);
|
|
|
|
}
|
|
|
|
|
2002-10-13 19:22:56 +00:00
|
|
|
/** Creates a new DuffPane that updates sb, if sb is not null,
|
|
|
|
with messages about how the users' keypresses are being
|
|
|
|
interpreted. */
|
|
|
|
public DuffPane(StatusBar sb) {
|
2002-10-22 03:53:33 +00:00
|
|
|
super();
|
|
|
|
initialize(sb, null, null);
|
2002-10-13 19:22:56 +00:00
|
|
|
}
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
public DuffPane() {
|
2002-10-22 03:53:33 +00:00
|
|
|
super();
|
|
|
|
initialize(null, null, null);
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public DuffPane(TibetanKeyboard keyboard) {
|
2002-10-22 03:53:33 +00:00
|
|
|
super();
|
|
|
|
initialize(null, keyboard, null);
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public DuffPane(java.net.URL keyboardURL) {
|
2002-10-22 03:53:33 +00:00
|
|
|
super();
|
|
|
|
initialize(null, null, keyboardURL);
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
2002-10-13 19:22:56 +00:00
|
|
|
/** Sets the status bar to update with mode information. If sb is
|
|
|
|
null, no status bar will be updated. */
|
|
|
|
public void setStatusBar(StatusBar sb) {
|
|
|
|
statBar = sb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** If we have a status bar, update it. */
|
2002-10-22 03:53:33 +00:00
|
|
|
protected void updateStatus(String newStatus) {
|
2002-10-13 19:22:56 +00:00
|
|
|
if (statBar != null) {
|
|
|
|
/* If we've seen this message just before, append " x2" to
|
|
|
|
the end of it. The third message will cause a toggle,
|
|
|
|
which you can tell is different, so that's fine. */
|
|
|
|
if (newStatus.equals(statBar.currentStatus())) {
|
|
|
|
newStatus = newStatus + " x2";
|
|
|
|
}
|
2002-11-03 17:05:05 +00:00
|
|
|
statBar.replaceStatus((isTopHypothesis ? "Guess: " : "Fact: ")
|
|
|
|
+ "[holding \"" + holdCurrent.toString() + "\"] "
|
|
|
|
+ newStatus);
|
2002-10-13 19:22:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** If we have a status bar, append msg to its current status. */
|
2002-10-22 03:53:33 +00:00
|
|
|
protected void appendStatus(String msg) {
|
2002-10-13 19:22:56 +00:00
|
|
|
if (statBar != null) {
|
|
|
|
statBar.replaceStatus(statBar.currentStatus() + msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
private static int defaultTibFontSize() {
|
|
|
|
// FIXME: at program exit, or when the user selects "Save
|
|
|
|
// preferences", or somehow, save the value the users chooses:
|
|
|
|
return ThdlOptions.getIntegerOption("thdl.default.tibetan.font.size",
|
|
|
|
36);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static int defaultRomanFontSize() {
|
|
|
|
// FIXME: at program exit, or when the user selects "Save
|
|
|
|
// preferences", or somehow, save the value the users chooses:
|
|
|
|
return ThdlOptions.getIntegerOption("thdl.default.roman.font.size",
|
|
|
|
14);
|
|
|
|
}
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
/**
|
|
|
|
* This method sets up the editor, assigns fonts and point sizes,
|
|
|
|
* sets the document, the caret, and adds key and focus listeners.
|
|
|
|
*/
|
2002-10-22 03:53:33 +00:00
|
|
|
private void setupEditor() {
|
2002-09-30 03:10:00 +00:00
|
|
|
rtfBoard = getToolkit().getSystemClipboard();
|
|
|
|
rtfFlavor = new DataFlavor("text/rtf", "Rich Text Format");
|
This may well be a fix to the "Improper line wrapping" bug. The fix
is basically that we use our own special ViewFactory, with a new
subclass of LabelView (the view RTFEditorKit uses for the nitty
gritty) that is aware of Tibetan.
There are a couple of nasty hacks still here, and Swing's
documentation for doing what I did was quite poor. I searched the web
for hours, read the Javadocs and the tutorials, and consulted a Swing
reference book, but I still don't have tremendous confidence in this
solution. If it fundamentally doesn't work, though, we have to define
our own first-class Document, Element hierarchy, ViewFactory, Views,
and EditorKit. So let's hope it *does* work fundamentally.
I can't say for sure if this even works, as I have yet to run this
code on a machine where Jskad works properly. I had major trouble
installing the TMW fonts on Linux, and have yet to resolve it, even
after verifying via xlsfonts that the fonts were installed and then
changing TibetanMachineWeb.java to look for them. Because I haven't
tested this yet, a lot of nasty code is tagged 'DLC' and commented
out.
2002-10-28 03:08:04 +00:00
|
|
|
rtfEd = new TibetanRTFEditorKit();
|
2002-09-30 03:10:00 +00:00
|
|
|
setEditorKit(rtfEd);
|
|
|
|
styleContext = new StyleContext();
|
|
|
|
|
|
|
|
doc = new TibetanDocument(styleContext);
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
doc.setTibetanFontSize(defaultTibFontSize());
|
2002-09-30 03:10:00 +00:00
|
|
|
setDocument(doc);
|
|
|
|
|
|
|
|
Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
|
|
|
|
StyleConstants.setFontFamily(defaultStyle, "TibetanMachineWeb");
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
StyleConstants.setFontSize(defaultStyle, defaultTibFontSize()); // FIXME make pref
|
2002-09-30 03:10:00 +00:00
|
|
|
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
romanFontFamily = ThdlOptions.getStringOption("thdl.default.roman.font.face",
|
|
|
|
"Serif"); // FIXME write out this preference.
|
|
|
|
romanFontSize = defaultRomanFontSize(); // FIXME make pref
|
2002-09-30 03:10:00 +00:00
|
|
|
setRomanAttributeSet(romanFontFamily, romanFontSize);
|
|
|
|
|
|
|
|
// newDocument();
|
|
|
|
caret = getCaret();
|
|
|
|
|
|
|
|
addKeyListener(this);
|
|
|
|
addFocusListener(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method sets up the Tibetan keyboard. Initially it is called
|
|
|
|
* by the constructor, but it is also called internally whenever
|
|
|
|
* the active keyboard is changed. It first sets various values with
|
|
|
|
* respect to stacking, and concerning the differences between
|
|
|
|
* Tibetan and Sanskrit; and then it initializes the input method.
|
|
|
|
*/
|
|
|
|
public void setupKeyboard() {
|
|
|
|
if (TibetanMachineWeb.hasTibetanStackingKey()) {
|
|
|
|
if (TibetanMachineWeb.hasSanskritStackingKey()) {
|
|
|
|
isDefinitelyTibetan_default = false;
|
|
|
|
isDefinitelySanskrit_default = false;
|
|
|
|
isStackingOn_default = false;
|
|
|
|
isDefinitelyTibetan_withStackKey = false;
|
|
|
|
isDefinitelySanskrit_withStackKey = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
isDefinitelyTibetan_default = false;
|
|
|
|
isDefinitelySanskrit_default = true;
|
|
|
|
isStackingOn_default = true;
|
|
|
|
isDefinitelyTibetan_withStackKey = true;
|
|
|
|
isDefinitelySanskrit_withStackKey = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (TibetanMachineWeb.hasSanskritStackingKey()) {
|
|
|
|
isDefinitelyTibetan_default = true;
|
|
|
|
isDefinitelySanskrit_default = false;
|
|
|
|
isStackingOn_default = true;
|
|
|
|
isDefinitelyTibetan_withStackKey = false;
|
|
|
|
isDefinitelySanskrit_withStackKey = true;
|
|
|
|
}
|
|
|
|
else { //no stacking key at all
|
|
|
|
isDefinitelyTibetan_default = false;
|
|
|
|
isDefinitelySanskrit_default = false;
|
|
|
|
isStackingOn_default = true;
|
|
|
|
}
|
|
|
|
}
|
2002-10-13 01:07:38 +00:00
|
|
|
charList = new ArrayList();
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = new ArrayList();
|
|
|
|
newGlyphList = new ArrayList();
|
|
|
|
initKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers the Extended Wylie keyboard, and sets it as
|
|
|
|
* the active keyboard.
|
|
|
|
* Unpredictable behavior will result
|
|
|
|
* if you set the keyboard in {@link org.thdl.tib.text.TibetanMachineWeb TibetanMachineWeb}
|
|
|
|
* but don't register it here.
|
|
|
|
*/
|
|
|
|
public void registerKeyboard() {
|
2002-10-22 03:53:33 +00:00
|
|
|
registerKeyboard((TibetanKeyboard)null);
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers a keyboard, and sets it as the active keyboard.
|
|
|
|
* Unpredictable behavior will result if you set the keyboard in {@link
|
|
|
|
* org.thdl.tib.text.TibetanMachineWeb TibetanMachineWeb} but don't
|
|
|
|
* register it in here.
|
|
|
|
* @param keyboardURL the URL of the keyboard you want to install */
|
|
|
|
public void registerKeyboard(java.net.URL keyboardURL) {
|
|
|
|
TibetanMachineWeb.setKeyboard(keyboardURL);
|
|
|
|
setupKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Registers a keyboard, and sets it as
|
|
|
|
* the active keyboard.
|
|
|
|
* Unpredictable behavior will result
|
|
|
|
* if you set the keyboard in {@link org.thdl.tib.text.TibetanMachineWeb TibetanMachineWeb}
|
|
|
|
* but don't register it in here.
|
|
|
|
* @param keyboard the keyboard you want to install
|
|
|
|
*/
|
|
|
|
public void registerKeyboard(TibetanKeyboard keyboard) {
|
|
|
|
TibetanMachineWeb.setKeyboard(keyboard);
|
|
|
|
setupKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Clears the current document.
|
|
|
|
*/
|
|
|
|
public void newDocument() {
|
|
|
|
styleContext = new StyleContext();
|
|
|
|
|
|
|
|
doc = new TibetanDocument(styleContext);
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
doc.setTibetanFontSize(defaultTibFontSize());
|
2002-09-30 03:10:00 +00:00
|
|
|
setDocument(doc);
|
|
|
|
|
|
|
|
Style defaultStyle = styleContext.getStyle(StyleContext.DEFAULT_STYLE);
|
|
|
|
StyleConstants.setFontFamily(defaultStyle, "TibetanMachineWeb");
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
StyleConstants.setFontSize(defaultStyle, defaultTibFontSize());
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes the keyboard input interpreter, setting all properties
|
|
|
|
* back to their default states. This method is called whenever an action
|
|
|
|
* or function key is pressed, and also whenever the user types punctuation
|
|
|
|
* or a vowel. It is not called when the user is typing characters that
|
|
|
|
* could be part of a stack, or require manipulation of glyphs - e.g.
|
|
|
|
* backspacing, redrawing, etc.
|
|
|
|
*/
|
2002-10-13 18:40:07 +00:00
|
|
|
private void initKeyboard() {
|
2002-10-13 19:22:56 +00:00
|
|
|
updateStatus("Jskad is in its basic input mode");
|
2002-09-30 03:10:00 +00:00
|
|
|
charList.clear();
|
|
|
|
oldGlyphList.clear();
|
|
|
|
holdCurrent = new StringBuffer();
|
|
|
|
isTopHypothesis = false;
|
|
|
|
isTypingVowel = false;
|
|
|
|
|
|
|
|
//for keyboard
|
|
|
|
isStackingOn = isStackingOn_default;
|
|
|
|
isStackingRightToLeft = true;
|
|
|
|
isDefinitelyTibetan = isDefinitelyTibetan_default;
|
|
|
|
isDefinitelySanskrit = isDefinitelySanskrit_default;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enables typing of Roman (non-Tibetan) text along
|
|
|
|
* with Tibetan.
|
|
|
|
*/
|
|
|
|
public void enableRoman() {
|
|
|
|
isRomanEnabled = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Disables typing of Roman (non-Tibetan) text.
|
|
|
|
*/
|
|
|
|
public void disableRoman() {
|
|
|
|
isRomanEnabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks to see if Roman input is enabled.
|
|
|
|
* @return true if so, false if not
|
|
|
|
*/
|
|
|
|
public boolean isRomanEnabled() {
|
|
|
|
return isRomanEnabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks to see if currently in Roman input mode.
|
|
|
|
* @return true if so, false if not
|
|
|
|
*/
|
|
|
|
public boolean isRomanMode() {
|
|
|
|
return !isTibetan;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Toggles between Tibetan and Roman input modes.
|
|
|
|
* Does nothing if Roman input is disabled.
|
|
|
|
* @see #enableRoman()
|
|
|
|
* @see #disableRoman()
|
|
|
|
*/
|
|
|
|
public void toggleLanguage() {
|
|
|
|
if (isTibetan && isRomanEnabled)
|
|
|
|
isTibetan = false;
|
|
|
|
else
|
|
|
|
isTibetan = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts Roman text into this object's document,
|
|
|
|
* at the position of the caret.
|
|
|
|
* @param attr the attributes for the text to insert
|
|
|
|
* @param s the string of text to insert
|
|
|
|
*/
|
|
|
|
public void append(String s, MutableAttributeSet attr) {
|
|
|
|
append(caret.getDot(), s, attr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts Roman text into this object's document.
|
|
|
|
* @param offset the position at which to insert text
|
|
|
|
* @param attr the attributes for the text to insert
|
|
|
|
* @param s the string of text to insert
|
|
|
|
*/
|
|
|
|
public void append(int offset, String s, MutableAttributeSet attr) {
|
|
|
|
try {
|
|
|
|
doc.insertString(offset, s, attr);
|
|
|
|
}
|
|
|
|
catch (BadLocationException ble) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Changes the default font size for Tibetan text entry mode.
|
|
|
|
*
|
|
|
|
* @param size a point size
|
|
|
|
*/
|
|
|
|
public void setTibetanFontSize(int size) {
|
|
|
|
if (size > 0)
|
|
|
|
doc.setTibetanFontSize(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the current point size for Tibetan text.
|
|
|
|
* @return the current default font size for Tibetan
|
|
|
|
* text entry mode
|
|
|
|
*/
|
|
|
|
public int getTibetanFontSize() {
|
|
|
|
return doc.getTibetanFontSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Changes the default font and font size for
|
|
|
|
* non-Tibetan (Roman) text entry mode.
|
|
|
|
*
|
|
|
|
* @param font a font name
|
|
|
|
* @param size a point size
|
|
|
|
*/
|
|
|
|
public void setRomanAttributeSet(String font, int size) {
|
|
|
|
romanAttributeSet = new SimpleAttributeSet();
|
|
|
|
StyleConstants.setFontFamily(romanAttributeSet, font);
|
|
|
|
StyleConstants.setFontSize(romanAttributeSet, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the current point size for non-Tibetan text.
|
|
|
|
* @return the current default font size for non-Tibetan
|
|
|
|
* (Roman) text entry mode
|
|
|
|
*/
|
|
|
|
public int getRomanFontSize() {
|
|
|
|
return romanFontSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the current font used for non-Tibetan text.
|
|
|
|
* @return the current default font for non-Tibetan
|
|
|
|
* (Roman) text entry mode
|
|
|
|
*/
|
|
|
|
public String getRomanFontFamily() {
|
|
|
|
return romanFontFamily;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Backspace and remove k elements from the current caret position.
|
|
|
|
*
|
|
|
|
* @param k the number of glyphs to remove by backspace
|
|
|
|
*/
|
|
|
|
private void backSpace(int k) {
|
|
|
|
try {
|
|
|
|
doc.remove(caret.getDot()-k, k);
|
|
|
|
}
|
|
|
|
catch (BadLocationException ble) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2002-11-02 05:21:12 +00:00
|
|
|
* Takes an old glyph list, which should be the currently visible set
|
|
|
|
* of glyphs preceding the cursor, and then tries to redraw the glyphs
|
|
|
|
* in light of the newly acquired keyboard input (which led to a
|
|
|
|
* revised 'new' glyph list). For example, the old glyph list might
|
|
|
|
* contain 'l' and 'n', because the user had typed 'ln' in Extended
|
|
|
|
* Wylie mode. This is what you'd see on the screen. But assume that
|
|
|
|
* the new glyph list contains the stacked glyph 'l-ng', because the
|
|
|
|
* user has just finished typing 'lng'. This method compares the
|
|
|
|
* glyphs, then figures out whether or not backspacing is necessary,
|
|
|
|
* and draws whatever characters need to be drawn.
|
|
|
|
*
|
|
|
|
* <p> For example, suppose that oldGlyphList contains the two glyphs
|
|
|
|
* 'l' and 'n', and newGlyphList contains a single glyph, 'lng'. In
|
|
|
|
* this case, redrawGlyphs will be instructed to backspace over both
|
|
|
|
* 'l' and 'n', and then insert 'lng'. */
|
2002-09-30 03:10:00 +00:00
|
|
|
private java.util.List redrawGlyphs(java.util.List oldGlyphList, java.util.List newGlyphList) {
|
|
|
|
if (newGlyphList.isEmpty())
|
|
|
|
return newGlyphList;
|
|
|
|
|
|
|
|
Iterator newIter = newGlyphList.iterator();
|
|
|
|
DuffCode newDc = (DuffCode)newIter.next();
|
|
|
|
|
|
|
|
int oldGlyphCount = oldGlyphList.size();
|
|
|
|
int newGlyphCount = newGlyphList.size();
|
|
|
|
int beginDifference = -1; //at what point does the new glyph list begin to differ from the old one?
|
|
|
|
int k=0;
|
|
|
|
|
|
|
|
if (oldGlyphCount!=0) {
|
|
|
|
int smallerGlyphCount;
|
|
|
|
DuffCode oldDc;
|
|
|
|
|
|
|
|
if (oldGlyphCount < newGlyphCount)
|
|
|
|
smallerGlyphCount = oldGlyphCount;
|
|
|
|
else
|
|
|
|
smallerGlyphCount = newGlyphCount;
|
|
|
|
|
|
|
|
Iterator oldIter = oldGlyphList.iterator();
|
|
|
|
|
|
|
|
for (; k<smallerGlyphCount; k++) {
|
|
|
|
oldDc = (DuffCode)oldIter.next();
|
|
|
|
|
|
|
|
if (!oldDc.equals(newDc)) {
|
|
|
|
beginDifference = k;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (newIter.hasNext())
|
|
|
|
newDc = (DuffCode)newIter.next();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (beginDifference == -1)
|
|
|
|
beginDifference = smallerGlyphCount;
|
|
|
|
|
|
|
|
if (beginDifference == newGlyphCount) {
|
|
|
|
if (oldGlyphCount > newGlyphCount)
|
|
|
|
backSpace(oldGlyphCount-newGlyphCount); //deals with 'pd+m' problem
|
|
|
|
|
|
|
|
return newGlyphList; //there is no difference between new and old glyph lists
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (beginDifference != -1)
|
|
|
|
backSpace(oldGlyphCount - beginDifference);
|
|
|
|
|
|
|
|
java.util.List sublist = newGlyphList.subList(k, newGlyphCount);
|
2002-11-02 03:38:59 +00:00
|
|
|
DuffData[] dd = TibTextUtils.convertGlyphs(sublist);
|
2002-09-30 03:10:00 +00:00
|
|
|
doc.insertDuff(caret.getDot(), dd);
|
|
|
|
return newGlyphList;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tries to insert the vowel v at the position of the caret.
|
|
|
|
* This method must deal with various issues, such as: can the preceding
|
|
|
|
* glyph take a vowel? If not, then what? If the preceding glyph can be
|
|
|
|
* followed by a vowel, then the method has to figure out what vowel
|
|
|
|
* glyph to affix, which may depend on the immediately preceding glyph,
|
|
|
|
* but may depend on other factors as well. For example, when affixing
|
|
|
|
* gigu to the consonantal stack "k'" (ie k plus achung), the value of
|
|
|
|
* the gigu will depend on "k", not "'".
|
|
|
|
*
|
|
|
|
* @param v the vowel (in Wylie) you want to insert
|
|
|
|
*/
|
|
|
|
private void putVowel(String v) {
|
|
|
|
if (caret.getDot()==0) {
|
|
|
|
if (!TibetanMachineWeb.isAChenRequiredBeforeVowel())
|
|
|
|
printAChenWithVowel(v);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
AttributeSet attr = doc.getCharacterElement(caret.getDot()-1).getAttributes();
|
|
|
|
String fontName = StyleConstants.getFontFamily(attr);
|
|
|
|
int fontNum;
|
|
|
|
|
|
|
|
if (0 != (fontNum = TibetanMachineWeb.getTMWFontNumber(fontName))) {
|
|
|
|
try {
|
|
|
|
char c2 = doc.getText(caret.getDot()-1, 1).charAt(0);
|
|
|
|
int k = (int)c2;
|
|
|
|
if (k<32 || k>126) { //if previous character is formatting or some other non-character
|
|
|
|
if (!TibetanMachineWeb.isAChenRequiredBeforeVowel())
|
|
|
|
printAChenWithVowel(v);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
String wylie = TibetanMachineWeb.getWylieForGlyph(fontNum, k);
|
|
|
|
if (TibetanMachineWeb.isWyliePunc(wylie)) {
|
|
|
|
if (charList.isEmpty() && !TibetanMachineWeb.isAChenRequiredBeforeVowel()) {
|
|
|
|
printAChenWithVowel(v);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DuffCode dc_1 = null;
|
|
|
|
DuffCode dc_2 = new DuffCode(fontNum, c2);
|
|
|
|
|
|
|
|
if (caret.getDot() > 2) {
|
|
|
|
attr = doc.getCharacterElement(caret.getDot()-2).getAttributes();
|
|
|
|
fontName = StyleConstants.getFontFamily(attr);
|
|
|
|
if (0 != (fontNum = TibetanMachineWeb.getTMWFontNumber(fontName))) {
|
|
|
|
c2 = doc.getText(caret.getDot()-2, 1).charAt(0);
|
|
|
|
dc_1 = new DuffCode(fontNum, c2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
java.util.List before_vowel = new ArrayList();
|
|
|
|
if (null != dc_1)
|
|
|
|
before_vowel.add(dc_1);
|
|
|
|
|
|
|
|
before_vowel.add(dc_2);
|
2002-11-02 03:38:59 +00:00
|
|
|
java.util.List after_vowel = TibTextUtils.getVowel(dc_1, dc_2, v);
|
2002-11-02 05:21:12 +00:00
|
|
|
if (after_vowel.size() >= before_vowel.size()) {
|
|
|
|
setNumberOfGlyphsForLastVowel(after_vowel.size()
|
|
|
|
- before_vowel.size());
|
|
|
|
} else {
|
|
|
|
setNumberOfGlyphsForLastVowel(0);
|
|
|
|
ThdlDebug.noteIffyCode(); // I don't think this can ever happen, but...
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
redrawGlyphs(before_vowel, after_vowel);
|
|
|
|
}
|
|
|
|
catch(BadLocationException ble) {
|
|
|
|
System.out.println("no--can't insert here");
|
2002-11-02 05:21:12 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else { //0 font means not Tibetan font, so begin new Tibetan font section
|
|
|
|
if (!TibetanMachineWeb.isAChenRequiredBeforeVowel())
|
|
|
|
printAChenWithVowel(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-02 05:21:12 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If the character last displayed was a vowel, this is how many glyphs
|
|
|
|
* the vowel was composed of. (Some vowels, such as Wylie 'I', consist
|
|
|
|
* of two glyphs.) We use the getter and setter for this variable and
|
|
|
|
* never the variable itself. */
|
|
|
|
private int numberOfGlyphsForLastVowel;
|
|
|
|
private int getNumberOfGlyphsForLastVowel() {
|
|
|
|
return numberOfGlyphsForLastVowel;
|
|
|
|
}
|
|
|
|
private void setNumberOfGlyphsForLastVowel(int x) {
|
|
|
|
numberOfGlyphsForLastVowel = x;
|
|
|
|
}
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
/**
|
|
|
|
* Prints ACHEN together with the vowel v. When using the Wylie
|
|
|
|
* keyboard, or any other keyboard in which {@link org.thdl.tib.text.TibetanMachineWeb#isAChenRequiredBeforeVowel() isAChenRequiredBeforeVowel()}
|
|
|
|
* is false, this method is called frequently.
|
|
|
|
*
|
|
|
|
* @param v the vowel (in Wylie) which you want to print with ACHEN
|
|
|
|
*/
|
|
|
|
private void printAChenWithVowel(String v) {
|
|
|
|
DuffCode[] dc_array = (DuffCode[])TibetanMachineWeb.getTibHash().get(TibetanMachineWeb.ACHEN);
|
|
|
|
DuffCode dc = dc_array[TibetanMachineWeb.TMW];
|
2002-11-02 03:38:59 +00:00
|
|
|
java.util.List achenlist = TibTextUtils.getVowel(dc,v);
|
|
|
|
DuffData[] dd = TibTextUtils.convertGlyphs(achenlist);
|
2002-09-30 03:10:00 +00:00
|
|
|
doc.insertDuff(caret.getDot(), dd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Puts a bindu/anusvara at the current caret position.
|
|
|
|
* In the TibetanMachineWeb font, top vowels (like gigu,
|
|
|
|
* drengbu, etc.) are merged together with bindu in a
|
|
|
|
* single glyph. This method deals with the problem of
|
|
|
|
* correctly displaying a bindu given this complication.
|
|
|
|
*/
|
|
|
|
private void putBindu() {
|
|
|
|
special_bindu_block: {
|
|
|
|
if (caret.getDot()==0)
|
|
|
|
break special_bindu_block;
|
|
|
|
|
|
|
|
AttributeSet attr = doc.getCharacterElement(caret.getDot()-1).getAttributes();
|
|
|
|
String fontName = StyleConstants.getFontFamily(attr);
|
|
|
|
int fontNum;
|
|
|
|
|
|
|
|
if (0 == (fontNum = TibetanMachineWeb.getTMWFontNumber(fontName)))
|
|
|
|
break special_bindu_block;
|
|
|
|
|
|
|
|
try {
|
|
|
|
char c2 = doc.getText(caret.getDot()-1, 1).charAt(0);
|
|
|
|
int k = (int)c2;
|
|
|
|
if (k<32 || k>126) //if previous character is formatting or some other non-character
|
|
|
|
break special_bindu_block;
|
|
|
|
|
|
|
|
String wylie = TibetanMachineWeb.getWylieForGlyph(fontNum, k);
|
|
|
|
if (!TibetanMachineWeb.isWylieVowel(wylie))
|
|
|
|
break special_bindu_block;
|
|
|
|
|
|
|
|
DuffCode dc = new DuffCode(fontNum, c2);
|
|
|
|
java.util.List beforecaret = new ArrayList();
|
|
|
|
beforecaret.add(dc);
|
2002-11-02 03:38:59 +00:00
|
|
|
java.util.List bindulist = TibTextUtils.getBindu(dc);
|
2002-09-30 03:10:00 +00:00
|
|
|
redrawGlyphs(beforecaret, bindulist);
|
|
|
|
initKeyboard();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
catch(BadLocationException ble) {
|
|
|
|
System.out.println("no--can't do this bindu maneuver");
|
2002-11-02 05:21:12 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-02 03:38:59 +00:00
|
|
|
DuffData[] dd = TibTextUtils.convertGlyphs(TibTextUtils.getBindu(null));
|
2002-09-30 03:10:00 +00:00
|
|
|
doc.insertDuff(caret.getDot(), dd);
|
|
|
|
initKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Required by implementations of the
|
|
|
|
* {@link java.awt.event.FocusListener FocusListener} interface,
|
|
|
|
* this method simply initializes the keyboard whenever this
|
|
|
|
* object gains focus.
|
|
|
|
*
|
|
|
|
* @param e a FocusEvent
|
|
|
|
*/
|
|
|
|
public void focusGained(FocusEvent e) {
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Required by implementations of the
|
|
|
|
* {@link java.awt.event.FocusListener FocusListener} interface,
|
2002-10-22 03:53:33 +00:00
|
|
|
* this method resets the keyboard.
|
2002-09-30 03:10:00 +00:00
|
|
|
*
|
|
|
|
* @param e a FocusEvent
|
|
|
|
*/
|
|
|
|
public void focusLost(FocusEvent e) {
|
|
|
|
initKeyboard();
|
2002-11-02 05:21:12 +00:00
|
|
|
setNumberOfGlyphsForLastVowel(0);
|
2002-10-22 03:53:33 +00:00
|
|
|
appendStatus(" (because the window focus was lost)");
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class RTFSelection implements ClipboardOwner, Transferable {
|
|
|
|
DataFlavor[] supportedFlavor;
|
|
|
|
ByteArrayOutputStream rtfOut;
|
|
|
|
String plainText;
|
|
|
|
|
|
|
|
RTFSelection(StyledDocument doc, 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 = doc.getText(i,1);
|
|
|
|
AttributeSet as = doc.getCharacterElement(i).getAttributes();
|
|
|
|
newDoc.insertString(i-offset, s, as);
|
|
|
|
} catch (BadLocationException ble) {
|
|
|
|
ble.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
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();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
} catch (IOException ioe) {
|
|
|
|
ioe.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
public void lostOwnership(Clipboard clipboard, Transferable contents) {
|
|
|
|
}
|
|
|
|
public Object getTransferData(DataFlavor flavor) {
|
|
|
|
if (flavor.equals(rtfFlavor))
|
|
|
|
return new ByteArrayInputStream(rtfOut.toByteArray());
|
|
|
|
if (flavor.equals(DataFlavor.stringFlavor))
|
|
|
|
return plainText;
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
public DataFlavor[] getTransferDataFlavors() {
|
|
|
|
return supportedFlavor;
|
|
|
|
}
|
|
|
|
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
|
|
|
for (int i=0; i<supportedFlavor.length; i++)
|
|
|
|
if (flavor.equals(supportedFlavor[i]))
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-22 03:53:33 +00:00
|
|
|
/** Copies the current selection to the system clipboard, unless
|
|
|
|
cut-and-paste operations are disabled. */
|
|
|
|
public void copyCurrentSelection() {
|
|
|
|
copy(getSelectionStart(), getSelectionEnd(), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** If this.isEditable(), then this copies the current selection
|
|
|
|
to the system clipboard and then deletes it. */
|
|
|
|
public void cutCurrentSelection() {
|
|
|
|
copy(getSelectionStart(), getSelectionEnd(), true);
|
|
|
|
}
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
/**
|
|
|
|
* Cuts or copies the specified portion of this object's document
|
|
|
|
* to the system clipboard. What is cut/copied is Wylie text -
|
|
|
|
* so, if you cut/copy a region of TibetanMachineWeb, it first converts
|
|
|
|
* it to Wylie before putting it on the clipboard. If the user
|
|
|
|
* tries to cut/copy non-TibetanMachineWeb, only the text preceding the
|
|
|
|
* first non-TibetanMachineWeb character is cut/copied.
|
|
|
|
* @param start the begin offset of the copy
|
|
|
|
* @param end the end offset of the copy
|
|
|
|
* @param remove this should be true if the operation is 'cut',
|
|
|
|
* false if it is 'copy'
|
|
|
|
*/
|
2002-10-22 03:53:33 +00:00
|
|
|
private void copy(int start, int end, boolean remove) {
|
|
|
|
updateStatus("Copied to clipboard");
|
2002-09-30 03:10:00 +00:00
|
|
|
int p1 = start;
|
|
|
|
int p2 = end;
|
|
|
|
if (p1 != p2) {
|
|
|
|
RTFSelection rtfSelection = new RTFSelection((StyledDocument)getDocument(), p1, p2-p1);
|
|
|
|
try {
|
|
|
|
rtfBoard.setContents(rtfSelection, rtfSelection);
|
|
|
|
} catch (IllegalStateException ise) {
|
|
|
|
ise.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
|
|
|
if (remove) {
|
|
|
|
// Respect setEditable(boolean):
|
|
|
|
if (!this.isEditable())
|
|
|
|
return;
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
try {
|
|
|
|
getDocument().remove(p1, p2-p1);
|
|
|
|
} catch (BadLocationException ble) {
|
|
|
|
ble.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Pastes the contents of the system clipboard into this object's
|
|
|
|
* document, at the specified position. The only kind of
|
|
|
|
* text accepted from the clipboard is Wylie text.
|
|
|
|
* This Wylie is converted and pasted into the document as
|
|
|
|
* TibetanMachineWeb. If the text to paste is invalid Wylie,
|
|
|
|
* then it will not be pasted, and instead an error message will
|
|
|
|
* appear.
|
|
|
|
* @param offset the position in the document you want to paste to
|
|
|
|
*/
|
|
|
|
public void paste(int offset) {
|
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
|
|
|
// Respect setEditable(boolean):
|
|
|
|
if (!this.isEditable())
|
|
|
|
return;
|
2002-09-30 03:10:00 +00:00
|
|
|
try {
|
|
|
|
Transferable contents = rtfBoard.getContents(this);
|
2002-10-25 17:34:30 +00:00
|
|
|
|
2002-10-25 19:47:14 +00:00
|
|
|
/*
|
|
|
|
if (!isRomanEnabled) {
|
|
|
|
if (contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
|
|
|
|
String data = (String)contents.getTransferData(DataFlavor.stringFlavor);
|
|
|
|
toTibetanMachineWeb(data, offset);
|
|
|
|
}
|
|
|
|
} else if (contents.isDataFlavorSupported(rtfFlavor)) {
|
|
|
|
*/
|
|
|
|
|
2002-10-25 17:59:27 +00:00
|
|
|
if (contents.isDataFlavorSupported(rtfFlavor)){
|
2002-10-25 19:47:14 +00:00
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
InputStream in = (InputStream)contents.getTransferData(rtfFlavor);
|
|
|
|
int p1 = offset;
|
|
|
|
|
|
|
|
//construct new document that contains only portion of text you want to paste
|
|
|
|
StyledDocument sd = new DefaultStyledDocument();
|
2002-10-22 03:53:33 +00:00
|
|
|
|
|
|
|
// I swear this happened once when I pasted in some
|
|
|
|
// random junk just after Jskad started up.
|
|
|
|
ThdlDebug.verify(null != in);
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
rtfEd.read(in, sd, 0);
|
2002-10-26 18:15:34 +00:00
|
|
|
|
|
|
|
/** Added by AM, to fix copy-paste issues for Translation Tool.
|
|
|
|
Assumes that if roman is disabled and you are pasting something
|
|
|
|
in RTF but is not TibetanMachineWeb it most be wylie.
|
|
|
|
*/
|
|
|
|
if (!sd.getFont((sd.getCharacterElement(0).getAttributes())).getFamily().equals("TibetanMachineWeb") && !isRomanEnabled && contents.isDataFlavorSupported(DataFlavor.stringFlavor))
|
|
|
|
{
|
|
|
|
String data = (String)contents.getTransferData(DataFlavor.stringFlavor);
|
|
|
|
toTibetanMachineWeb(data, offset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (int i=0; i<sd.getLength()-1; i++) { //getLength()-1 so that final newline is not included in paste
|
|
|
|
try {
|
|
|
|
String s = sd.getText(i,1);
|
|
|
|
AttributeSet as = sd.getCharacterElement(i).getAttributes();
|
|
|
|
doc.insertString(p1+i, s, as);
|
|
|
|
} catch (BadLocationException ble) {
|
|
|
|
ble.printStackTrace();
|
|
|
|
ThdlDebug.noteIffyCode();
|
|
|
|
}
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
2002-10-25 17:59:27 +00:00
|
|
|
} else if (contents.isDataFlavorSupported(DataFlavor.stringFlavor))
|
|
|
|
{
|
|
|
|
if (!isRomanEnabled) {
|
|
|
|
String data = (String)contents.getTransferData(DataFlavor.stringFlavor);
|
|
|
|
toTibetanMachineWeb(data, offset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
String s = (String)contents.getTransferData(DataFlavor.stringFlavor);
|
|
|
|
replaceSelection(s);
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
} catch (UnsupportedFlavorException ufe) {
|
|
|
|
ufe.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
} catch (IOException ioe) {
|
|
|
|
ioe.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
} catch (IllegalStateException ise) {
|
|
|
|
ise.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
} catch (BadLocationException ble) {
|
|
|
|
ble.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Enables cutting and pasting of Tibetan text.
|
|
|
|
*/
|
|
|
|
public void enableCutAndPaste() {
|
|
|
|
isCutAndPasteEnabled = true;
|
|
|
|
}
|
|
|
|
|
2002-10-22 03:53:33 +00:00
|
|
|
/** Returns true iff cut-and-paste operations are enabled. */
|
|
|
|
public boolean isCutAndPasteOn() {
|
|
|
|
return isCutAndPasteEnabled;
|
|
|
|
}
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
/**
|
|
|
|
* Disables cutting and pasting of Tibetan text.
|
|
|
|
* Cut and paste must be disabled if Jskad's
|
|
|
|
* parent is an applet, because it violates the
|
|
|
|
* Java security sandbox to cut and paste from an
|
|
|
|
* applet to the system clipboard.
|
|
|
|
*/
|
|
|
|
public void disableCutAndPaste() {
|
|
|
|
isCutAndPasteEnabled = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This method is required as part of the
|
|
|
|
* implementation of the KeyListener
|
|
|
|
* interface.
|
|
|
|
*
|
|
|
|
* Basically this method only handles action keys -
|
|
|
|
* Escape, Ctrl-c, Ctrl-x, etc, and TAB and ENTER.
|
|
|
|
* Other keystrokes are handled by keyTyped.
|
|
|
|
*/
|
|
|
|
public void keyPressed(KeyEvent e) {
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
// FIXME: exceptions thrown here do not cause the program to fail, even in development mode.
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
if (e.isActionKey())
|
|
|
|
initKeyboard();
|
|
|
|
|
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
|
|
|
switch (e.getKeyCode()) {
|
2002-09-30 03:10:00 +00:00
|
|
|
case KeyEvent.VK_ESCAPE:
|
|
|
|
e.consume();
|
|
|
|
initKeyboard();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_A:
|
|
|
|
if (e.isControlDown() && isCutAndPasteEnabled) {
|
|
|
|
e.consume();
|
|
|
|
setSelectionStart(0);
|
|
|
|
setSelectionEnd(doc.getLength());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_C:
|
|
|
|
if (e.isControlDown() && isCutAndPasteEnabled) {
|
|
|
|
e.consume();
|
|
|
|
copy(getSelectionStart(), getSelectionEnd(), false);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_X:
|
|
|
|
if (e.isControlDown() && isCutAndPasteEnabled) {
|
|
|
|
e.consume();
|
|
|
|
copy(getSelectionStart(), getSelectionEnd(), true);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_V:
|
|
|
|
if (e.isControlDown() && isCutAndPasteEnabled) {
|
|
|
|
e.consume();
|
|
|
|
paste(caret.getDot());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_TAB:
|
|
|
|
e.consume();
|
2002-10-22 03:53:33 +00:00
|
|
|
if (this.isEditable()) {
|
|
|
|
initKeyboard();
|
|
|
|
if (isTibetan)
|
|
|
|
doc.appendDuff(caret.getDot()," ",TibetanMachineWeb.getAttributeSet(1));
|
|
|
|
else
|
|
|
|
append(" ", romanAttributeSet);
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_ENTER:
|
|
|
|
e.consume();
|
2002-10-22 03:53:33 +00:00
|
|
|
if (this.isEditable()) {
|
|
|
|
initKeyboard();
|
|
|
|
if (isTibetan)
|
|
|
|
doc.appendDuff(caret.getDot(),"\n",TibetanMachineWeb.getAttributeSet(1)); // FIXME does this work on all platforms?
|
|
|
|
else
|
|
|
|
append("\n", romanAttributeSet); // FIXME does this work on all platforms?
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Required of implementations of the Key Listener interface,
|
|
|
|
* this method does (almost) nothing.
|
|
|
|
*
|
|
|
|
* @param e the KeyEvent
|
|
|
|
*/
|
|
|
|
public void keyReleased(KeyEvent e) {
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
// FIXME: exceptions thrown here do not cause the program to fail, even in development mode.
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
/*
|
|
|
|
* Apparently it works best to check for backspace
|
|
|
|
* and init the keyboard here in key released
|
|
|
|
* though i don't really know why...
|
|
|
|
*/
|
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
|
|
|
if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE)
|
2002-09-30 03:10:00 +00:00
|
|
|
initKeyboard();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Required of implementations of the KeyListener interface,
|
|
|
|
* this method handles the pressing of non-control and non-action keys. If the user
|
|
|
|
* is in Tibetan typing mode, then the KeyEvent
|
|
|
|
* e is consumed, and passed on to {@link #processTibetan(KeyEvent e)}, which
|
|
|
|
* contains the meat of the keyboard logic. If the user is in English mode, then
|
|
|
|
* {@link #append(String s, MutableAttributeSet attr) append} is called.
|
|
|
|
*
|
|
|
|
* @param e a KeyEvent
|
|
|
|
*/
|
|
|
|
public void keyTyped(KeyEvent e) {
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
// FIXME: exceptions thrown here do not cause the program to fail, even in development mode.
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
e.consume();
|
|
|
|
|
Fixed bug 617156, "DuffPane ignores setEditable(false)".
I fixed this the easy way, by checking the value of isEditable() before
cutting, pasting, or adding typed text. I may have missed a spot, but
checking at a lower level is a bit less efficient.
Fixing this the hard way, the keymaps-and-overridden-default-action way,
seems like it will make the code uglier, not cleaner. And it won't get us
closer to fixing the killer bug, 614475, "Improper Line Wrapping".
2002-10-20 05:54:29 +00:00
|
|
|
// Respect setEditable(boolean):
|
|
|
|
if (!this.isEditable())
|
|
|
|
return;
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
if (isTibetan)
|
|
|
|
processTibetan(e);
|
|
|
|
else {
|
|
|
|
if (e.isControlDown() || e.isAltDown())
|
|
|
|
return;
|
|
|
|
|
|
|
|
char c = e.getKeyChar();
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case KeyEvent.VK_TAB:
|
|
|
|
case KeyEvent.VK_ENTER:
|
|
|
|
case KeyEvent.VK_ESCAPE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_BACK_SPACE:
|
|
|
|
backSpace(1);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
append(String.valueOf(c), romanAttributeSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Interprets a key typed during Tibetan input mode.
|
|
|
|
* This method keeps track of which characters the user has and is typing,
|
|
|
|
* and also of whether or not the user is in stacking
|
|
|
|
* mode. Most of the keyboard logic can be found here.
|
|
|
|
*
|
2002-10-13 19:22:56 +00:00
|
|
|
* If there is a nonnull status bar to be updated (passed to the
|
|
|
|
* constructor), let's explain to the user which mode we're in, why
|
|
|
|
* their keypress has changed nothing, etc. At present, this is really
|
|
|
|
* for developers to understand what's going on. For example, if you
|
|
|
|
* type s-g-r, you see a single glyph, a three-letter stack, but if you
|
|
|
|
* type s-d-r, you see two glyphs. If you examine the status bar,
|
|
|
|
* you'll see that the thing determining that is
|
2002-11-02 03:38:59 +00:00
|
|
|
* TibTextUtils.getGlyphs, which in turn relies on 'tibwn.ini'.
|
2002-10-13 19:22:56 +00:00
|
|
|
*
|
|
|
|
* @param e a KeyEvent */
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
public void processTibetan(KeyEvent kev) {
|
2002-09-30 03:10:00 +00:00
|
|
|
boolean shouldIBackSpace = true;
|
|
|
|
|
2002-10-22 03:53:33 +00:00
|
|
|
// We don't handle just any old keypress. We handle only the
|
|
|
|
// ones that enter text.
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
if (kev.isControlDown() || kev.isAltDown())
|
2002-09-30 03:10:00 +00:00
|
|
|
return;
|
|
|
|
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
{
|
|
|
|
int start = getSelectionStart();
|
|
|
|
int end = getSelectionEnd();
|
|
|
|
if (start != end) {
|
|
|
|
if (kev.getKeyCode() != KeyEvent.VK_ESCAPE) {
|
|
|
|
try {
|
|
|
|
initKeyboard();
|
|
|
|
doc.remove(start, end-start);
|
|
|
|
shouldIBackSpace = false;
|
|
|
|
}
|
|
|
|
catch (BadLocationException ble) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
processTibetanChar(kev.getKeyChar(), shouldIBackSpace);
|
|
|
|
}
|
|
|
|
|
2002-11-03 17:05:05 +00:00
|
|
|
/** Utility method used by processTibetan(keyEvent).
|
|
|
|
@param c the character the user entered in whatever keyboard
|
|
|
|
is in use
|
|
|
|
@param shouldIBackSpace false iff a press of the backspace key
|
|
|
|
should not backspace, such as when you've selected some text
|
|
|
|
and then pressed backspace
|
|
|
|
@see #processTibetan(KeyEvent) */
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
private void processTibetanChar(char c, boolean shouldIBackSpace) {
|
2002-09-30 03:10:00 +00:00
|
|
|
|
2002-10-22 03:53:33 +00:00
|
|
|
// Have we modified the status bar?
|
|
|
|
boolean changedStatus = false;
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
key_block:
|
|
|
|
{
|
|
|
|
|
|
|
|
if (TibetanMachineWeb.hasDisambiguatingKey())
|
|
|
|
if (c == TibetanMachineWeb.getDisambiguatingKey()) {
|
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because you pressed the disambiguating key)");
|
2002-09-30 03:10:00 +00:00
|
|
|
break key_block;
|
|
|
|
};
|
|
|
|
|
|
|
|
if (TibetanMachineWeb.hasSanskritStackingKey() || TibetanMachineWeb.hasTibetanStackingKey()) {
|
|
|
|
if (c == TibetanMachineWeb.getStackingKey()) {
|
|
|
|
if (TibetanMachineWeb.isStackingMedial()) {
|
|
|
|
int size = charList.size();
|
|
|
|
|
2002-10-13 18:40:07 +00:00
|
|
|
if (size == 0) {
|
2002-09-30 03:10:00 +00:00
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because you pressed the stacking key with nothing to stack on)");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else if (size > 1 && isStackingRightToLeft) {
|
2002-10-13 01:07:38 +00:00
|
|
|
String s = (String)charList.remove(charList.size() - 1);
|
2002-11-02 03:38:59 +00:00
|
|
|
newGlyphList = TibTextUtils.getGlyphs(charList, isStackingRightToLeft, isDefinitelyTibetan, isDefinitelySanskrit);
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = redrawGlyphs(oldGlyphList, newGlyphList);
|
|
|
|
initKeyboard();
|
|
|
|
charList.add(s);
|
2002-11-02 03:38:59 +00:00
|
|
|
newGlyphList = TibTextUtils.getGlyphs(charList, isStackingRightToLeft, isDefinitelyTibetan, isDefinitelySanskrit);
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = redrawGlyphs(oldGlyphList, newGlyphList);
|
|
|
|
holdCurrent = new StringBuffer();
|
|
|
|
isTopHypothesis = false;
|
|
|
|
isStackingOn = true;
|
|
|
|
isStackingRightToLeft = false;
|
|
|
|
isDefinitelyTibetan = isDefinitelyTibetan_withStackKey;
|
|
|
|
isDefinitelySanskrit = isDefinitelySanskrit_withStackKey;
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("You have stacked a letter atop another.");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else {
|
2002-09-30 03:10:00 +00:00
|
|
|
holdCurrent = new StringBuffer();
|
|
|
|
isTopHypothesis = false;
|
|
|
|
isStackingOn = true;
|
|
|
|
isStackingRightToLeft = false;
|
|
|
|
isDefinitelyTibetan = isDefinitelyTibetan_withStackKey;
|
|
|
|
isDefinitelySanskrit = isDefinitelySanskrit_withStackKey;
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("Some sort of stack-fu is happening/has happened.");
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
break key_block;
|
|
|
|
}
|
|
|
|
else { //stacking must be pre/post
|
|
|
|
if (!isStackingOn || (isStackingOn && isDefinitelyTibetan==isDefinitelyTibetan_default)) {
|
|
|
|
initKeyboard();
|
|
|
|
isStackingOn = true;
|
|
|
|
isStackingRightToLeft = false;
|
|
|
|
isDefinitelyTibetan = isDefinitelyTibetan_withStackKey;
|
|
|
|
isDefinitelySanskrit = isDefinitelySanskrit_withStackKey;
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("!isStackingOn || (isStackingOn && isDefinitelyTibetan==isDefinitelyTibetan_default)");
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
else {try {
|
|
|
|
char ch = doc.getText(caret.getDot()-1, 1).charAt(0);
|
|
|
|
AttributeSet attr = doc.getCharacterElement(caret.getDot()-1).getAttributes();
|
|
|
|
String fontName = StyleConstants.getFontFamily(attr);
|
|
|
|
int fontNum = TibetanMachineWeb.getTMWFontNumber(fontName);
|
|
|
|
|
|
|
|
if (0 == fontNum) {
|
|
|
|
initKeyboard();
|
|
|
|
isStackingOn = true;
|
|
|
|
isStackingRightToLeft = false;
|
|
|
|
isDefinitelyTibetan = isDefinitelyTibetan_withStackKey;
|
|
|
|
isDefinitelySanskrit = isDefinitelySanskrit_withStackKey;
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because 0 == fontNum)");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else {
|
2002-09-30 03:10:00 +00:00
|
|
|
initKeyboard();
|
|
|
|
DuffCode dc = new DuffCode(fontNum, ch);
|
|
|
|
|
|
|
|
if (!TibetanMachineWeb.isStack(dc) && !TibetanMachineWeb.isSanskritStack(dc)) {
|
|
|
|
isStackingOn = true;
|
|
|
|
isStackingRightToLeft = false;
|
|
|
|
isDefinitelyTibetan = isDefinitelyTibetan_withStackKey;
|
|
|
|
isDefinitelySanskrit = isDefinitelySanskrit_withStackKey;
|
|
|
|
}
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because 0 != fontNum)");
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (BadLocationException ble) {
|
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because a BadLocationException was thrown)");
|
2002-09-30 03:10:00 +00:00
|
|
|
}}
|
|
|
|
break key_block;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case KeyEvent.VK_TAB:
|
|
|
|
case KeyEvent.VK_ENTER:
|
|
|
|
case KeyEvent.VK_ESCAPE:
|
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because you typed enter, tab, or escape)");
|
2002-09-30 03:10:00 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case KeyEvent.VK_BACK_SPACE:
|
|
|
|
if (shouldIBackSpace) {
|
|
|
|
backSpace(1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
String val = String.valueOf(c);
|
|
|
|
|
|
|
|
if (TibetanMachineWeb.isPunc(val)) { //punctuation
|
|
|
|
val = TibetanMachineWeb.getWylieForPunc(val);
|
|
|
|
|
|
|
|
if (val.charAt(0) == TibetanMachineWeb.BINDU)
|
|
|
|
putBindu();
|
|
|
|
|
|
|
|
else {
|
|
|
|
DuffCode puncDc = TibetanMachineWeb.getGlyph(val);
|
|
|
|
MutableAttributeSet mas = TibetanMachineWeb.getAttributeSet(puncDc.getFontNum());
|
|
|
|
doc.appendDuff(caret.getDot(), String.valueOf(puncDc.getCharacter()), mas);
|
|
|
|
}
|
|
|
|
|
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because you typed punctuation)");
|
2002-10-13 18:40:07 +00:00
|
|
|
break key_block; /* DLC is this right? */
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (charList.size()==0) { //add current character to charList if possible
|
|
|
|
holdCurrent.append(c);
|
|
|
|
String s = holdCurrent.toString();
|
|
|
|
|
|
|
|
if (TibetanMachineWeb.isVowel(s)) {
|
|
|
|
s = TibetanMachineWeb.getWylieForVowel(s);
|
|
|
|
|
2002-11-02 05:21:12 +00:00
|
|
|
if (isTypingVowel) {
|
|
|
|
//note: this takes care of multiple keystroke vowels like 'ai'
|
|
|
|
backSpace(getNumberOfGlyphsForLastVowel());
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
|
|
|
|
putVowel(s);
|
|
|
|
isTypingVowel = true;
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("You typed a vowel (the simple way).");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else {
|
2002-09-30 03:10:00 +00:00
|
|
|
if (isTypingVowel) {
|
|
|
|
isTypingVowel = false;
|
|
|
|
s = String.valueOf(c);
|
|
|
|
holdCurrent = new StringBuffer(s);
|
2002-10-13 18:40:07 +00:00
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
|
|
|
|
if (TibetanMachineWeb.isVowel(s)) {
|
|
|
|
s = TibetanMachineWeb.getWylieForVowel(s);
|
|
|
|
putVowel(s);
|
|
|
|
isTypingVowel = true;
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("You typed a vowel (the other way).");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else if (TibetanMachineWeb.isChar(s)) {
|
2002-09-30 03:10:00 +00:00
|
|
|
s = TibetanMachineWeb.getWylieForChar(s);
|
|
|
|
charList.add(s);
|
|
|
|
isTopHypothesis = true;
|
2002-11-02 03:38:59 +00:00
|
|
|
newGlyphList = TibTextUtils.getGlyphs(charList, isStackingRightToLeft, isDefinitelyTibetan, isDefinitelySanskrit);
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = redrawGlyphs(oldGlyphList, newGlyphList);
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("You typed a non-vowel, Tibetan character.");
|
2002-11-02 05:21:12 +00:00
|
|
|
} else {
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
if (TibetanMachineWeb.hasInputPrefix(s)) {
|
|
|
|
isTopHypothesis = false;
|
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("incomplete input (like the \"S\" in Extended Wylie's \"Sh\")");
|
|
|
|
} else {
|
2002-11-03 17:05:05 +00:00
|
|
|
// before we call initKeyboard, get info to prevent infinite loops:
|
|
|
|
StringBuffer prevHoldCurrent = new StringBuffer(holdCurrent.toString());
|
|
|
|
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
// FIXME: ring a bell here so the user knows what's up.
|
|
|
|
initKeyboard();
|
|
|
|
|
|
|
|
// The recursive call to
|
|
|
|
// processTibetanChar will update the
|
|
|
|
// status bar, so set this to true:
|
|
|
|
changedStatus = true;
|
|
|
|
|
|
|
|
// This status message is bound to get
|
|
|
|
// overridden, but this is what we
|
|
|
|
// would say if we had a queue of
|
|
|
|
// messages or something like Emacs's
|
|
|
|
// M-x view-lossage to see a history
|
|
|
|
// of status messages:
|
2002-11-03 17:05:05 +00:00
|
|
|
appendStatus(" (because you typed something invalid [1st way])");
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
|
2002-11-03 17:05:05 +00:00
|
|
|
if (prevHoldCurrent.length() != 0
|
|
|
|
&& !prevHoldCurrent.toString().equals(String.valueOf(c))) {
|
|
|
|
processTibetanChar(c, false);
|
|
|
|
}
|
|
|
|
// else we'd go into an infinite loop
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
}
|
2002-11-02 05:21:12 +00:00
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
2002-10-13 18:40:07 +00:00
|
|
|
} else { //there is already a character in charList
|
2002-09-30 03:10:00 +00:00
|
|
|
holdCurrent.append(c);
|
|
|
|
String s = holdCurrent.toString();
|
|
|
|
|
|
|
|
if (TibetanMachineWeb.isVowel(s)) { //the holding string is a vowel
|
|
|
|
s = TibetanMachineWeb.getWylieForVowel(s);
|
|
|
|
initKeyboard();
|
|
|
|
isTypingVowel = true;
|
|
|
|
putVowel(s);
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("You typed another vowel, so the first vowel was discarded.");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else if (TibetanMachineWeb.isChar(s)) { //the holding string is a character
|
2002-09-30 03:10:00 +00:00
|
|
|
String s2 = TibetanMachineWeb.getWylieForChar(s);
|
|
|
|
|
|
|
|
if (isTopHypothesis) {
|
|
|
|
if (TibetanMachineWeb.isAChungConsonant() && isStackingOn && charList.size()>1 && s2.equals(TibetanMachineWeb.ACHUNG)) {
|
2002-10-13 01:07:38 +00:00
|
|
|
charList.remove(charList.size() - 1);
|
2002-11-02 03:38:59 +00:00
|
|
|
newGlyphList = TibTextUtils.getGlyphs(charList, isStackingRightToLeft, isDefinitelyTibetan, isDefinitelySanskrit);
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = redrawGlyphs(oldGlyphList, newGlyphList);
|
|
|
|
putVowel(TibetanMachineWeb.A_VOWEL);
|
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because we put a vowel and there's some achung stuff happening)");
|
2002-09-30 03:10:00 +00:00
|
|
|
break key_block;
|
|
|
|
}
|
|
|
|
charList.set(charList.size()-1, s2);
|
2002-11-02 03:38:59 +00:00
|
|
|
newGlyphList = TibTextUtils.getGlyphs(charList, isStackingRightToLeft, isDefinitelyTibetan, isDefinitelySanskrit);
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = redrawGlyphs(oldGlyphList, newGlyphList);
|
2002-11-02 05:21:12 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("we were holding a hypothesis, and we've updated it");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else {
|
2002-09-30 03:10:00 +00:00
|
|
|
if (!isStackingOn) {
|
|
|
|
initKeyboard();
|
|
|
|
holdCurrent = new StringBuffer(s);
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because you weren't stacking, and there was a character already)");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else if (TibetanMachineWeb.isAChungConsonant() && s2.equals(TibetanMachineWeb.ACHUNG)) {
|
2002-09-30 03:10:00 +00:00
|
|
|
putVowel(TibetanMachineWeb.A_VOWEL);
|
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because you were stacking, and we put a vowel, and there was some achung business)");
|
2002-09-30 03:10:00 +00:00
|
|
|
break key_block;
|
|
|
|
}
|
|
|
|
|
|
|
|
charList.add(s2);
|
|
|
|
isTopHypothesis = true;
|
2002-11-02 03:38:59 +00:00
|
|
|
newGlyphList = TibTextUtils.getGlyphs(charList, isStackingRightToLeft, isDefinitelyTibetan, isDefinitelySanskrit);
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = redrawGlyphs(oldGlyphList, newGlyphList);
|
2002-11-02 05:21:12 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("we weren't holding a hypothesis, but we are now");
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
2002-10-13 18:40:07 +00:00
|
|
|
} else { //the holding string is not a character
|
2002-09-30 03:10:00 +00:00
|
|
|
if (isTopHypothesis) { //finalize top character and add new hypothesis to top
|
|
|
|
holdCurrent = new StringBuffer();
|
|
|
|
holdCurrent.append(c);
|
|
|
|
s = holdCurrent.toString();
|
|
|
|
|
|
|
|
if (TibetanMachineWeb.isVowel(s)) {
|
|
|
|
String s2 = TibetanMachineWeb.getWylieForVowel(s);
|
|
|
|
putVowel(s2);
|
|
|
|
initKeyboard();
|
|
|
|
isTypingVowel = true;
|
|
|
|
holdCurrent = new StringBuffer(s);
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because we put a vowel and the previous...)");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else {
|
2002-11-03 17:05:05 +00:00
|
|
|
if (TibetanMachineWeb.isStackingMedial() && !isStackingRightToLeft) {
|
2002-09-30 03:10:00 +00:00
|
|
|
initKeyboard();
|
2002-11-03 17:05:05 +00:00
|
|
|
changedStatus = true;
|
|
|
|
appendStatus(" (because TibetanMachineWeb.isStackingMedial() && !isStackingRightToLeft)");
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
|
|
|
|
if (TibetanMachineWeb.isChar(s)) {
|
|
|
|
String s2 = TibetanMachineWeb.getWylieForChar(s);
|
|
|
|
|
2002-10-13 18:40:07 +00:00
|
|
|
if (!isStackingOn) {
|
2002-09-30 03:10:00 +00:00
|
|
|
initKeyboard();
|
2002-10-13 18:40:07 +00:00
|
|
|
} else if (TibetanMachineWeb.isAChungConsonant() && s2.equals(TibetanMachineWeb.ACHUNG)) {
|
2002-09-30 03:10:00 +00:00
|
|
|
putVowel(TibetanMachineWeb.A_VOWEL);
|
|
|
|
initKeyboard();
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
appendStatus(" (because we put a vowel)");
|
2002-09-30 03:10:00 +00:00
|
|
|
break key_block;
|
|
|
|
}
|
|
|
|
|
|
|
|
charList.add(s2);
|
2002-11-02 03:38:59 +00:00
|
|
|
newGlyphList = TibTextUtils.getGlyphs(charList, isStackingRightToLeft, isDefinitelyTibetan, isDefinitelySanskrit);
|
2002-09-30 03:10:00 +00:00
|
|
|
oldGlyphList = redrawGlyphs(oldGlyphList, newGlyphList);
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("added character to charList");
|
2002-10-13 18:40:07 +00:00
|
|
|
} else {
|
2002-09-30 03:10:00 +00:00
|
|
|
holdCurrent = new StringBuffer(s);
|
|
|
|
isTopHypothesis = false;
|
2002-10-13 19:22:56 +00:00
|
|
|
changedStatus = true;
|
2002-11-03 17:05:05 +00:00
|
|
|
// FIXME: ring a bell here so the user knows what's up.
|
|
|
|
updateStatus("semireset (holdCurrent was reset) because you typed something invalid");
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
} else {
|
|
|
|
// top char is just a guess! Just keep c
|
|
|
|
// in holdCurrent if it may become valid
|
|
|
|
// input, or reset if we've no hope.
|
|
|
|
|
|
|
|
if (TibetanMachineWeb.hasInputPrefix(s)) {
|
|
|
|
isTopHypothesis = false;
|
|
|
|
changedStatus = true;
|
|
|
|
updateStatus("incomplete input (like the \"S\" in Extended Wylie's \"Sh\")");
|
|
|
|
} else {
|
2002-11-03 17:05:05 +00:00
|
|
|
// before we call initKeyboard, get info to prevent infinite loops:
|
|
|
|
StringBuffer prevHoldCurrent = new StringBuffer(holdCurrent.toString());
|
|
|
|
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
// FIXME: ring a bell here so the user knows what's up.
|
|
|
|
initKeyboard();
|
|
|
|
|
|
|
|
// The recursive call to
|
|
|
|
// processTibetanChar will update the
|
|
|
|
// status bar, so set this to true:
|
|
|
|
changedStatus = true;
|
|
|
|
|
|
|
|
// This status message is bound to get
|
|
|
|
// overridden, but this is what we
|
|
|
|
// would say if we had a queue of
|
|
|
|
// messages or something like Emacs's
|
|
|
|
// M-x view-lossage to see a history
|
|
|
|
// of status messages:
|
|
|
|
appendStatus(" (because you typed something invalid [2nd way])");
|
|
|
|
|
2002-11-03 17:05:05 +00:00
|
|
|
if (prevHoldCurrent.length() != 0
|
|
|
|
&& !prevHoldCurrent.toString().equals(String.valueOf(c))) {
|
|
|
|
processTibetanChar(c, false);
|
|
|
|
}
|
|
|
|
// else we'd go into an infinite loop
|
Fixes bug 624133, "Input freezes after impossible character". Try 'shsM' in
ACIP or 'ShSm' in Extended Wylie to see the new behavior.
We use a trie to store valid input sequences. In the future, we could use
the same trie as a replacement for the more inefficient HashSets we use to
store characters, vowels, and punctuation. For example, we'd use
'validInputSequences.put("K", new Pair("consonant", "k"))' when reading
in the ACIP keyboard's description of the first consonant of the Tibetan
alphabet in 'TibetanKeyboard.java'.
Note that the current trie implementation is only useful for 7- or 8-bit
transcription systems, and works best for tries with low average depth, which
describes a transcription system's trie very well. If you used arbitrary
Unicode in your keyboard, you'd need a different trie implementation.
Improved the optional keyboard input mode status messages.
2002-11-02 18:44:24 +00:00
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} //end switch
|
|
|
|
} //end key_block
|
2002-10-13 19:22:56 +00:00
|
|
|
|
|
|
|
if (changedStatus == false) {
|
|
|
|
updateStatus("THAT KEY DID NOTHING BECAUSE OF THE CURRENT INPUT MODE.");
|
|
|
|
}
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts the entire document to Extended Wylie.
|
|
|
|
*/
|
|
|
|
public void toWylie() {
|
|
|
|
int start = getSelectionStart();
|
|
|
|
int end = getSelectionEnd();
|
|
|
|
|
|
|
|
toWylie(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts the specified portion
|
|
|
|
* of this object's document to Extended Wylie.
|
|
|
|
*
|
|
|
|
* @param start the point from which to begin converting to Wylie
|
|
|
|
* @param end the point at which to stop converting to Wylie
|
|
|
|
*/
|
|
|
|
public void toWylie(int start, int end) {
|
|
|
|
if (start == end)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DuffCode[] dc_array;
|
|
|
|
AttributeSet attr;
|
|
|
|
String fontName;
|
|
|
|
Position endPos;
|
|
|
|
int fontNum;
|
|
|
|
DuffCode dc;
|
|
|
|
char ch;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
java.util.List dcs = new ArrayList();
|
|
|
|
|
|
|
|
try {
|
|
|
|
endPos = doc.createPosition(end);
|
|
|
|
i = start;
|
|
|
|
|
|
|
|
while (i < endPos.getOffset()+1) {
|
|
|
|
attr = doc.getCharacterElement(i).getAttributes();
|
|
|
|
fontName = StyleConstants.getFontFamily(attr);
|
|
|
|
|
|
|
|
if ((0 == (fontNum = TibetanMachineWeb.getTMWFontNumber(fontName))) || i==endPos.getOffset()) {
|
|
|
|
if (i != start) {
|
|
|
|
dc_array = new DuffCode[0];
|
|
|
|
dc_array = (DuffCode[])dcs.toArray(dc_array);
|
|
|
|
doc.remove(start, i-start);
|
2002-11-02 03:38:59 +00:00
|
|
|
append(start, TibTextUtils.getWylie(dc_array), romanAttributeSet);
|
2002-09-30 03:10:00 +00:00
|
|
|
dcs.clear();
|
|
|
|
}
|
|
|
|
start = i+1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ch = doc.getText(i,1).charAt(0);
|
|
|
|
dc = new DuffCode(fontNum, ch);
|
|
|
|
dcs.add(dc);
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (BadLocationException ble) {
|
|
|
|
ble.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a string of Extended Wylie to TibetanMachineWeb, and
|
|
|
|
* inserts it at the specified position.
|
|
|
|
*
|
|
|
|
* @param wylie the string of Wylie to convert
|
|
|
|
* @param offset the position at which to insert the conversion
|
|
|
|
*/
|
|
|
|
public void toTibetanMachineWeb(String wylie, int offset) {
|
|
|
|
try {
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
StringTokenizer sTok = new StringTokenizer(wylie, "\n\t", true); // FIXME does this work on all platforms?
|
2002-09-30 03:10:00 +00:00
|
|
|
while (sTok.hasMoreTokens()) {
|
|
|
|
String next = sTok.nextToken();
|
Added a flexible mechanism for persistent boolean-, integer-, and
string-valued preferences built atop java.util.Properties.
How it works: the jvm is asked first, and then the user's prefs file, if it exists,
then the system-wide prefs file, and then the built-in preferences. Finally, for
robustness, a default may be optionally hard-coded in the source.
I made several things configurable, too:
the default Tibetan keyboard
the default font sizes and faces
whether you want developer-only features enabled
Savant's file extension (.savant)
etc.
The only known problems are the following:
The default location for the user's preferences file is windows-specific,
arbitrary, and not in the user documentation. Likewise for the location of the
system-wide preferences file. You can change them using 'java -D', though.
There is no "Save preferences" option yet, and closing the program does
not save preferences either.
2002-10-14 04:06:05 +00:00
|
|
|
if (next.equals("\n") || next.equals("\t")) { // FIXME does this work on all platforms?
|
2002-09-30 03:10:00 +00:00
|
|
|
try {
|
|
|
|
doc.insertString(offset, next, null);
|
|
|
|
offset++;
|
|
|
|
} catch (BadLocationException ble) {
|
|
|
|
ble.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
2002-11-02 03:38:59 +00:00
|
|
|
DuffData[] dd = TibTextUtils.getTibetanMachineWeb(next);
|
2002-09-30 03:10:00 +00:00
|
|
|
offset = doc.insertDuff(offset, dd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (InvalidWylieException iwe) {
|
|
|
|
JOptionPane.showMessageDialog(this,
|
|
|
|
"The Wylie you are trying to convert is invalid, " +
|
|
|
|
"beginning from:\n " + iwe.getCulpritInContext() + "\n" +
|
|
|
|
"The culprit is probably the character '"+iwe.getCulprit()+"'.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts the currently selected text from Extended Wylie to TibetanMachineWeb.
|
|
|
|
*/
|
|
|
|
public void toTibetanMachineWeb() {
|
|
|
|
int start = getSelectionStart();
|
|
|
|
int end = getSelectionEnd();
|
|
|
|
|
|
|
|
toTibetanMachineWeb(start, end);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a stretch of text from Extended Wylie to TibetanMachineWeb.
|
|
|
|
* @param start the begin point for the conversion
|
|
|
|
* @param end the end point for the conversion
|
|
|
|
*/
|
|
|
|
public void toTibetanMachineWeb(int start, int end) {
|
|
|
|
if (start == end)
|
|
|
|
return;
|
|
|
|
|
|
|
|
StringBuffer sb;
|
|
|
|
AttributeSet attr;
|
|
|
|
String fontName;
|
|
|
|
Position endPos;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
try {
|
|
|
|
sb = new StringBuffer();
|
|
|
|
endPos = doc.createPosition(end);
|
|
|
|
i = start;
|
|
|
|
|
|
|
|
while (i < endPos.getOffset()+1) {
|
|
|
|
attr = doc.getCharacterElement(i).getAttributes();
|
|
|
|
fontName = StyleConstants.getFontFamily(attr);
|
|
|
|
|
2002-11-02 16:01:40 +00:00
|
|
|
if ((0 != TibetanMachineWeb.getTMWFontNumber(fontName)) || i==endPos.getOffset()) {
|
2002-09-30 03:10:00 +00:00
|
|
|
if (i != start) {
|
|
|
|
try {
|
2002-11-02 03:38:59 +00:00
|
|
|
DuffData[] duffdata = TibTextUtils.getTibetanMachineWeb(sb.toString());
|
2002-09-30 03:10:00 +00:00
|
|
|
doc.remove(start, i-start);
|
|
|
|
doc.insertDuff(start, duffdata);
|
|
|
|
}
|
|
|
|
catch (InvalidWylieException iwe) {
|
|
|
|
JOptionPane.showMessageDialog(this,
|
|
|
|
"The Wylie you are trying to convert is invalid, " +
|
|
|
|
"beginning from:\n " + iwe.getCulpritInContext() +
|
|
|
|
"\nThe culprit is probably the character '" +
|
|
|
|
iwe.getCulprit() + "'.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
start = i+1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sb.append(doc.getText(i, 1));
|
|
|
|
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (BadLocationException ble) {
|
|
|
|
ble.printStackTrace();
|
2002-10-06 18:23:27 +00:00
|
|
|
ThdlDebug.noteIffyCode();
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-02 03:38:59 +00:00
|
|
|
/**
|
|
|
|
* Converts the entire associated document into Extended Wylie. If the
|
|
|
|
* document consists of both Tibetan and non-Tibetan fonts, however,
|
|
|
|
* the conversion stops at the first non-Tibetan font.
|
|
|
|
* @return the string of Wylie corresponding to the associated document
|
2002-11-02 16:01:40 +00:00
|
|
|
* @see org.thdl.tib.text.TibetanDocument#getWylie() */
|
2002-11-02 03:38:59 +00:00
|
|
|
public String getWylie() {
|
|
|
|
return doc.getWylie();
|
|
|
|
}
|
|
|
|
|
2002-09-30 03:10:00 +00:00
|
|
|
}
|