TM->TMW and TMW->TM conversion in RTF is now supported. I've

noticed that formatting is mostly OK but sometimes gets bungled slightly.
I tried everything I could think of, and now I'm passing the buck to Java's
RTF support.

TMW_RTF_TO_THDL_WYLIE (now misnamed) support TMW->TM
conversion (but not TM->TMW).  There is an automated test case for a
TMW->TM conversion.

I have full confidence in this conversion.  Even the smallest glitch in the core
functionality (not formatting) would surprise me.

Note that the JUnit test TMW_RTF_TO_THDL_WYLIETest sometimes fails
due to one- or two-line diffs between the actual and expected outputs.  This
is because Java's RTF support is not deterministic, I'm guessing, and is not
a real failure.  I'm too lazy to make a more elaborate sed/diff mechanism
that works on all platforms, and that would complicate the build anyway.
This commit is contained in:
dchandler 2003-05-31 23:21:29 +00:00
parent 56d5ac7210
commit 0235263ddf
8 changed files with 416 additions and 103 deletions

View file

@ -323,7 +323,25 @@ public class Jskad extends JPanel implements DocumentListener {
}); });
toolsMenu.addSeparator(); toolsMenu.addSeparator();
toolsMenu.add(importItem); toolsMenu.add(importItem);
JMenuItem toTMItem = new JMenuItem("Convert TMW to TM"); // DLC FIXME: do it just in the selection?
toTMItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
((TibetanDocument)dp.getDocument()).convertToTM(0, -1); // entire document
} }
});
JMenuItem toTMWItem = new JMenuItem("Convert TM to TMW"); // DLC FIXME: do it just in the selection?
toTMWItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
((TibetanDocument)dp.getDocument()).convertToTMW(0, -1); // entire document
}
});
toolsMenu.addSeparator();
toolsMenu.add(toTMItem);
toolsMenu.add(toTMWItem);
}
if (ThdlOptions.getBooleanOption("thdl.add.developer.options.to.menu")) { if (ThdlOptions.getBooleanOption("thdl.add.developer.options.to.menu")) {
toolsMenu.addSeparator(); toolsMenu.addSeparator();
@ -338,7 +356,7 @@ public class Jskad extends JPanel implements DocumentListener {
if (ThdlOptions.getBooleanOption("thdl.add.developer.options.to.menu")) { if (ThdlOptions.getBooleanOption("thdl.add.developer.options.to.menu")) {
toolsMenu.addSeparator(); toolsMenu.addSeparator();
JMenuItem DevelItem = new JMenuItem("Check for non-TMW characters"); // DLC NOW: do it just in the selection JMenuItem DevelItem = new JMenuItem("Check for non-TMW characters"); // FIXME: do it just in the selection?
DevelItem.addActionListener(new ThdlActionListener() { DevelItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) { public void theRealActionPerformed(ActionEvent e) {
((TibetanDocument)dp.getDocument()).findSomeNonTMWCharacters(0, -1); // entire document. ((TibetanDocument)dp.getDocument()).findSomeNonTMWCharacters(0, -1); // entire document.
@ -347,17 +365,6 @@ public class Jskad extends JPanel implements DocumentListener {
toolsMenu.add(DevelItem); toolsMenu.add(DevelItem);
} }
if (ThdlOptions.getBooleanOption("thdl.add.developer.options.to.menu")) {
toolsMenu.addSeparator();
JMenuItem DevelItem = new JMenuItem("Fix curly braces RTF problem"); // DLC NOW: do it just in the selection
DevelItem.addActionListener(new ThdlActionListener() {
public void theRealActionPerformed(ActionEvent e) {
((TibetanDocument)dp.getDocument()).replaceTahomaCurlyBracesAndBackslashes(0, -1); // entire document
}
});
toolsMenu.add(DevelItem);
}
menuBar.add(toolsMenu); menuBar.add(toolsMenu);
JMenu infoMenu = new JMenu("Info"); JMenu infoMenu = new JMenu("Info");
@ -401,11 +408,11 @@ public class Jskad extends JPanel implements DocumentListener {
new SimpleFrame(kbd.getIdentifyingString(), new SimpleFrame(kbd.getIdentifyingString(),
kbd.getQuickRefPane()); kbd.getQuickRefPane());
/* DLC FIXME -- pressing the "Extended /* DLC FIXME -- pressing the "Extended
Wylie" menu item twice causes the first Wylie" menu item (for example) twice
pane to become dead. We should check causes the first pane to become dead.
to see if the first pane exists and We should check to see if the first
raise it rather than creating a second pane exists and raise it rather than
pane. */ creating a second pane. */
} }
}); });
infoMenu.add(keybdItem); infoMenu.add(keybdItem);
@ -420,11 +427,11 @@ public class Jskad extends JPanel implements DocumentListener {
public void theRealActionPerformed(ActionEvent e) { public void theRealActionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(Jskad.this, JOptionPane.showMessageDialog(Jskad.this,
"Copyright 2001-2003 Tibetan and Himalayan Digital Library\n\n"+ "Copyright 2001-2003 Tibetan and Himalayan Digital Library\n\n"+
"Jskad is protected by the THDL Open Community License.\n\n"+ /* FIXME HARD-CODED VERSION NUMBER */ "Jskad is protected by the THDL Open Community License.\n\n"+ /* FIXME UPDATE THE YEAR REGULARLY */
"For more information, or to download the source code\n"+ "For more information, or to download the source code\n"+
"for Jskad, visit our web site:\n"+ "for Jskad, visit our web site:\n"+
" http://www.thdl.org/\n" + " http://thdl.org/\n" +
"\n" + "\n" +
"When submitting bug reports, please indicate that the\n" + "When submitting bug reports, please indicate that the\n" +
"time of compilation is " "time of compilation is "

View file

@ -23,11 +23,14 @@ import java.io.*;
import org.thdl.util.*; import org.thdl.util.*;
import org.thdl.tib.text.*; import org.thdl.tib.text.*;
/** /** DLC FIXME: this is misnamed and it doesn't allow for TM->TMW conversion.
*
* TMW_RTF_TO_THDL_WYLIE is a command-line utility for converting TMW * TMW_RTF_TO_THDL_WYLIE is a command-line utility for converting TMW
* to Wylie. It is a TibetanMachineWeb-in-RichTextFormat to THDL * to Wylie or to Tibetan Machine. It is a
* Extended Wylie converter, more specifically. Invoke it with no * TibetanMachineWeb-in-RichTextFormat to your choice of
* parameters for usage information. * TibetanMachine-in-RichTextFormat or THDL Extended
* Wylie-in-RichTextFormat converter, more specifically. Invoke it
* with no parameters for usage information.
* @author David Chandler */ * @author David Chandler */
public class TMW_RTF_TO_THDL_WYLIE { public class TMW_RTF_TO_THDL_WYLIE {
static final String rtfErrorMessage static final String rtfErrorMessage
@ -48,19 +51,25 @@ public class TMW_RTF_TO_THDL_WYLIE {
* @return the exit code. */ * @return the exit code. */
public static int realMain(String[] args, PrintStream out) { public static int realMain(String[] args, PrintStream out) {
try { try {
boolean convertToTMMode = false;
boolean convertToWylieMode = false;
boolean findSomeNonTMWMode = false; boolean findSomeNonTMWMode = false;
boolean findAllNonTMWMode = false; boolean findAllNonTMWMode = false;
// Process arguments: // Process arguments:
if ((args.length != 1 && args.length != 2) if ((args.length != 1 && args.length != 2)
|| (args.length == 1 || (args.length == 1
&& (args[0].equals("-h") && !(args[0].equals("-v")
|| args[0].equals("--help"))) || args[0].equals("--version")))
|| (args.length == 2 || (args.length == 2
&& !((findAllNonTMWMode && !((findAllNonTMWMode
= args[0].equals("--find-all-non-tmw")) = args[0].equals("--find-all-non-tmw"))
|| (convertToTMMode
= args[0].equals("--to-tibetan-machine"))
|| (convertToWylieMode
= args[0].equals("--to-wylie"))
|| (findSomeNonTMWMode || (findSomeNonTMWMode
= args[0].equals("--find-some-non-tmw"))))) { = args[0].equals("--find-some-non-tmw"))))) {
out.println("TMW_RTF_TO_THDL_WYLIE [--find-all-non-tmw | --find-some-non-tmw] RTF_file |"); out.println("TMW_RTF_TO_THDL_WYLIE [--find-all-non-tmw | --find-some-non-tmw | --to-tibetan-machine | --to-wylie] RTF_file |");
out.println("TMW_RTF_TO_THDL_WYLIE [--version | -v | --help | -h]"); out.println("TMW_RTF_TO_THDL_WYLIE [--version | -v | --help | -h]");
out.println(""); out.println("");
out.println("Distributed under the terms of the THDL Open Community License Version 1.0."); out.println("Distributed under the terms of the THDL Open Community License Version 1.0.");
@ -72,17 +81,24 @@ public class TMW_RTF_TO_THDL_WYLIE {
out.println(" not in Tibetan Machine Web fonts, exit zero iff none found"); out.println(" not in Tibetan Machine Web fonts, exit zero iff none found");
out.println(" --find-some-non-tmw to locate all distinct characters in the input document"); out.println(" --find-some-non-tmw to locate all distinct characters in the input document");
out.println(" not in Tibetan Machine Web fonts, exit zero iff none found"); out.println(" not in Tibetan Machine Web fonts, exit zero iff none found");
out.println(" Otherwise, needs one argument, the name of the TibetanMachineWeb RTF file."); out.println(" --to-tibetan-machine to convert TibetanMachineWeb to TibetanMachine");
out.println(" Writes the Wylie transliteration of that file to standard output after"); out.println(" rather than TibetanMachineWeb to Wylie");
out.println(" dealing with the curly brace problem. Exit code is zero on success,"); out.println(" --to-wylie to convert TibetanMachineWeb to TibetanMachine");
out.println(" nonzero otherwise."); out.println(" rather than TibetanMachineWeb to Wylie");
out.println(" In --to... modes, needs one argument, the name of the TibetanMachineWeb RTF");
out.println(" file. Writes the THDL Extended Wylie transliteration of that file [in");
out.println(" --to-wylie mode] or the TibetanMachine equivalent of that file [in");
out.println(" --to-tibetan-machine mode] to standard output after dealing with the curly");
out.println(" brace problem. Exit code is zero on success, nonzero otherwise.");
out.println(""); out.println("");
out.println(" You may find it helpful to use `--find-some-non-tmw' mode before doing a"); out.println(" You may find it helpful to use `--find-some-non-tmw' mode before doing a");
out.println(" conversion so that you have confidence in the conversion's correctness."); out.println(" conversion so that you have confidence in the conversion's correctness.");
return 77; return 77;
} }
if (args[0].equals("--version") || args[0].equals("-v")) { if (args[0].equals("--version") || args[0].equals("-v")) {
out.println("TMW_RTF_TO_THDL_WYLIE version 0.8"); out.println("TMW_RTF_TO_THDL_WYLIE version 0.81");
out.println("Compiled at "
+ ThdlVersion.getTimeOfCompilation());
return 77; return 77;
} }
String tmwRtfPath = args[args.length - 1]; String tmwRtfPath = args[args.length - 1];
@ -107,12 +123,19 @@ public class TMW_RTF_TO_THDL_WYLIE {
} else if (findSomeNonTMWMode) { } else if (findSomeNonTMWMode) {
// 0, -1 is the entire document. // 0, -1 is the entire document.
return ((TibetanDocument)dp.getDocument()).findSomeNonTMWCharacters(0, -1, out); return ((TibetanDocument)dp.getDocument()).findSomeNonTMWCharacters(0, -1, out);
} else { // conversion mode } else { // conversion {to Wylie or TM} mode
// Fix curly braces in the entire document: // Fix curly braces in the entire document:
((TibetanDocument)dp.getDocument()).replaceTahomaCurlyBracesAndBackslashes(0, -1); ((TibetanDocument)dp.getDocument()).replaceTahomaCurlyBracesAndBackslashes(0, -1);
if (convertToWylieMode) {
ThdlDebug.verify(!convertToTMMode);
// Convert to THDL Wylie: // Convert to THDL Wylie:
dp.toWylie(0, dp.getDocument().getLength()); dp.toWylie(0, dp.getDocument().getLength());
} else {
ThdlDebug.verify(convertToTMMode);
// Convert to TibetanMachine:
((TibetanDocument)dp.getDocument()).convertToTM(0, dp.getDocument().getLength());
}
// Write to standard output the result: // Write to standard output the result:
((TibetanDocument)dp.getDocument()).writeRTFOutputStream(out); ((TibetanDocument)dp.getDocument()).writeRTFOutputStream(out);

View file

@ -77,74 +77,55 @@ public class TMW_RTF_TO_THDL_WYLIETest extends TestCase {
assertTrue(0 == rc); assertTrue(0 == rc);
} }
/** Tests the --find-some-non-tmw mode of {@link
* org.thdl.tib.input.TMW_RTF_TO_THDL_WYLIE}. */ private void helper(String mode, String extension, int erc) {
public void testFindSomeNonTMWMode() {
String[] args = new String[] { String[] args = new String[] {
"--find-some-non-tmw", mode,
"source" + File.separator getTestFileName("Test1")
+ "org" + File.separator
+ "thdl" + File.separator
+ "tib" + File.separator
+ "input" + File.separator
+ "TMW_RTF_TO_THDL_WYLIETest1.rtf"
}; };
boolean fileNotFound = false; boolean fileNotFound = false;
try { try {
int rc = TMW_RTF_TO_THDL_WYLIE.realMain(args, new PrintStream(new FileOutputStream("bin/for-junit/TMW_RTF_TO_THDL_WYLIETest1ResultFindSome.out"))); int rc = TMW_RTF_TO_THDL_WYLIE.realMain(args, new PrintStream(new FileOutputStream("bin/for-junit/TMW_RTF_TO_THDL_WYLIETest1Result" + extension + ".out")));
assertTrue(rc == 1); assertTrue(rc == erc);
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
fileNotFound = true; fileNotFound = true;
} }
assertTrue(!fileNotFound); assertTrue(!fileNotFound);
testActualAndExpected("Test1ResultFindSome"); testActualAndExpected("Test1Result" + extension);
}
private static String getTestFileName(String testName) {
return "source" + File.separator
+ "org" + File.separator
+ "thdl" + File.separator
+ "tib" + File.separator
+ "input" + File.separator
+ "TMW_RTF_TO_THDL_WYLIE" + testName + ".rtf";
}
/** Tests the --find-some-non-tmw mode of {@link
* org.thdl.tib.input.TMW_RTF_TO_THDL_WYLIE}. */
public void testFindSomeNonTMWMode() {
helper("--find-some-non-tmw", "FindSome", 1);
} }
/** Tests the --find-all-non-tmw mode of {@link /** Tests the --find-all-non-tmw mode of {@link
* org.thdl.tib.input.TMW_RTF_TO_THDL_WYLIE}. */ * org.thdl.tib.input.TMW_RTF_TO_THDL_WYLIE}. */
public void testFindAllNonTMWMode() { public void testFindAllNonTMWMode() {
String[] args = new String[] { helper("--find-all-non-tmw", "FindAll", 1);
"--find-all-non-tmw",
"source" + File.separator
+ "org" + File.separator
+ "thdl" + File.separator
+ "tib" + File.separator
+ "input" + File.separator
+ "TMW_RTF_TO_THDL_WYLIETest1.rtf"
};
boolean fileNotFound = false;
try {
int rc = TMW_RTF_TO_THDL_WYLIE.realMain(args, new PrintStream(new FileOutputStream("bin/for-junit/TMW_RTF_TO_THDL_WYLIETest1ResultFindAll.out")));
assertTrue(rc == 1);
} catch (FileNotFoundException e) {
fileNotFound = true;
}
assertTrue(!fileNotFound);
testActualAndExpected("Test1ResultFindAll");
} }
/** Tests the converter mode of {@link /** Tests the --to-wylie converter mode of {@link
* org.thdl.tib.input.TMW_RTF_TO_THDL_WYLIE}. */ * org.thdl.tib.input.TMW_RTF_TO_THDL_WYLIE}. */
public void testConverterMode() { public void testConverterMode() {
String[] args = new String[] { helper("--to-wylie", "Conversion", 0);
"source" + File.separator
+ "org" + File.separator
+ "thdl" + File.separator
+ "tib" + File.separator
+ "input" + File.separator
+ "TMW_RTF_TO_THDL_WYLIETest1.rtf"
};
boolean fileNotFound = false;
try {
int rc = TMW_RTF_TO_THDL_WYLIE.realMain(args, new PrintStream(new FileOutputStream("bin/for-junit/TMW_RTF_TO_THDL_WYLIETest1ResultConversion.out")));
assertTrue(rc == 0);
} catch (FileNotFoundException e) {
fileNotFound = true;
} }
assertTrue(!fileNotFound);
testActualAndExpected("Test1ResultConversion"); /** Tests the --to-tibetan-machine converter mode of {@link
* org.thdl.tib.input.TMW_RTF_TO_THDL_WYLIE}. */
public void testTMConverterMode() {
helper("--to-tibetan-machine", "TM", 0);
} }
} }

View file

@ -0,0 +1,84 @@
{\rtf1\ansi
{\fonttbl\f0\fnil Monospaced;\f1\fnil TibetanMachineWeb;\f2\fnil TibetanMachine;\f3\fnil Tahoma;\f4\fnil TibetanMachineSkt4;\f5\fnil TimesNewRoman;\f6\fnil TibetanMachineSkt2;\f7\fnil TibetanMachineSkt3;\f8\fnil Times New Roman;}
{\stylesheet{\s2\f1\fs144\i0\b0\cf0 default;}{\s1\li0\ri0\fi0\ql\sbasedon2\snext1 Body Text;}}
\margl1440\margr1440\widowctrl
\s1\li0\ri0\fi0\ql\f2\fs56\i0\b0\cf0 /\'eb+-`\'dc-+\'e8/-*\'e89-+c\'dc+-`\'dc-\{:-0\'eb7\'dc-u\'e4-+e$<\'ca\f3\fs44\ul0\par
\par
\f2\ul0\'c9\f4 &\f2\'ca \f5\ul0 \f2\ul0\'ca#$<-%,-8\'df:-b\'dc-<-:-\u129 ?\'eb+-\'fd7\'dc-0*\'eb-9\'dc<-`\'dc-\{:-v\'eb,-#1\'ec-/\'eb9-/B\'eb+-\'fd7\'dc-+\'e8/-*\'e89-J\'eb#<-Q,-#5\'eb,-\'b9\'a57\'dc-+#7-Y\'eb,-+c\'dc+-`\'dc-\{:-0\'eb7\'dc-u\'e4-+e$<-5\'e8<-e-/-/\'ba\'a5#<-<\'eb\'ca\'ca\par
\par
/U:-\'fd-/6$-\'fd\'eb7\'dc-/P-,-Z\'a8#-\'fd7\'dc-i\'eb$-a\'e89-+/\'df<-,-7'\'dc#<-o:-X\'dc$-Y\'eb/<-#<\'e89-b\'dc-#+,-h\'dc-:\'ca\'ca\par
i#<-X,-,\'eb9-/\'df7\'dc-F-\{,-7\'eb+-#6\'dc-0$\'eb,-\'fd9-9/-7/9-&\'eb<-\'b4\'a5,-0-:\'df<-#6\'dc#<-\'fd7\'dc-0\'dc#-Y\'eb$-%,\'ca\'ca\par
0*7-#(\'dc<-/%\'b0+-o:-Z\'e89-/%<-/%\'eb0-\'fd7\'dc-\{:-A-Y\'eb$-/E\'e3$<-Y\'eb/<-/%\'b0-0$7-/-0"9-(:-2\'ec#<-`\'dc-+\'fd:\'ca\'ca\par
v-,-0*\'eb-/7\'dc-a\'b2-0&\'eb#-6<-#1$-r<-\'fd\'eb-7&\'dc-0\'e8+-#1\'ec-/\'eb<-7'\'dc#-D\'e8,-\'b5<\'df0-\'b8\'a5-+#\'e8-:\'e8#<-03\'ec+\'ca\'ca\par
\par
7&\'dc-/7\'dc-+$\'eb<-\'fd\'eb-F0-\'fd9-7'\'eb0<-\'fd7\'dc-#5\'eb0-0\'e8+-2\'e9-8\'dc-#8\'df$-l\'e1$-D#-\'fd7\'dc-E\'eb-B\'e8-#$-\'ca\'ca\par
:\'eb$<-<\'df-\u129 ?\'eb+-:-6+-0\'dc-;\'e8<-\'fd9-7+\'eb+-\'fd-7'\'eb-/7\'dc-7e\'b3$-#,<-0&\'eb#-#\'dc-#,-03\'ec+-`\'dc\'ca\'ca\par
a/-/+#-+/$-\'fd\'eb9-\'b8\'a5<-#<\'df0-\{:-/-8\'eb$<-`\'dc<-:\'e8#<-/W#<-2\'e9-+$-8\'e8-;\'e8<-+\'fd#-\'b7\'e2-0\'e8+\'ca\'ca\par
2\'e9-+\'fd:-8\'eb$<-7\'b8\'a57\'dc-O\'eb,-\'fd-\'b8\'a5<-<\'df-^\'dc,-\'fd7\'dc-+$\'eb<-i\'e1/-7o<-/\'df-v-,-0\'e8+-\'fd-_\'eb:\'ca\'ca\par
\par
29-\'b8\'a5-+$9-/7\'dc-0a\'e8,-\'fd7\'dc-#\'e8-<9-#5\'eb,-\'b9\'a57\'dc-:$-2\'ec7\'dc-N#<-`\'b2-8\'dc<\'ca\'ca\par
&\'eb<-\'b4\'a5,-9\'dc-\u144 ?#<-0\'dc#-%,-0-8\'dc-X\'dc$-:-/[\'a8,-\'fd7\'dc-9$-+/$-\'b8\'a5\'ca\'ca\par
7\'b8\'a5-7o:-w\'eb<-#9-9\'dc-0\'eb7\'dc-[$-/C,-&\'eb<-(\'dc+-0\'e8-:\'eb$-#1$-07\'dc-$\'eb<\'ca\'ca\par
B\'e8,-\'fd9-7&9-/7\'dc-e\'e8+-\'fd\'eb-6\'df9-.\'df+-M-\'fd-0i\'dc,-\'fd7\'dc-\{,-\'b8\'a5-/\'ba\'a5#<\'ca\'ca\par
\f3\ul0\par
\li720\f2\ul0 [$-03\'ec+-7/\'df0-b\'dc-l-/<-7a\'b2+-\'fd7\'dc-e\'b3-9\'df7\'dc-E\'e3:-/I\'e8#<-:\'ca\'ca\par
/D,-#8\'eb7\'dc-+$\'eb<-\'b4\'a5,-+/$-\'b8\'a5-e\'e8+-\'fd7\'dc-8\'eb,-),-8\'eb$<-J\'eb#<-\'fd7\'dc\'ca\'ca\par
6\'df9-0\'dc#-(#-n,-10-b\'dc<-+#\'e8-/7\'dc-#6\'df#<-%,-7\'b8\'a5<-0-e<\'ca\'ca\par
7+9-03+-9\'dc#-e\'e8+-T-0\'eb<-r\'dc+-\'fd-#<\'df0-:-0$7-\u128 ?\'e79-%\'dc#\'ca\par
\par
8\'dc+-7\'eb$-/5\'dc,-9<-w-#5\'eb,-7"\'eb9-:\'eb-#(\'dc<-\'fe\'e8<-:\'ca\'ca\par
7h\'e1:-/-Y\'e89-8$-7d$-0\'eb-<\'e8:-e\'e8+-0#\'eb-\'fe\'e8<-`\'dc\'ca\'ca\par
/\'ea-\'ac\'d99-0*\'dc$-"7\'dc-:,-/\'df-9/-7d$-+e$<-%,-0\'ca\'ca\par
\u137 ?-/7\'dc-+/$-d\'b3#-$#-#\'dc-\{:-\'fd\'eb-(\'e89-i\'e1/-03\'ec+\'ca\'ca\par
\par
#$<-%,-T-:0-8$<-\'fd7\'dc-a\'eb,-7+\'dc9-\{:-/7\'dc-/Y,-\'fd-/%\'b0-#(\'dc<-/+#-\'fd\'eb7\'dc-\'b5\'a59-"$-0&\'eb#\'ca\par
0a\'e8,-/I\'e8-\'b9\'a5<-\'fd7\'dc-,0-0"7\'dc-i\'e1-8\'dc<-(\'e8-/9-7l\'e8,-03+-&\'eb<-\{:-0\'e8<-+/\'eb,-F0-#<\'df0-+$-\'ca\'ca\par
\{:-/-\'b4\'a5,-+$\'eb<-02\'ec-\'fe\'e8<-E\'eb-B\'e8-/Y,-\'fd7\'dc-I-:#-*0<-%+-0a\'e8,-\'fd-5\'dc-/-72\'ec7\'dc\'ca\'ca\par
/!7-l\'dc,-#6\'df#<-%,-+e\'dc#-73\'dd,-P\'eb-7+\'dc9-;\'eb$-7b\'b29-0\'dc,-,-\'b4\'a5,-0a\'e8,-r$-:<-#$-#\'dc<-#5:\'ca\'ca\par
\par
:\'dc-h\'dc7\'dc-N\'e4#-n,-0a\'e8,-\'fd7\'dc-[$-/-%,\'ca\'ca\par
7'0-0#\'eb,-v\'eb\f4 e\f2 -8\'dc-:$-2\'ec-/6\f4 e\f2 $-\'fd\'eb7\'dc-2\'ec,\'ca\'ca\par
"-+\'eb#-<\'eb-<\'eb9-/g-/7\'dc-i#\f4 e\f2 <-\'fd\f4 e\f2 7\'dc-\{,\'ca\'ca\par
d\'eb#<-o:-F-:\'df$-7#\'eb+-0"<-D#-\'b7\'e2-\{:\'ca\'ca\f3\ul0\par
\par
\f2\ul0 +\'fd:-Q,-&\'eb<-`\'dc-9$-/5\'dc,-$\'eb<-8$<-\'fd9\'ca\'ca\par
#,<-M7\'dc-/$-03\'ec+-7e\'eb9-\'fd9-T\'a9,-i\'e1/-\'fd7\'dc\'ca\'ca\par
0$7-\u128 ?\'e79-/i\'eb+-e\'e8+-/\f6 v\'e4\f2 -3\'dd\'a1-4-!\'ca\par
H+-e\'b3$-%\'eb+-\'fd,-0&\'eb#-\'b7\'e2-F0-\'fd9-/W#<\'ca\'ca\par
\par
\{-=\'eb9-:\'df$-+$-9\'dc#<-`\'dc<-0$\'eb,-0*\'eb-5\'dc$-\'ca\'ca\par
/!7-h\'dc0<-#<\'e89-7"\'eb9-0&\'eb#-+0,-#(7-#,\'eb,-\'fd7\'dc\'ca\'ca\par
<-\'fe-7'0-0#\'eb,-+\'fd:-Q,-x$<-`\'dc-#\'b8\'a5$-\'ca\'ca\par
&\'eb<-Q,-<-\'fe\'eb$-\{:-\'fd\'eb9-<\'df-0\'dc-++\'ca\'ca\par
\par
\u137 ?-/7\'dc-7//-Y\'e8#<-0\'b8\'a5+-\'fd7\'dc-\{9-/%\'dc$<-`$-\'ca\'ca\par
0*\'eb,-\'fd\'eb7\'dc-h\'dc-:-l\'e8#<-\'fd<-7b\'dc$-0\'dc,-\'fd7\'dc\'ca\'ca\par
:\'e8#<-/;+-#)0-b\'dc-7e\'b3$-#,<-v\'eb-Q,-%,\'ca\'ca\par
#$-\'b8\'a5-#,<-`$-+$-/7\'dc-\u135 ?\'eb-/-7.\'e8:\'ca\'ca\par
\par
8-9/<-+0-\'fd7\'dc-\u129 ?\'eb+-2\'b1:-\'fd+-+!9-2:\'ca\'ca\par
&\'e8<-&\'e89-/+\'eb-/-X\'dc#<-07\'dc-/<\'dc:-6\'e89-b\'dc<\'ca\'ca\par
6\'df0-\'fd7\'dc-\'b8\'a5<-7+\'dc9-+\'e8/-*\'e89-#)0-\{\'e6+-<\'eb#<\'ca\'ca\par
/B\'eb+-\'fd-9$-(\'dc+-$:-/7\'dc-\{\'e6-9\'df-6+\'ca\'ca\par
\par
a+-\'fd9-/%\'b0-n#-9\'dc#-\'fd7\'dc-&\'b1-#)\'e89-&\'e8\'ca\'ca\par
v\'eb-i\'eb<-#6\'dc$<-`\'dc<-\u133 ?\'eb:-7+\'eb+-9\'dc#-e\'e8+-\'fd\'ca\'ca\par
;\'e8<-e7\'dc-2\'b1:-:-0-\u130 ?$<-/Y,-/%\'eb<-+#\'ca\par
I\'eb0-\'fd9-9\'dc$<-\'fd7\'dc-2\'b1:-:-8\'dc+-0\'dc-#)\'eb+\'ca\'ca\par
\par
7\'eb,-)$-Y\'eb/<-`\'dc<-8$<-\'fd7\'dc-,\'eb9-73\'dd,-:\'ca\'ca\par
7"\'eb9-:\'eb<-\u128 ?\'e79-/7\'dc-/!7-8\'dc-l\'dc-/5\'eb,-b\'dc<\'ca\'ca\par
+\'e8/-*\'e89-J\'eb#<-Q,-#<9-\'fd7\'dc-+#7-Y\'eb,-0i\'eb,\'ca\'ca\par
7/\'eb+-e\'e8+-0-:-8-8\'dc-\{\'e6+-7+\'dc-\u135 ?\'eb\'ca\'ca\par
\f3\ul0\par
\li0\fi720\f2\ul0 ;\'dc<-\'fd-/B\'eb+-\'fd7\'dc-+e$<-`\'dc-$-9\'eb-)\f6\'ae\'e0\f2 -97\'dc-P\'df+-:<-(\'e8-/9-l$<-)\'e8\'ca\f5\ul0 \f2\ul0 v-,-0\'e8+-\'fd7\'dc-8\'e8-;\'e8<-`\'dc-/\'b8\'a5+-I\'dc-6+-0\'dc-;\'e8<-\'fd7\'dc-7e\'b3$-#,<-6-0-)\'eb#-+/$-#\'dc-\{:-\'fd\'eb-H+-\'b8\'a5-e\'b3$-/7\'dc-*\'df#<-`\'dc-#<$-03\'ec+-+\'fd:-/\'e87\'df7\'dc-03\'e9<-\{,-\'b8\'a5-\\\'e4+-\'fd7\'dc-/U:-\'fd-/6$-\'fd\'eb-7+\'dc7\'dc-7l\'e8,-0&\'eb#-Y\'eb/<-/%\'b0-0$7-/-Y\'eb$-#\'dc-0\'dc-P\'a9$-7n\'e8$-/7\'dc-+/\'df<-,<-&\'b1-;\'e8:-+/$-\'fd\'eb7\'dc-+`\'dc:-7"\'eb9-(-#$-/-P-/\'df9-0$\'eb,-\'fd9-7.#<-;\'dc$-\'ca\f5\ul0 \f2\ul0 0+7-8\'dc<-/%\'dc$<-\'fd7\'dc-x/<-\'fd\'eb-&\'e87\'dc-^\'eb,-:0-b\'dc-0*\'df-.\'df:-\'b8\'a5-e\'b3$-/7\'dc-/+\'e8,-Y\'eb/<-l\'dc-0-0\'e8+-\'fd<-\'fd+-+!9-P-/\'df9-/W#<-\'fd7\'dc-+e$<-`\'dc-\{:-0\'eb7\'dc-A-/\'eb-&\'e8-r\'dc+-\'fd-#<\'df0-b\'dc-"\'eb9-0\'eb-8\'df#-\'b7\'e2-/E\'e3$-/7\'dc-\{:-/-/\'df-90-;\'dc$-\'fd-7+\'dc-(\'dc+-`\'dc-/Y,-\'fd-9\'dc,-\'fd\'eb-&\'e8-,\'dc-T-+$-/%<-\'fd7\'dc-7i\'eb-/7\'dc-:\'e8#<-e<-i$<-0\'e8+-\'fd7\'dc-6\'eb$-#\'dc<-/\u133 ?\'e5/<-\'fd7\'dc-.,-/+\'e8-\'b4\'a5,-b\'dc-I-:#-Y\'e8\'ca\par
\'cc\f5\ul0 \f2\ul0 +\'e8-8$-7e\'b3$-5\'dc$-7.\'e8:-/-+$-\'ca\f5\ul0 \f2\ul0 89-Q,-\'b8\'a5-\{<-\'fd7\'dc-e\'e8+-\'fd\'eb-,\'dc-8$<-\'fd7\'dc-,\'eb9-73\'dd,-b\'dc-a\'eb,-:-0$7-\u128 ?\'e79-/7\'dc-\{:-\'fd\'eb-&\'e8,-\'fd\'eb-5\'dc#-:-9#-:<-\'fd<-,\'ca\f5\ul0 \f2\ul0 7\'eb-U\'eb:-b\'dc-Y\'eb,-\'fd<-`$-9\'dc#<-+$-\'ca\f5\ul0 \f2\ul0 8\'df:-+$-\'ca\f5\ul0 \f2\ul0\'b8\'a5<-+$-\'ca\f5\ul0 \f2\ul0 /\{\'e6+-+$-\'ca\f5\ul0 \f2\ul0 /\'df+-0\'e8+-+\'e8-#6\'dc#<-\'fd-M-:-#6\'dc#<-,<\'ca\f5\ul0 \f2\ul0 6<-#1$-#\'dc-r<-<\'df-/P0<-\'fd9-03+-\'fd<\'ca\f5\ul0 \f2\ul0 *\'eb#-09-7+\'dc-(\'dc+-`\'dc-#\'b8\'a5$-9/<-%\'b0$-6+-/B\'eb+-\'fd9-e-Y\'e8\'ca\f5\ul0 \f2\ul0 7.#<-\'fd7\'dc-8\'df:-b\'dc-0\'dc-.:-&\'e8-/-7&\'dc-0\'e8+-`\'dc-#,<-,<-&+-\'fd<\'ca\f5\ul0 \f2\ul0 #5:-\'b8\'a5-0\'e8+-\'fd7\'dc-2\'e9-+$-7+\'eb+-@\'e3-:-:\'eb$<-\u129 ?\'eb+-%\'dc$-0*7-8<-\'fd7\'dc-8\'eb,-),-\'b8\'a5-0-:-+/$-7e\'eb9-\'fd7\'dc-2\'e9\'ca\f5\ul0 \f2\ul0 7/+-I\'eb:-b\'dc-0*\'df-:-9#-0-:<-\'fd7\'dc-/\'b8\'a5+-I\'dc-<7\'dc-/%\'b0+-+$-\'ca\f5\ul0 \f2\ul0 <7\'dc-5#\f5\ul0 \f2\ul0 f\'b3-\'b5\'a57\'dc-2:\'ca\f5\ul0 \f2\ul0 0-H\'eb<-\'fd7\'dc-7o<-<-:\'df-F0<-:-:\'eb$<-\u129 ?+-\'fd<\'ca\f5\ul0 \f2\ul0 T-:<-&+-\'fd7\'dc-8\'eb,-),-.:-&\'e89-:<-#5,-\'b8\'a5-b\'b29-%\'dc$-\'ca\f5\ul0 \f2\ul0 0-H\'eb<-\'fd7\'dc-7o<-`$-F0-\'fd9-#8\'e8$-/7\'dc-#5,-+/$-\'b8\'a5-b\'b29-\'fd-5\'dc#-#\'dc-e\'e8+-\'fd-:-/D\'e8,\'ca\f5\ul0 \f2\ul0 <\'eb-,0-b\'dc-e-/-:-/I0<-\'fd<\'ca\f5\ul0 \f2\ul0 .,-2\'b1,-\'b8\'a5-I\'eb+-\'fd-+$-02$-7o\'e1-/-e\'b3$-/-F0<-:-l$-\'fd\'eb7\'dc-*\'dc#-#\'dc<-#%\'eb+-\'fd7\'dc-5:-N\'e8-/9\'ca\f5\ul0 \f2\ul0\u128 ?\'a5,-b\'dc<-/\'b4\'a59-5\'dc$-7\'b8\'a5+-\'fd-:<\'ca\f5\ul0 \f2\ul0 0$-\'fd\'eb<-/\'b4\'a59-/7\'dc-\{:-\'fd\'eb-5\'e8<-\{:-\'fd\'eb-:-W-/9-i#<-;\'dc$-\'ca\f5\ul0 \f2\ul0 +\'e8-,<-9\'dc0-/5\'dc,-7\'eb+-03\'e9<\'ca\f5\ul0 \f2\ul0 +#\'e8-/\'ca\f5\ul0 \f2\ul0 +#\'e8-0&\'eb#\f5\ul0 \f2\ul0 #<\'eb-\u130 ?\'eb$-7.#<-)\'e8-W\'eb,-b\'dc-\{:-\'fd\'eb-Z\'e8-M9-/B\'eb+-:\'ca\f5\ul0 \f2\ul0 #<\'eb-\u130 ?\'eb$-7.#<-`\'dc-\u129 ?\'dc-/\'eb9-;-H\'e8,-5\'dc#-e\'b3$-/-:<-$-:<-\'b9\'a5\'ca\f5\ul0 \f2\ul0 +\'e87\'dc-/x-#8<-\'fd9-;-H\'e8,-5\'dc#-e\'b3$-/-:<-03\'e9<-\'fd\'ca\f5\ul0 \f2\ul0 +\'e87\'dc-/x-#8\'eb,-\'fd9-;-H\'e8,-5\'dc$-e\'b3$-/-:<-(\'e8-03\'e9<\'ca\f5\ul0 \f2\ul0 +\'e87\'dc-?$-\'fd-#8<-\'fd9-;-H\'e8,-5\'dc#-e\'b3$-/-:<-03\'e9<-Q,\'ca\f5\ul0 \f2\ul0 +\'e87\'dc-?$-\'fd-#8\'eb,-\'fd9-;-H\'e8,-5\'dc#-e\'b3$-/-:<-(\'e8-03\'e9<-Q,-)\'e8\'ca\f5\ul0 \f2\ul0 7+\'dc-M-:-7"\'eb9-:\'eb<-\u128 ?\'e79-/7\'dc-\{:-\'fd\'eb-M9-i#<-;\'dc$-\'ca\f5\ul0 \f2\ul0 d\'dc-0-/5\'dc<-,\'dc-u\'dc$-/5\'dc-,<-#%\'dc#-#\'dc-/9-:-+/$-\u128 ?\'e79-/<\'ca\f5\ul0 \f2\ul0 #<\'e89-+$\'df:-6$<-N#<-`\'dc-7"\'eb9-:\'eb<-\u128 ?\'e79-/7\'dc-\{:-\'fd\'eb-8\'dc,-,\'eb\'ca\f5\ul0 \f2\ul0\'ca\par
\f5\ul0 \f2\ul0\{:-\'fd\'eb-7+\'dc-+#-,<-9\'dc0-\'fd9-/\{\'e6+-+\'e8-6<-#1$-8,-&\'eb+-\'b8\'a5-<-8-&\'dc#-7/\'df0-(\'dc-h\'dc-&\'dc#-Y\'eb$-M-/\{-/%\'b0-/5\'dc-e\'b3$-/9-i#<-:\'ca\f5\ul0 \f2\ul0 7'\'dc#-D\'e8,-#+#<-\'fd9\'ca\f5\ul0 \f2\ul0\{:-\'fd\'eb-7/\'df0-n#-/\{+-<\'df0-h\'dc-/5\'dc-Y\'eb$-M-/\{-<\'df0-%\'b0-I-/5\'dc-8\'eb+-\'fd9-/;+-\'fd7\'dc-:\'df#<-#(\'dc<-!-X\'dc#<-\'b8\'a5<-`\'dc-:\'eb-\{\'e6<-\u137 ?-/-\'b4\'a5,-b\'dc-#1\'b0#-\{,\'ca\f5\ul0 \f2\ul0 #5\'eb,-\'b9\'a5-+\'fd:-b\'dc<-7l\'e8,-\'fd9-03+-\'fd-:<-#<:-/9-0-#<\'df$<-\'fd<\'ca\f5\ul0 \f2\ul0 y+-,<-`$-:\'eb-\{\'e6<-:-7l\'dc<-\'fd9-7+\'eb+-\'fd7\'dc-v\'eb-Q,-+#-#\'dc<-+c+-\'fd9-e7\'eb\'ca\f5\ul0 \f2\ul0\'ca\par
\f5\ul0 \f2\ul0 +\'e8-8$-Y\'eb,-\'fd-7+\'dc-(\'dc+-`\'dc-#\'b8\'a5$-:-(\'dc-07\'dc-#(\'e8,-+$-/\'df-90-;\'dc$-\'fd-\'bb\'d3`-5\'e8<-/B\'eb+-\'fd-,\'dc\'ca\f5\ul0 \f2\ul0 8\'df:-i\'e1-73\'dd,-\'b8\'a5-\{:-\'fd\'eb-/\{-*0-\'fd-e\'b3$-/7\'dc-0*7-0-F-/-%,-b\'dc-/\'df-#\'ed-)-0-+$-\f6\'a3\f2 -9-\f6 a\f2 -3-#(\'dc<-:<\'ca\f5\ul0 \f2\ul0 W\'eb,-0<-9/-\'b7\'e2-e\'b3$-Y\'e8-:\'eb-07\'dc-\u129 ?\'dc:-\'fd\'eb-8\'dc+-\'b8\'a5-7\'eb$-/7\'dc-/<0-#),-b\'dc-"$-/\'df9-#,<-\'fd7\'dc-2\'e9\'ca\f5\ul0 \f2\ul0 #8\'eb-%,-\'fd\f6 V\f2 7\'dc-I-:#-+$-/6$-0\'eb-+#7-0\'b5\'a59-\u129 ?\'eb+-\'fd7\'dc-\'b8\'a5<-:<-8\'eb:-/<\'ca\f5\ul0 \f2\ul0 /6$-0\'eb-/<+-\'fd7\'dc-9:-i\'dc-h#-%,-:\'eb-07\'dc-\u129 ?\'dc:-\'fd\'eb7\'dc-(\'e8-7+/<-<\'df-/\'eb9-/7\'dc-z\'e8,-b\'dc<-#\'ed-)-0-/<:-;\'dc$-:-/\'fe\'eb,-\'fd7\'dc-\'b8\'a5<\'ca\f5\ul0 \f2\ul0 l$-r\'eb$-0+\'eb#-,#-#\'dc-J\'e0-7n\'e1:-b\'dc<-i\'e1-&9-b\'dc-*\'dc#<-\'fd-+$-\'ca\f5\ul0 \f2\ul0 l\'dc-/5\'eb,-:\'df<-:-9\'e8#-\'fd7\'dc-z\'e8,-b\'dc<-7+\'eb+-\'fd7\'dc-#,<-B\'e8<-<\'df-l,-\'fd7\'dc-8\'dc+-`\'dc-;\'dc$-D<-l$<-)\'e8\'ca\f5\ul0 \f2\ul0 "0<-`\'dc-\u144 ?$<-0-#(\'dc<-T,-%\'dc#-\'b7\'e2-T\'a9$-/-:<-V\'eb-$-#(\'dc<-<\'df-b\'b29-\'fd-(\'dc-7\'eb+-`\'dc<-/\'fe$<-;\'dc$-a\'e87\'df-#(\'dc<-/\'df-90-b\'dc-;\'dc$-#<\'e8/-\'b7\'e2-\'ba\'a5#<-\'fd<-0\'dc$-+\'e8-P9-\'b8\'a5-i#<-:\'ca\f5\ul0 \f2\ul0 /\'df-90-;\'dc$-\'fd7\'dc-/\{\'e6+-:-\{:-\'fd\'eb-/\{-e\'b3$-/7\'dc-0*7-0-7.#<-\'fe\'e8<-\'fd\'eb\'ca\f5\ul0 \f2\ul0 7.#<-\'fe\'e8<-\'fd\'eb-:-r<-/5\'dc-e\'b3$-8$-/1\'b0,-0\'eb-7+<-)\'e8-y9-Y\'eb/<-Q,-b\'dc-\{:-\'fd\'eb-#5,-5\'dc#-#\'dc-/\'df-0\'eb-"/-\'b7\'e2-v$<-\'fd9-r<-e\'b3$-,-\{:-r\'dc+-\'b8\'a5-+/$-/U\'a89-/9-"<-v$<-\'fd<-+0-/%<\'ca\f5\ul0 \f2\ul0 r<-W\'eb,-0-F0<-\u129 ?\'e7#<-\'fd-9$-9$-#\'dc-r\'dc$-0\'eb-+$-/%<-)\'e8-&\'b1-/\'eb-U:-Q,-;\'dc$-D7\'dc-7i0-\'b8\'a5-0\'dc$-r\'dc$-T,-%\'dc#-\'b7\'e2-7\'b8\'a5<-\'fd-:<-\'bb\'d3`7\'dc-/\{\'e6+-%\'e8<-i#<-\'fd-8\'dc,-,\'eb\'ca\'ca\par
\f5\ul0 \f2\ul0 +\'e8-8$-\'b4\'a5,-0a\'e8,-(\'dc-07\'dc-#(\'e8,-7+\'dc-(\'dc+-7h\'e1$<-:\'eb9-0"<-i\'e1/-F0<-`\'dc-/5\'e8+-2\'b1:-0$-\'b8\'a5-0&\'dc<-`$-+\'eb,-i\'e1/-%\'e8<-\'fd-<-:\'df#-+e9-w-7o\'dc$-\'fd\'eb7\'dc-&\'b1-Y\'eb+-`\'dc-(-/7\'dc-2\'e9<-/%\'eb-M7\'dc-\'b8\'a5<-<\'df\'ca\f5\ul0 \f2\ul0 8\'df0-#<\'eb-\u130 ?\'eb$-:-#,<-\'fd7\'dc-T\'a90<-<\'df-u$-\'fd\'eb-&\'e87\'dc-n\'e1#-\'b5\'a5-*:-+!9-b\'dc-F0-\'fd9-b\'b29-,<-\'ba\'a5#<\'ca\f5\ul0 \f2\ul0 w-/-/%\'b0-.:-&\'e89-:\'eb,-\'fd-:\'e8#<-\'fd9-\u130 ?9-/-T7\'dc-U+-\'b8\'a5-9\'df-l-5\'e8<-\'fd-/<\'dc:-Q,-\'fd-F0<-l#-\'fd\'eb9-/B\'eb+-\'fd\'ca\f5\ul0 \f2\ul0\{-,#-\'fd-+/$-*$-+$-/Y\'a9,-\'fd7\'dc-0\'dc$-#\'dc$-;\'dc$-\'ca\f5\ul0 \f2\ul0 /\'eb+-8\'df:-\'b8\'a5-N#<-.\'eb-\u135 ?\'e87\'df9-7/\'eb+-\'fd7\'dc-+c\'dc+-*-<-#<-(-/-0\'e8-)\'eb#-%,-b\'dc-w-/\'ca\f5\ul0 \f2\ul0\{-,#-\'fd-<\'dc-8\'eb:-\'b8\'a5-/B\'eb+-\'fd7\'dc-89-$\'eb7\'dc-2\'e9<-/\'b8\'a5,-b\'dc-9\'e8<-#67-7\'eb+-6\'e89-/\'b8\'a5,-\'fd-+$-\'ca\f5\ul0 \f2\ul0 :<-U9-\{:-:-//<-\'fd-,-:\'df\f6\'b1\f2\'dc-,\'dc7\'dc-,#<-<\'df-U\'a8-/P0<\'ca\f5\ul0 \f2\ul0 +\'e8-,<-:$-2\'ec7\'dc-\'b4\'a5\f6 q\f2 -F0-\'fd9-\{<-\'fd7\'dc-6\'dc:-0$9-b\'dc-\u128 ?\'e7-I:-l\'e1#-%\'b0-I-/5\'dc7\'dc-8:-7+/-`\'dc-8\'eb,-),-\'b4\'a5,-:-9$-#\'dc9-/b\'dc<-;\'dc$-\'ca\f5\ul0 \f2\ul0\'fd\f6 V\f2\'eb7\'dc-X\'e80<-\'fd-*\'eb#<-\'fd7\'dc-9\'dc-\u144 ?#<-0\'dc#-%,-b\'dc-+\'eb,-8\'eb$<-<\'df-2$-/7\'dc-i#<-73\'dd,-0-+$-<-02\'ec-0-<\'eb#<-/1\'b0,-0\'eb9-+/$-/U\'a89-)\'e8-:\'eb-(\'dc-\'bb\'a5-I-+\'b5\'a57\'dc-/9-\'b8\'a5-(\'dc-7\'eb#-b\'dc-\{:-n,-#(\'dc<-7*\'df$-#\'dc-\u129 ?\'dc-/\'eb9-7'\'dc#<-\'fd-0\'e8+-\'fd7\'dc-\{:-*/<-`\'dc-e-/7\'dc-U+-#<$-0*\'eb,-\'fd\'eb<-9$-e,-\'b8\'a5-7b\'dc$-/9-+/$-*\'eb/-,7$-\'ca\f5\ul0 \f2\ul0 0&\'eb#-#\'dc-\u135 ?\'e5:-U\'a87\'dc-03+-\'fd-Y\'eb,-\'fd7\'dc-&\'e8+-\'b8\'a5\'ca\f5\ul0 \f2\ul0 +\'b5\'a5$-:\'eb-(\'e89-+\'b5\'a5-\'fd-\'b4\'a5,-73\'dd,-5\'e8<-\'fd-<-.\'eb-e\'dc-/-:-9$-e\'b3$-#\'dc-V\'eb-,<\'ca\f5\ul0 \f2\ul0 9/-e\'b3$-#\'dc-+$\'eb<-\'fd\'eb-8\'eb$<-<\'df-J\'eb#<-)\'e8\'ca\f5\ul0 \f2\ul0 :\'eb-l\'e1#-\'b7\'e2-+!7-/-\u129 ?+-\'fd<-:$-2\'ec-.\'df,-<\'df0-2\'ec#<-\'fd-:<-#5,-\'b8\'a5-b\'b29-\'fd-,\'ca\f5\ul0 \f2\ul0 +#7-0\'eb-+$-+#7-Y\'eb/<-0<-/-Y\'eb$-#\'dc-7\'eb-0-:,-/%\'b0-l\'e1#-#\'dc-/9-\'b8\'a5-(\'dc$-"\'df9-e<-\'fd7\'dc-7\'eb-*\'df#-\u136 ?$-I\'dc-+$-\u130 ?9-/7\'dc-\'b4\'a5,-\'b7\'e2-/6$-\'fd\'eb7\'dc-0&\'eb+-\u135 ?\'dc,-b\'dc<-U\'a8-<\'df-4\f6\'c7\f2 7\'dc-0&\'eb+-Z\'eb$-(\'dc-#5\'eb,-7/\'df0-b\'dc<-7a\'b2+-\'fd-P9-b\'b29-)\'e8-E\'eb-B\'e8-#+,-\'b8\'a5-e$-&\'b1/-`\'dc-;\'dc$-l\'e1$-,-7&\'dc-0\'e8+-/+#-\'fd\'eb<-~-72\'ec$-b\'dc-F0-\'fd9-\u135 ?\'e5:-)\'e8-.\'df:-/7\'dc-~7\'dc-#+,-:-/\'ba\'a5#<-,<\'ca\f5\ul0 \f2\ul0 &\'b1-r\'dc,-\{:-02,-%,-Z\'e8-+$-/%<-\'fd7\'dc-#8\'df:-:<-F0-\'fd9-\{:-/7\'dc-/-+,-,0-0"7\'dc-0*7-t<-\'fd9-/\u133 ?\'e8$<-)\'e8\'ca\f5\ul0 \f2\ul0 +\'b5\'a5$-:\'eb-<\'eb-M-\'fd-\{:-/-5\'e8<-\'fd-;\'dc$-D7\'dc-<-#<-(-/7\'dc-/%\'eb-M7\'dc-\'fe-9\'e8$<-;9-/-,-8\'e8-;\'e8<-0&\'eb#-#\'dc-/\'b8\'a5+-I\'dc-0$\'eb,-\'b8\'a5-03+-+\'eb\'ca\f5\ul0 \f2\ul0\'ca0+\'eb-:<\'ca\f5\ul0 \f2\ul0 +\'e87\'dc-(\'dc,-0\'eb-w-/-\u133 ?-#%,-b\'dc<-/6\'df$-/-+$-\'ca\f5\ul0 \f2\ul0\u133 ?-#%,-73\'dd,-+$-/\'b8\'a5+-I\'dc-6<-`\'dc-a\'e87\'df-5\'dc#-`$-\'fe\'e8<-\'fd9-/;+-\'fd7\'dc-#67-73\'dd,-b\'dc-9\'dc-0\'eb-,\'dc-#67-#,<-<\'df-#%\'dc#-&\'b1-2\'ec+-<\'eb-/\{+-w-U9-b\'dc-U9-#,<-<\'df-/%\'b0-l\'e1#-&\'b1-2\'ec+-Y\'eb$-\'fd-\u133 ?-#%,-#+\'eb$-#\'dc-U9-09-/%\'b0-l\'e1#-&\'b1-2\'ec+-(\'e89-+\'b5\'a5-e\'b3$-/<-#67-73\'dd,-b\'dc-9\'dc-0\'eb-,\'dc-2+-07\'dc->\'a1-+\f7 5\f2 -#1$-07\'dc-$\'eb<-<\'df-#<:-/9-;9-/-8\'dc,-,\'eb\'ca\f5\ul0 \f2\ul0\'ca\par
\f5\ul0 \f2\ul0 +\'e8-,<-5#-5\'e8-+\'b5\'a57\'dc-/9-\'b8\'a5-+0-\'fd7\'dc-&\'eb<-`\'dc-/\'b8\'a5+-I\'dc7\'dc-V\'eb-/\{-0-d\'e8-/7\'dc-2\'b1:-/Y,-\'fd<\'ca\f5\ul0 \f2\ul0 7'\'dc#-D\'e8,-b\'dc-e\'e8+-\'fd\'eb-#<\'e89-0$:-%,-b\'dc<-U:-\'fd-0&\'eb#-#\'dc-/6$-\'fd\'eb7\'dc-+\'fd:-+$-Q,-\'fd7\'dc-+\'eb,-\'b8\'a5-#<\'eb:-/-:-/D\'e8,-,<\'ca\f5\ul0 \f2\ul0 0&\'eb#-+0,-b\'dc-#\'b8\'a5:-e-<\'eb-<\'eb7\'dc-v\'eb-+$-720-\'fd9-6/-\{<-&\'eb<-`\'dc-V\'eb-u\'e8#<-F0-\'fd9-/g:-,<-*\'e8#-\'fd-&\'e8-&\'b1$-#\'dc-9\'dc#<-%,-b\'dc-8\'eb:-#\'eb\'ca\f5\ul0 \f2\ul0 9$-7+\'eb+-\'fd7\'dc-2\'ec#<-0*7-+#-#%\'dc#-\'b7\'e2-7'\'eb-/7\'dc-9\'eb-6+-0\'dc-;\'e8<-\'fd-0"7-a/-\'b7\'e2-o\'eb-/7\'dc-7"\'eb9-:\'eb-/U\'eb9-)\'e8\'ca\f5\ul0 \f2\ul0 0*9-b+-`\'dc-8\'df:-~-0&\'eb#-#\'dc-i\'eb$-\'b8\'a5-+\'b5\'a5$-:\'eb-b-#%\'dc#-\'fd-+\'fd7-/\'eb-5\'e8<-\'fd-N#<-7o\'e1#-#\'dc-:\'eb9-0\'dc-7b\'b29-/7\'dc-/+\'e8-/-&\'e8,-\'fd\'eb-&\'eb<-`\'dc-U\'a87\'dc-0"7-t\'eb$-\'b8\'a5-[-2\'ec#<-\'fd7\'dc-\u135 ?\'e5:-U\'a87\'dc-w\'eb<-#9-b\'dc<-9\'eb:-\'fd7\'dc-&\'b1-73\'dd,-#6\'df#<-U\'a8-*-0\'dc-++-\'fd7\'dc-03+-\'fd-/Y,-)\'eb\'ca\f5\ul0 \f2\ul0\'ca\par
\f5\ul0 \f2\ul0 +\'e8-P9-/Y,-\'fd-9\'dc,-\'fd\'eb-&\'e8-8\'df:-+/\'df<-7b\'b29-,<-&9-\'b8\'a5<-`\'dc-+:-7i\'eb7\'dc-t\'e4$-9$-//<-<\'df-7b\'b29-/7\'dc-#;\'dc<-:\'df#<-/5\'dc,-*-i\'e19-a/-\'fd-:<\'ca\f5\ul0 \f2\ul0 7i\'eb-/7\'dc-v-0-\'bb\'d3`-<\'e8$-#\'e8-b-#%\'dc#-\'fd-N#<-7o\'e1#-:\'eb-,#-(9-q\'dc\'a2-\f6 Z\'c9\f2 -\f6\u130 ?\f2 -!-\'aa-!9-#<$-/-\'b4\'a5,-b\'dc-#,-03\'ec+-F0-\'fd9-73\'dd,-\'fd7\'dc-0\'dc7\'dc-+/$-d\'b3#-w-/-/6$-\'fd\'eb9-;\'eb-:\'eb-!-Y\'eb$-n#-/%\'b0-#(\'dc<-`\'dc-/+#-(\'dc+-%,-b\'dc-+\'fd:-+$-\'fd\'eb7\'dc-<$<-\{<-\'b8\'a5<-`\'dc-7"\'eb9-:\'eb7\'dc-\{\'e6+-#<\'df$<-\'fd-;\f6\'b2\f2 -:9-\u129 ?,-l$<-,<-0-:-87\'dc-\'fe\'e8+-2:-\'b8\'a5-U\'a8-#<\'df$<-*\'df#<-8\'eb$<-<\'df-J\'eb#<-\'fd7\'dc-+`\'dc:-7"\'eb9-b\'dc-[$-/C,-8\'e8-;\'e8<-`\'dc-#6\'dc-e\'dc,-0$\'eb,-\'fd9-7/9-/7\'dc-\u128 ?\'e7-07\'dc-#9-b\'dc<-I\'e8,-\'fd7\'dc-7l\'e8,-e\'e8+-`\'dc-+#7-Y\'eb,-#<9-\'fd-/\u132 ?\'e5,-)\'e8\'ca\f5\ul0 \f2\ul0 E\'eb-B\'e8-*\'e8#-\'fd7\'dc-/#\'eb-U:-!-:\'a1-\'fd7\'dc-i\'eb$-a\'e89-b\'dc-\'fe\'e8-@\'e39-7b\'e8+-\'fd7\'dc-0\'df-0*7-o:-/7\'dc-03+-\'fd-,<-/6\'df$-7'\'dc#<-\'fd-0\'e8+-\'fd7\'dc-#+\'eb$-M7\'dc-h\'dc-:-/i\'eb+-e\'e8+-I\'dc/<-Y\'eb$-7"\'eb9-:\'eb7\'dc-9\'dc-0\'eb-0&\'eb#-\'b7\'e2-/g-/7\'dc-&\'eb<-\{:-9\'dc#<-Q,-<\'df0-%\'b0-I-#<\'df0-\'b8\'a5-e\'eb,-\'fd-0*7-+#-#\'dc<-d\'dc-,$-#5,-#<\'df0-\u130 ?\'eb9-/7\'dc-#<$-&\'e8,-\'b9\'d3-+7\'dc-\u133 ?-+e$<-`\'dc-,\'eb9-/\'df7\'dc-7d$-7n\'e1:-:<-Q,-b\'dc-F-/9-\\\'e4+-\'fd9-03+-\'fd7\'dc-*-0\'ca\f5\ul0 \f2\ul0 l#-\'fd\'eb7\'dc-7"\'eb9-:\'eb-%,-b\'dc<-+\'b5\'a5$-:\'eb-+\'b5\'a5-/%\'b0-I-/\{+-\'fd9-t-t\'eb7\'dc-+\'fd\'df$-2\'ec#<-0*7-+#-0\'dc$-#\'dc-T#-09-e<-,<-W-,-0\'e8+-\'fd<-<-&\'e8,-\'fd\'eb7\'dc-"\'eb9-8\'df#-\'b4\'a5,-\'b7\'e2-a/-\'fd9-03+-+\'eb\'ca\f5\ul0 \f2\ul0\'ca+\'e8-8$-9\'dc#<-Q,-l#-\'fd\'eb-+\'b5\'a5$-:\'eb-M-/%\'b07\'dc-Y\'e8$-\'b8\'a5-t-t\'eb-/%\'eb0-\'fd9-/5\'e8+-\'fd-P9-,\'ca\f5\ul0 \f2\ul0 t-t\'eb7\'dc-#,<-2+-Y\'eb$-+$-/\{+-/\{9-/;+-\'fd-:<-:\'eb-i$<-/5\'dc-/%\'b0-I-/\'b8\'a5,-10-0\'dc-7i\'dc#-\'fd7\'dc-\'fe\'eb,-8\'eb+-%\'dc$-\'ca\f5\ul0 \f2\ul0 +\'e8-+#-9#<-I\'dc<-<\'df-7&+-,-5\'dc/-I\'dc<-,\'dc-7e\'b3$-/7\'dc-U/<-0\'e8+-\'fd<-#6\'df9-#,<-`\'dc-;\'e8<-Q,-F0<-<\'eb0<-;\'dc#\f5\ul0 \f2\ul0 +\'e8-P9-;0-\f6\'a3\f2 -:<-02\'ec,-)\'e8\'ca\f5\ul0 \f2\ul0 >\'eb-\{,\'ca\f5\ul0 \f2\ul0 /:-8\'df:\'ca\f5\ul0 \f2\ul0\{-=\'eb9-<\'eb#<-<\'df-/Y,-\'fd-e\'b3$-2\'b1:-,\'dc-0*7-8<-`$-0$-#\'dc<-+\'eb#<-\'fd<-0-\u135 ?\'eb<-<\'eb\'ca\f5\ul0 \f2\ul0\'ca\par
\f8\fs24\ul0\par
\pard\ql\f2\fs72\ul0\par
\f1\fs144\par
}

View file

@ -8,6 +8,7 @@
<h2>Jskad Documentation</h2> <h2>Jskad Documentation</h2>
<ul> <ul>
<li><a href="#latest">Latest Changes</a></li>
<li><a href="#install">Running Jskad</a></li> <li><a href="#install">Running Jskad</a></li>
<li><a href="#start">Getting Started</a></li> <li><a href="#start">Getting Started</a></li>
<li><a href="#tibetan">Typing Tibetan</a></li> <li><a href="#tibetan">Typing Tibetan</a></li>
@ -22,6 +23,17 @@
<li><a href="http://iris.lib.virginia.edu/tibet/tools/jskad.html">Jskad Home Page</a></li> <li><a href="http://iris.lib.virginia.edu/tibet/tools/jskad.html">Jskad Home Page</a></li>
</ul> </ul>
<a name="latest"></a>
<h3>Latest Changes</h3>
<p>
Jskad now supports converting Tibetan Machine to Tibetan Machine Web
and vice versa.&nbsp; Try it form the Tools menu.&nbsp; Be on the
lookout for formatting changes; Java's RTF support is currently
poor.<!-- FIXME: do this correctly, not in a "Latest Changes"
section. -->
</p>
<a name="install"></a> <a name="install"></a>
<h3>Running Jskad</h3> <h3>Running Jskad</h3>

View file

@ -19,9 +19,13 @@ Contributor(s): ______________________________________.
package org.thdl.tib.text; package org.thdl.tib.text;
/** /**
* A wrapper object for a stretch of TibetanMachineWeb data that shares the same font. * A wrapper object for a stretch of TibetanMachineWeb (TMW) or
* A piece of DuffData consists of a font number and a string. * TibetanMachine (TM) data that shares the same font. A piece of
* The font number is a number from one to ten, corresponding * DuffData consists of a font number and a string. The fact that this
* stretch is TMW vs. TM is not stored in this object; the client must
* remember that itself.
*
* For TMW, the font number is a number from one to ten, corresponding
* to the ten TibetanMachineWeb fonts, as follows: * to the ten TibetanMachineWeb fonts, as follows:
* <p> * <p>
* 1 - TibetanMachineWeb<br> * 1 - TibetanMachineWeb<br>
@ -29,9 +33,18 @@ package org.thdl.tib.text;
* ...<br> * ...<br>
* 10 - TibetanMachineWeb9<br> * 10 - TibetanMachineWeb9<br>
* <p> * <p>
* The string represents a contiguous stretch of data in that * For TM, the font number is a number from one to five, corresponding
* font, i.e. a stretch of TibetanMachineWeb that doesn't require a font change. * to the five TibetanMachineWeb fonts, as follows:
*/ * <p>
* 1 - TibetanMachine<br>
* 2 - TibetanMachineSkt1<br>
* 3 - TibetanMachineSkt2<br>
* 4 - TibetanMachineSkt3<br>
* 5 - TibetanMachineSkt4<br>
* <p>
* The string represents a contiguous stretch of data in that font,
* i.e. a stretch of TibetanMachineWeb or TibetanMachine that doesn't
* require a font change. */
public class DuffData { public class DuffData {
/** /**
* a string of text * a string of text
@ -43,11 +56,24 @@ public class DuffData {
public int font; public int font;
/** /**
* @param s a string of TibetanMachineWeb text * @param s a string of TibetanMachineWeb or TibetanMachine text
* @param i a TibetanMachineWeb font number * @param i a TibetanMachineWeb or TibetanMachine font number
*/ */
public DuffData(String s, int i) { public DuffData(String s, int i) {
text = s; text = s;
font = i; font = i;
} }
/** Default constructor. The DuffData is invalid after this until
you call setData or manipulate the public fields. */
public DuffData() { }
/** Changes the text and font this DuffData represents.
* @param c a character of TibetanMachineWeb or TibetanMachine text
* @param i a TibetanMachineWeb or TibetanMachine font number
*/
public void setData(char c, int i) {
text = new String(new char[] { c });
font = i;
}
} }

View file

@ -150,16 +150,18 @@ public class TibetanDocument extends DefaultStyledDocument {
* @param pos the position at which you want to insert text * @param pos the position at which you want to insert text
*/ */
public int insertDuff(int pos, DuffData[] glyphs) { public int insertDuff(int pos, DuffData[] glyphs) {
return insertDuff(tibetanFontSize, pos, glyphs); return insertDuff(tibetanFontSize, pos, glyphs, true);
} }
private int insertDuff(int fontSize, int pos, DuffData[] glyphs) { private int insertDuff(int fontSize, int pos, DuffData[] glyphs, boolean asTMW) {
if (glyphs == null) if (glyphs == null)
return pos; return pos;
MutableAttributeSet mas; MutableAttributeSet mas;
for (int i=0; i<glyphs.length; i++) { for (int i=0; i<glyphs.length; i++) {
mas = TibetanMachineWeb.getAttributeSet(glyphs[i].font); mas = ((asTMW)
? TibetanMachineWeb.getAttributeSet(glyphs[i].font)
: TibetanMachineWeb.getAttributeSetTM(glyphs[i].font));
appendDuff(fontSize, pos, glyphs[i].text, mas); appendDuff(fontSize, pos, glyphs[i].text, mas);
pos += glyphs[i].text.length(); pos += glyphs[i].text.length();
} }
@ -350,7 +352,8 @@ public class TibetanDocument extends DefaultStyledDocument {
TibetanMachineWeb. Works within the range [start, end). TibetanMachineWeb. Works within the range [start, end).
Using a negative number for end means that this will run to Using a negative number for end means that this will run to
the end of the document. Be sure to set the size for Tibetan the end of the document. Be sure to set the size for Tibetan
as you like it before using this. SPEED_FIXME: might be as you like it before using this (well, it usually gets it
right on its own, but just in case). SPEED_FIXME: might be
faster to run over the elements, if they are one per font. */ faster to run over the elements, if they are one per font. */
public void replaceTahomaCurlyBracesAndBackslashes(int begin, int end) { public void replaceTahomaCurlyBracesAndBackslashes(int begin, int end) {
if (end < 0) if (end < 0)
@ -382,7 +385,7 @@ public class TibetanDocument extends DefaultStyledDocument {
} catch (Exception e) { } catch (Exception e) {
// leave it as tibetanFontSize // leave it as tibetanFontSize
} }
insertDuff(fontSize, i, toReplaceWith); insertDuff(fontSize, i, toReplaceWith, true);
remove(i+1, 1); remove(i+1, 1);
} }
} }
@ -393,4 +396,102 @@ public class TibetanDocument extends DefaultStyledDocument {
ThdlDebug.noteIffyCode(); ThdlDebug.noteIffyCode();
} }
} }
/** Converts all TibetanMachineWeb glyphs in the document to
TibetanMachine. Works within the range [start, end). Using a
negative number for end means that this will run to the end of
the document. Be sure to set the size for Tibetan as you like
it before using this (well, it usually gets it right on its
own, but just in case). SPEED_FIXME: might be faster to run
over the elements, if they are one per font. */
public void convertToTM(int begin, int end) {
convertTMW_TM(begin, end, true);
}
/** Converts all TibetanMachine glyphs in the document to
TibetanMachineWeb. Works within the range [start, end).
Using a negative number for end means that this will run to
the end of the document. Be sure to set the size for Tibetan
as you like it before using this (well, it usually gets it
right on its own, but just in case). SPEED_FIXME: might be
faster to run over the elements, if they are one per font. */
public void convertToTMW(int begin, int end) {
convertTMW_TM(begin, end, false);
}
/** Helper function.
@see convertToTMW(int,int)
@see convertToTM(int,int) */
private void convertTMW_TM(int begin, int end, boolean toTM) {
if (end < 0)
end = getLength();
if (begin >= end)
return;
int i = begin;
try {
DuffData[] equivalent = new DuffData[1];
equivalent[0] = new DuffData();
while (i < end) {
AttributeSet attr = getCharacterElement(i).getAttributes();
String fontName = StyleConstants.getFontFamily(attr);
int fontNum
= (toTM
? TibetanMachineWeb.getTMWFontNumber(fontName)
: TibetanMachineWeb.getTMFontNumber(fontName));
if (0 != fontNum) {
DuffCode dc = null;
try {
if (toTM) {
dc = TibetanMachineWeb.mapTMWtoTM(fontNum - 1,
getText(i,1).charAt(0));
} else {
dc = TibetanMachineWeb.mapTMtoTMW(fontNum - 1,
getText(i,1).charAt(0));
}
if (null != dc) {
equivalent[0].setData(dc.getCharacter(),
dc.getFontNum());
}
} catch (ArrayIndexOutOfBoundsException e) {
// we handle this below...
System.out.println("FIXME: "
+ (toTM ? "TMW->TM" : "TM->TMW")
+ " conversion is in trouble");
System.out.println("font is " + (fontNum - 1)
+ ", char is "
+ (int)getText(i,1).charAt(0)
+ "; pos is " + i);
ThdlDebug.noteIffyCode();
}
if (null != dc) {
int fontSize = tibetanFontSize;
try {
fontSize = ((Integer)getCharacterElement(i).getAttributes().getAttribute(StyleConstants.FontSize)).intValue();
} catch (Exception e) {
// leave it as tibetanFontSize
}
insertDuff(fontSize, i, equivalent, !toTM);
remove(i+1, 1);
} else {
// DLC FIXME: insert into document a string
// saying "there's no TM equivalent for this."
// (For now, I'm inserting the alphabet and
// all the numbers in a big font in TMW to try
// and get some attention. And I've
// *documented* this on the website.)
String trickyTMW
= "!-\"-#-,-%-&-'-(-)-*-+-,-.-/-0-1-2-3-4-5-6-7-8-9-:-;-<-=->-?-0-1-2-3-4-5-6-7-8-9-";
equivalent[0] = new DuffData(trickyTMW, 1);
insertDuff(72, i, equivalent, true);
i += trickyTMW.length() + 1;
}
}
i++;
}
} catch (BadLocationException ble) {
ble.printStackTrace();
ThdlDebug.noteIffyCode();
}
}
} }

View file

@ -74,7 +74,12 @@ public class TibetanMachineWeb implements THDLWylieConstants {
private static String fileName = "tibwn.ini"; private static String fileName = "tibwn.ini";
private static final String DELIMITER = "~"; private static final String DELIMITER = "~";
private static Set top_vowels; private static Set top_vowels;
/** a way of encoding the choice of TibetanMachineWeb font from
that family of 10 fonts: */
private static SimpleAttributeSet[] webFontAttributeSet = new SimpleAttributeSet[11]; private static SimpleAttributeSet[] webFontAttributeSet = new SimpleAttributeSet[11];
/** a way of encoding the choice of TibetanMachine font from
that family of 5 fonts: */
private static SimpleAttributeSet[] normFontAttributeSet = new SimpleAttributeSet[6];
private static boolean hasDisambiguatingKey; //to disambiguate gy and g.y= private static boolean hasDisambiguatingKey; //to disambiguate gy and g.y=
private static char disambiguating_key; private static char disambiguating_key;
private static boolean hasSanskritStackingKey; //for stacking Sanskrit private static boolean hasSanskritStackingKey; //for stacking Sanskrit
@ -244,6 +249,12 @@ public class TibetanMachineWeb implements THDLWylieConstants {
StyleConstants.setFontFamily(webFontAttributeSet[i],tmwFontNames[i]); StyleConstants.setFontFamily(webFontAttributeSet[i],tmwFontNames[i]);
} }
normFontAttributeSet[0] = null;
for (int i=1; i<normFontAttributeSet.length; i++) {
normFontAttributeSet[i] = new SimpleAttributeSet();
StyleConstants.setFontFamily(normFontAttributeSet[i],tmFontNames[i]);
}
StringTokenizer sTok; StringTokenizer sTok;
topSet = new HashSet(); topSet = new HashSet();
leftSet = new HashSet(); leftSet = new HashSet();
@ -560,6 +571,23 @@ public static SimpleAttributeSet getAttributeSet(int font) {
return null; return null;
} }
/**
* Gets the AttributeSet for the given TibetanMachine font.
* This information is required in order to be able to put styled
* text into {@link TibetanDocument TibetanDocument}.
* @param font the number of the TibetanMachineWeb font for which
* you want the SimpleAttributeSet: TibetanMachine = 1,
* TibetanMachineSkt1 = 2, etc. up to 5
* @return a SimpleAttributeSet for the given font - that is,
* a way of encoding the font itself
*/
public static SimpleAttributeSet getAttributeSetTM(int font) {
if (font > -1 && font < normFontAttributeSet.length)
return normFontAttributeSet[font];
else
return null;
}
/** /**
* Says whether or not the character is formatting. * Says whether or not the character is formatting.
* @param c the character to be checked * @param c the character to be checked
@ -851,6 +879,10 @@ public static DuffCode getHalfHeightGlyph(String hashKey) {
return dc[REDUCED_C]; return dc[REDUCED_C];
} }
private static final DuffCode TMW_cr = new DuffCode(1, '\r');
private static final DuffCode TMW_lf = new DuffCode(1, '\n');
private static final DuffCode TMW_tab = new DuffCode(1, '\t');
/** Returns the DuffCode for the TibetanMachineWeb glyph corresponding /** Returns the DuffCode for the TibetanMachineWeb glyph corresponding
to the given TibetanMachine font to the given TibetanMachine font
(0=norm,1=Skt1,2=Skt2,3=Skt3,4=Skt4) and character(32-254). (0=norm,1=Skt1,2=Skt2,3=Skt3,4=Skt4) and character(32-254).
@ -861,14 +893,36 @@ public static DuffCode getHalfHeightGlyph(String hashKey) {
an existing TibetanMachine glyph, null is returned. In general, an existing TibetanMachine glyph, null is returned. In general,
though, this method may raise a runtime exception if you pass in a though, this method may raise a runtime exception if you pass in a
(font, ord) that doesn't correspond to an existing TibetanMachine (font, ord) that doesn't correspond to an existing TibetanMachine
glyph. */ glyph.
public static DuffCode mapTMtoTMW(int font, int ordinal) {
Only a few control characters are supported: '\r' (carriage
return), '\n' (line feed), and '\t' (tab).
*/
public static DuffCode mapTMtoTMW(int font, int ordinal)
throws ArrayIndexOutOfBoundsException {
if (ordinal < 32) {
if (ordinal == (int)'\r')
return TMW_cr;
else if (ordinal == (int)'\n')
return TMW_lf;
else if (ordinal == (int)'\t')
return TMW_tab;
else {
// for robustness, just return font 1, char ordinal.
ThdlDebug.noteIffyCode();
return null;
}
}
DuffCode ans = TMtoTMW[font][ordinal-32]; DuffCode ans = TMtoTMW[font][ordinal-32];
// comment this out to test via main(..): // comment this out to test via main(..):
ThdlDebug.verify(null != ans); ThdlDebug.verify(null != ans);
return ans; return ans;
} }
private static final DuffCode TM_cr = new DuffCode(1, '\r');
private static final DuffCode TM_lf = new DuffCode(1, '\n');
private static final DuffCode TM_tab = new DuffCode(1, '\t');
/** Returns the DuffCode for the TibetanMachine glyph corresponding to /** Returns the DuffCode for the TibetanMachine glyph corresponding to
the given TibetanMachineWeb font the given TibetanMachineWeb font
(0=TibetanMachineWeb,1=TibetanMachineWeb1,...) and character(32-127). (0=TibetanMachineWeb,1=TibetanMachineWeb1,...) and character(32-127).
@ -880,8 +934,27 @@ public static DuffCode mapTMtoTMW(int font, int ordinal) {
existing TibetanMachineWeb glyph, null is returned. In general, existing TibetanMachineWeb glyph, null is returned. In general,
though, this method may raise a runtime exception if you pass in a though, this method may raise a runtime exception if you pass in a
(font, ord) that doesn't correspond to an existing (font, ord) that doesn't correspond to an existing
TibetanMachineWeb glyph. */ TibetanMachineWeb glyph.
public static DuffCode mapTMWtoTM(int font, int ordinal) {
Only a few control characters are supported: '\r' (carriage
return), '\n' (line feed), and '\t' (tab).
*/
public static DuffCode mapTMWtoTM(int font, int ordinal)
throws ArrayIndexOutOfBoundsException {
if (ordinal < 32) {
if (ordinal == (int)'\r')
return TM_cr;
else if (ordinal == (int)'\n')
return TM_lf;
else if (ordinal == (int)'\t')
return TM_tab;
else {
// for robustness, just return font 1, char ordinal.
ThdlDebug.noteIffyCode();
return null;
}
}
DuffCode ans = TMWtoTM[font][ordinal-32]; DuffCode ans = TMWtoTM[font][ordinal-32];
// comment this out to test via main(..): // comment this out to test via main(..):
ThdlDebug.verify(null != ans || (font == 7 && ordinal == 91)); ThdlDebug.verify(null != ans || (font == 7 && ordinal == 91));
@ -975,7 +1048,13 @@ private static DuffCode getTMtoTMW(int font, int code) {
return TMtoTMW[font][code]; return TMtoTMW[font][code];
} }
private static int getTMFontNumber(String name) { /**
* Gets the TibetanMachine font number for this font name.
* @param name a font name
* @return between 1 and 5 if the font is one
* of the TibetanMachine fonts, otherwise 0
*/
public static int getTMFontNumber(String name) {
String internedName = name.intern(); String internedName = name.intern();
for (int i=1; i<tmFontNames.length; i++) { for (int i=1; i<tmFontNames.length; i++) {
if (internedName == tmFontNames[i]) if (internedName == tmFontNames[i])