2002-10-06 18:23:27 +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.text ;
import java.util.* ;
import javax.swing.* ;
import javax.swing.text.* ;
import javax.swing.text.rtf.RTFEditorKit ;
import java.io.* ;
import org.thdl.util.ThdlDebug ;
2003-06-01 23:05:32 +00:00
import org.thdl.util.ThdlOptions ;
2002-10-06 18:23:27 +00:00
2003-05-18 14:14:47 +00:00
/ * * Represents a character meant to be rendered in a certain font .
* @author David Chandler
* /
class CharacterInAGivenFont {
private char character ;
private String fontName ;
public CharacterInAGivenFont ( char ch , String font ) {
character = ch ;
fontName = font ;
}
public CharacterInAGivenFont ( String s , String font ) {
if ( s . length ( ) ! = 1 )
throw new Error ( " character in a given font was given a string "
+ s + " in a given font " ) ;
character = s . charAt ( 0 ) ;
fontName = font ;
}
public boolean equals ( Object x ) {
return ( ( x instanceof CharacterInAGivenFont )
& & ( ( CharacterInAGivenFont ) x ) . character = = character
& & ( ( CharacterInAGivenFont ) x ) . fontName . equals ( fontName ) ) ;
}
public int hashCode ( ) {
return ( int ) character + fontName . hashCode ( ) ;
}
public String toString ( ) {
String characterRepresentation
2003-06-22 00:14:18 +00:00
= " ' " + ( ( '\'' = = character )
? " \\ ' "
: new Character ( character ) . toString ( ) )
+ " ' [decimal " + ( int ) character + " ] " ;
2003-05-18 14:14:47 +00:00
if ( '\n' = = character )
2003-06-22 00:14:18 +00:00
characterRepresentation
= " newline [decimal " + ( int ) character + " ] " ;
2003-05-18 14:14:47 +00:00
if ( '\r' = = character )
2003-06-22 00:14:18 +00:00
characterRepresentation
= " carriage return " + ( int ) character + " ] " ;
2003-05-18 14:14:47 +00:00
return characterRepresentation + " in the font "
+ ( ( null = = fontName )
? " _ERROR_FINDING_FONT_ "
: fontName ) ;
}
}
2002-10-06 18:23:27 +00:00
/ * *
2002-11-02 03:38:59 +00:00
* A TibetanDocument is a styled document that knows about Tibetan and
* will respect line breaks and the like . It allows you to insert
* Tibetan also .
2002-10-06 18:23:27 +00:00
* @author Edward Garrett , Tibetan and Himalayan Digital Library
2002-11-02 03:38:59 +00:00
* @version 1 . 0 * /
2002-10-06 18:23:27 +00:00
public class TibetanDocument extends DefaultStyledDocument {
private int tibetanFontSize = 36 ;
2002-11-08 04:11:42 +00:00
/** Creates a new TibetanDocument with default styles. */
public TibetanDocument ( ) { super ( ) ; }
2002-11-02 03:38:59 +00:00
/** Do not use this contructor. */
private TibetanDocument ( AbstractDocument . Content c , StyleContext styles ) {
super ( c , styles ) ;
}
2002-10-06 18:23:27 +00:00
/ * *
* Creates a TibetanDocument .
* @param styles a StyleContext , which is simply passed on
* to DefaultStyledDocument ' s constructor
* /
public TibetanDocument ( StyleContext styles ) {
super ( styles ) ;
}
/ * *
* Sets the point size used by default for Tibetan text .
* @param size the point size for Tibetan text
* /
public void setTibetanFontSize ( int size ) {
tibetanFontSize = size ;
}
/ * *
* Gets the point size for Tibetan text .
* @return the point size used for Tibetan text
* /
public int getTibetanFontSize ( ) {
return tibetanFontSize ;
}
/ * *
* Writes the document to an OutputStream as Rich Text Format ( . rtf ) .
* @param out the OutputStream to write to
* /
public void writeRTFOutputStream ( OutputStream out ) throws IOException {
RTFEditorKit rtf = new RTFEditorKit ( ) ;
try {
rtf . write ( out , this , 0 , getLength ( ) ) ;
}
catch ( BadLocationException ble ) {
2002-11-02 03:38:59 +00:00
ThdlDebug . noteIffyCode ( ) ;
2002-10-06 18:23:27 +00:00
}
}
/ * *
* Inserts Tibetan text into the document . The font size is applied automatically ,
* according to the current Tibetan font size .
* @param offset the position at which you want to insert text
* @param s the string you want to insert
* @param attr the attributes to apply , normally a particular TibetanMachineWeb font
* @see # setTibetanFontSize ( int size )
* /
public void appendDuff ( int offset , String s , MutableAttributeSet attr ) {
2003-05-28 00:40:59 +00:00
appendDuff ( tibetanFontSize , offset , s , attr ) ;
}
private void appendDuff ( int fontSize , int offset , String s , MutableAttributeSet attr ) {
2002-10-06 18:23:27 +00:00
try {
2003-05-28 00:40:59 +00:00
StyleConstants . setFontSize ( attr , fontSize ) ;
2002-10-06 18:23:27 +00:00
insertString ( offset , s , attr ) ;
}
catch ( BadLocationException ble ) {
2002-11-02 03:38:59 +00:00
ThdlDebug . noteIffyCode ( ) ;
2002-10-06 18:23:27 +00:00
}
}
/ * *
* Inserts a stretch of TibetanMachineWeb data into the document .
* @param glyphs the array of Tibetan data you want to insert
* @param pos the position at which you want to insert text
* /
public int insertDuff ( int pos , DuffData [ ] glyphs ) {
2003-05-31 23:21:29 +00:00
return insertDuff ( tibetanFontSize , pos , glyphs , true ) ;
2003-05-28 00:40:59 +00:00
}
2003-06-08 23:12:52 +00:00
/ * * Replacing can be more efficient than inserting and then
removing . This replaces the glyph at position pos with glyph ,
which is interpreted as a TMW glyph if asTMW is true and a TM
glyph otherwise . The font size for the new glyph is
fontSize . * /
private void replaceDuff ( int fontSize , int pos ,
DuffData glyph , boolean asTMW ) {
MutableAttributeSet mas
= ( ( asTMW )
? TibetanMachineWeb . getAttributeSet ( glyph . font )
: TibetanMachineWeb . getAttributeSetTM ( glyph . font ) ) ;
StyleConstants . setFontSize ( mas , fontSize ) ;
try {
replace ( pos , 1 , glyph . text , mas ) ;
} catch ( BadLocationException ble ) {
ThdlDebug . noteIffyCode ( ) ;
}
}
2003-06-15 16:27:36 +00:00
/ * * Replacing can be more efficient than inserting and then
removing . This replaces the glyph at position pos with
unicode . The font size for the new unicode is fontSize . * /
private void replaceDuffWithUnicode ( int fontSize , int pos ,
String unicode ) {
MutableAttributeSet mas
= TibetanMachineWeb . getUnicodeAttributeSet ( ) ;
StyleConstants . setFontSize ( mas , fontSize ) ;
try {
replace ( pos , 1 , unicode , mas ) ;
} catch ( BadLocationException ble ) {
ThdlDebug . noteIffyCode ( ) ;
}
}
2003-05-31 23:21:29 +00:00
private int insertDuff ( int fontSize , int pos , DuffData [ ] glyphs , boolean asTMW ) {
2002-10-06 18:23:27 +00:00
if ( glyphs = = null )
return pos ;
MutableAttributeSet mas ;
for ( int i = 0 ; i < glyphs . length ; i + + ) {
2003-05-31 23:21:29 +00:00
mas = ( ( asTMW )
? TibetanMachineWeb . getAttributeSet ( glyphs [ i ] . font )
: TibetanMachineWeb . getAttributeSetTM ( glyphs [ i ] . font ) ) ;
2003-05-28 00:40:59 +00:00
appendDuff ( fontSize , pos , glyphs [ i ] . text , mas ) ;
2002-10-06 18:23:27 +00:00
pos + = glyphs [ i ] . text . length ( ) ;
}
return pos ;
}
/ * *
* Converts the entire 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 this document
* /
public String getWylie ( ) {
return getWylie ( 0 , getLength ( ) ) ;
}
/ * *
* Converts a portion of the 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 .
* @param begin the beginning of the region to convert
* @param end the end of the region to convert
* @return the string of Wylie corresponding to this document
* /
public String getWylie ( int begin , int end ) {
AttributeSet attr ;
String fontName ;
int fontNum ;
DuffCode dc ;
char ch ;
if ( begin > = end )
return " " ;
java . util . List dcs = new ArrayList ( ) ;
int i = begin ;
StringBuffer wylieBuffer = new StringBuffer ( ) ;
try {
while ( i < end ) {
attr = getCharacterElement ( i ) . getAttributes ( ) ;
fontName = StyleConstants . getFontFamily ( attr ) ;
ch = getText ( i , 1 ) . charAt ( 0 ) ;
//current character is formatting
if ( ch = = '\n' | | ch = = '\t' ) {
if ( dcs . size ( ) > 0 ) {
DuffCode [ ] dc_array = new DuffCode [ 0 ] ;
dc_array = ( DuffCode [ ] ) dcs . toArray ( dc_array ) ;
2002-11-02 03:38:59 +00:00
wylieBuffer . append ( TibTextUtils . getWylie ( dc_array ) ) ;
2002-10-06 18:23:27 +00:00
dcs . clear ( ) ;
}
wylieBuffer . append ( ch ) ;
}
//current character isn't TMW
else if ( ( 0 = = ( fontNum = TibetanMachineWeb . getTMWFontNumber ( fontName ) ) ) ) {
if ( dcs . size ( ) > 0 ) {
DuffCode [ ] dc_array = new DuffCode [ 0 ] ;
dc_array = ( DuffCode [ ] ) dcs . toArray ( dc_array ) ;
2002-11-02 03:38:59 +00:00
wylieBuffer . append ( TibTextUtils . getWylie ( dc_array ) ) ;
2002-10-06 18:23:27 +00:00
dcs . clear ( ) ;
}
}
//current character is convertable
else {
dc = new DuffCode ( fontNum , ch ) ;
dcs . add ( dc ) ;
}
i + + ;
}
if ( dcs . size ( ) > 0 ) {
DuffCode [ ] dc_array = new DuffCode [ 0 ] ;
dc_array = ( DuffCode [ ] ) dcs . toArray ( dc_array ) ;
2002-11-02 03:38:59 +00:00
wylieBuffer . append ( TibTextUtils . getWylie ( dc_array ) ) ;
2002-10-06 18:23:27 +00:00
}
return wylieBuffer . toString ( ) ;
}
catch ( BadLocationException ble ) {
ble . printStackTrace ( ) ;
ThdlDebug . noteIffyCode ( ) ;
}
return " " ;
}
2003-05-18 14:14:47 +00:00
/ * * Prints to standard output a list of all the indices of
characters that are not in a TMW font within the range [ start ,
end ) . Using a negative number for end means that this will
run to the end of the document . SPEED_FIXME : might be faster
to run over the elements , if they are one per font .
@return 1 if at least one non - TMW character was found in
the specified range , zero if none were , - 1 on error . * /
public int findAllNonTMWCharacters ( int begin , int end ) {
2003-05-18 17:17:52 +00:00
return findAllNonTMWCharacters ( begin , end , System . out ) ;
}
/** Configurable so that System.out isn't necessarily used. */
public int findAllNonTMWCharacters ( int begin , int end , PrintStream out ) {
2003-06-22 00:14:18 +00:00
return findCharacters ( begin , end , out , " Non-TMW " , true ) ;
}
/ * * Prints to standard output a list of all the indices of
characters that are not in a TM font within the range [ start ,
end ) . Using a negative number for end means that this will
run to the end of the document . SPEED_FIXME : might be faster
to run over the elements , if they are one per font .
@return 1 if at least one non - TM character was found in
the specified range , zero if none were , - 1 on error . * /
public int findAllNonTMCharacters ( int begin , int end ) {
return findAllNonTMCharacters ( begin , end , System . out ) ;
}
/** Configurable so that System.out isn't necessarily used. */
public int findAllNonTMCharacters ( int begin , int end , PrintStream out ) {
return findCharacters ( begin , end , out , " Non-TM " , true ) ;
2003-05-18 14:14:47 +00:00
}
/ * * Finds the first occurrence of a non - TMW character in a given
font and prints it to System . out . If you have a Tahoma
2003-06-22 00:14:18 +00:00
newline and an Arial newline , e . g . , the first occurrence of
each will be reported .
2003-05-18 14:14:47 +00:00
< p > Works within the range [ start , end ) . Using a negative
number for end means that this will run to the end of the
document . SPEED_FIXME : might be faster to run over the
elements , if they are one per font .
@return 1 if at least one non - TMW character was found in
the specified range , zero if none were , - 1 on error . * /
public int findSomeNonTMWCharacters ( int begin , int end ) {
2003-05-18 17:17:52 +00:00
return findSomeNonTMWCharacters ( begin , end , System . out ) ;
}
2003-06-22 00:14:18 +00:00
/ * * Finds the first occurrence of a non - TM character in a given
font and prints it to System . out . If you have a Tahoma
newline and an Arial newline , e . g . , the first occurrence of
each will be reported .
< p > Works within the range [ start , end ) . Using a negative
number for end means that this will run to the end of the
document . SPEED_FIXME : might be faster to run over the
elements , if they are one per font .
@return 1 if at least one non - TMW character was found in
the specified range , zero if none were , - 1 on error . * /
public int findSomeNonTMCharacters ( int begin , int end ) {
return findSomeNonTMCharacters ( begin , end , System . out ) ;
}
2003-05-18 17:17:52 +00:00
/** Configurable so that System.out isn't necessarily used. */
public int findSomeNonTMWCharacters ( int begin , int end , PrintStream out ) {
2003-06-22 00:14:18 +00:00
return findCharacters ( begin , end , out , " Non-TMW " , false ) ;
}
/** Configurable so that System.out isn't necessarily used. */
public int findSomeNonTMCharacters ( int begin , int end , PrintStream out ) {
return findCharacters ( begin , end , out , " Non-TM " , false ) ;
}
/ * * Pass in whatKind = = " Non-TMW " or whatKind = = " Non-TM " for now ; see
callers and the code to understand the semantics . Pass in all
= = true to find all characters or all = = false to report each
character just once . * /
private int findCharacters ( int begin , int end , PrintStream out ,
String whatKind , boolean all ) {
if ( whatKind ! = " Non-TMW " & & whatKind ! = " Non-TM " )
throw new IllegalArgumentException ( " You didn't use an interned string. " ) ;
2003-05-18 14:14:47 +00:00
if ( end < 0 )
end = getLength ( ) ;
if ( begin > = end )
return 0 ;
int i = begin ;
int returnValue = 0 ;
try {
2003-06-22 00:14:18 +00:00
HashMap cgfTable = null ;
if ( ! all ) cgfTable = new HashMap ( ) ;
2003-05-18 14:14:47 +00:00
while ( i < end ) {
AttributeSet attr = getCharacterElement ( i ) . getAttributes ( ) ;
String fontName = StyleConstants . getFontFamily ( attr ) ;
2003-06-22 00:14:18 +00:00
if ( ( whatKind = = " Non-TMW "
& & ( 0 = = TibetanMachineWeb . getTMWFontNumber ( fontName ) ) )
| | ( whatKind = = " Non-TM "
& & ( 0 = = TibetanMachineWeb . getTMFontNumber ( fontName ) ) ) ) {
2003-05-18 14:14:47 +00:00
returnValue = 1 ;
CharacterInAGivenFont cgf
= new CharacterInAGivenFont ( getText ( i , 1 ) , fontName ) ;
2003-06-22 00:14:18 +00:00
boolean doOutput = all ;
if ( ! all & & ! cgfTable . containsKey ( cgf ) ) {
2003-05-18 14:14:47 +00:00
cgfTable . put ( cgf , " yes this character appears once " ) ;
2003-06-22 00:14:18 +00:00
doOutput = true ;
2003-05-18 14:14:47 +00:00
}
2003-06-22 00:14:18 +00:00
if ( true = = doOutput )
out . println ( whatKind + " character "
+ cgf + " appears "
+ ( ( all ) ? " " : " first " )
+ " at location " + i ) ;
2003-05-18 14:14:47 +00:00
}
i + + ;
}
} catch ( BadLocationException ble ) {
2003-05-18 17:17:52 +00:00
ble . printStackTrace ( out ) ;
2003-05-18 14:14:47 +00:00
ThdlDebug . noteIffyCode ( ) ;
returnValue = - 1 ;
}
return returnValue ;
}
private static final DuffData [ ] leftCurlyBraceTMW
= new DuffData [ ] { new DuffData ( " { " , 1 ) } ;
private static final DuffData [ ] rightCurlyBraceTMW
= new DuffData [ ] { new DuffData ( " } " , 1 ) } ;
private static final DuffData [ ] backslashTMW
= new DuffData [ ] { new DuffData ( " \\ " , 2 ) } ;
/ * * This is a band - aid used to help Jskad fix RTF files that are
mostly TMW but have some Tahoma characters that should be TMW .
Replaces '{' , '}' , and '\\' characters with the correct
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
2003-05-31 23:21:29 +00:00
as you like it before using this ( well , it usually gets it
right on its own , but just in case ) . SPEED_FIXME : might be
2003-05-18 14:14:47 +00:00
faster to run over the elements , if they are one per font . * /
public void replaceTahomaCurlyBracesAndBackslashes ( int begin , int end ) {
if ( end < 0 )
end = getLength ( ) ;
if ( begin > = end )
return ;
int i = begin ;
try {
while ( i < end ) {
AttributeSet attr = getCharacterElement ( i ) . getAttributes ( ) ;
String fontName = StyleConstants . getFontFamily ( attr ) ;
if ( fontName . equals ( " Tahoma " ) ) {
DuffData [ ] toReplaceWith = null ;
switch ( getText ( i , 1 ) . charAt ( 0 ) ) {
case '{' :
toReplaceWith = leftCurlyBraceTMW ;
break ;
case '}' :
toReplaceWith = rightCurlyBraceTMW ;
break ;
case '\\' :
toReplaceWith = backslashTMW ;
break ;
}
if ( null ! = toReplaceWith ) {
2003-06-01 23:05:32 +00:00
// SPEED_FIXME: determining font size might be slow
2003-05-28 00:40:59 +00:00
int fontSize = tibetanFontSize ;
try {
fontSize = ( ( Integer ) getCharacterElement ( i ) . getAttributes ( ) . getAttribute ( StyleConstants . FontSize ) ) . intValue ( ) ;
} catch ( Exception e ) {
// leave it as tibetanFontSize
}
2003-06-08 23:12:52 +00:00
if ( replaceInsteadOfInserting ( ) ) {
replaceDuff ( fontSize , i , toReplaceWith [ 0 ] , true ) ;
} else {
if ( insertBefore ( ) ) {
insertDuff ( fontSize , i , toReplaceWith , true ) ;
remove ( i + 1 , 1 ) ;
} else {
insertDuff ( fontSize , i + 1 , toReplaceWith , true ) ;
remove ( i , 1 ) ;
}
}
2003-05-18 14:14:47 +00:00
}
}
i + + ;
}
} catch ( BadLocationException ble ) {
ble . printStackTrace ( ) ;
ThdlDebug . noteIffyCode ( ) ;
}
}
2003-05-31 23:21:29 +00:00
/ * * 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
2003-06-01 23:05:32 +00:00
over the elements , if they are one per font .
2003-06-08 23:12:52 +00:00
@return false on 100 % success , true if any exceptional case
2003-06-01 23:05:32 +00:00
was encountered
@param errors if non - null , then notes about all exceptional
cases will be appended to this StringBuffer
* /
public boolean convertToTM ( int begin , int end , StringBuffer errors ) {
2003-06-15 16:27:36 +00:00
return convertHelper ( begin , end , true , false , errors ) ;
2003-05-31 23:21:29 +00:00
}
/ * * 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
2003-06-01 23:05:32 +00:00
faster to run over the elements , if they are one per font .
2003-06-08 23:12:52 +00:00
@return false on 100 % success , true if any exceptional case
2003-06-01 23:05:32 +00:00
was encountered
@param errors if non - null , then notes about all exceptional
cases will be appended to this StringBuffer
* /
public boolean convertToTMW ( int begin , int end , StringBuffer errors ) {
2003-06-15 16:27:36 +00:00
return convertHelper ( begin , end , false , false , errors ) ;
}
/ * * Converts all TibetanMachineWeb glyphs in the document to
Unicode . 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 .
@return false on 100 % success , true if any exceptional case
was encountered
@param errors if non - null , then notes about all exceptional
cases will be appended to this StringBuffer * /
public boolean convertToUnicode ( int begin , int end , StringBuffer errors ) {
return convertHelper ( begin , end , false , true , errors ) ;
2003-05-31 23:21:29 +00:00
}
2003-06-08 23:12:52 +00:00
/ * * For debugging only . Start with an empty document , and call
this on it . You ' ll get all the TibetanMachine glyphs
inserted , in order , into your document . * /
private void insertAllTMGlyphs ( ) {
int font ;
int ord ;
DuffData [ ] equivalent = new DuffData [ 1 ] ;
equivalent [ 0 ] = new DuffData ( ) ;
int count = 0 ;
for ( font = 0 ; font < 5 ; font + + ) {
for ( ord = 32 ; ord < 255 ; ord + + ) {
if ( TibetanMachineWeb . mapTMtoTMW ( font , ord ) ! = null ) {
equivalent [ 0 ] . setData ( ( char ) ord , font + 1 ) ;
try {
insertDuff ( tibetanFontSize , count + + , equivalent , false ) ;
} catch ( NullPointerException e ) {
System . err . println ( " nullpointerexception happened: font is " + font + " ord is " + ord ) ;
}
}
}
}
}
/ * * This setting determines whether the formatting is preserved ,
but with infinite loops in it , or is not preserved , but works
well . Inserting + removing must be used rather than replacing
because you get the same exception otherwise . FIXME : try Java
1 . 5 - - maybe it beats Java 1 . 4 .
[ java ] javax . swing . text . StateInvariantError : infinite loop in formatting
[ java ] at javax . swing . text . FlowView$FlowStrategy . layout ( FlowView . java : 404 )
[ java ] at javax . swing . text . FlowView . layout ( FlowView . java : 182 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . text . BoxView . updateChildSizes ( BoxView . java : 348 )
[ java ] at javax . swing . text . BoxView . setSpanOnAxis ( BoxView . java : 330 )
[ java ] at javax . swing . text . BoxView . layout ( BoxView . java : 682 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . plaf . basic . BasicTextUI$RootView . setSize ( BasicTextUI . java : 1598 )
[ java ] at javax . swing . plaf . basic . BasicTextUI . getPreferredSize ( BasicTextUI . java : 800 )
[ java ] at javax . swing . JComponent . getPreferredSize ( JComponent . java : 1272 )
[ java ] at javax . swing . JEditorPane . getPreferredSize ( JEditorPane . java : 1206 )
[ java ] at javax . swing . ScrollPaneLayout . layoutContainer ( ScrollPaneLayout . java : 769 )
[ java ] at java . awt . Container . layout ( Container . java : 1017 )
[ java ] at java . awt . Container . doLayout ( Container . java : 1007 )
[ java ] at java . awt . Container . validateTree ( Container . java : 1089 )
[ java ] at java . awt . Container . validate ( Container . java : 1064 )
[ java ] at javax . swing . RepaintManager . validateInvalidComponents ( RepaintManager . java : 353 )
[ java ] at javax . swing . SystemEventQueueUtilities$ComponentWorkRequest . run ( SystemEventQueueUtilities . java : 116 )
[ java ] at java . awt . event . InvocationEvent . dispatch ( InvocationEvent . java : 178 )
[ java ] at java . awt . EventQueue . dispatchEvent ( EventQueue . java : 448 )
[ java ] at java . awt . EventDispatchThread . pumpOneEventForHierarchy ( EventDispatchThread . java : 197 )
[ java ] at java . awt . EventDispatchThread . pumpEventsForHierarchy ( EventDispatchThread . java : 150 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 144 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 136 )
[ java ] at java . awt . EventDispatchThread . run ( EventDispatchThread . java : 99 )
[ java ] javax . swing . text . StateInvariantError : infinite loop in formatting
[ java ] at javax . swing . text . FlowView$FlowStrategy . layout ( FlowView . java : 404 )
[ java ] at javax . swing . text . FlowView . layout ( FlowView . java : 182 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . text . BoxView . updateChildSizes ( BoxView . java : 348 )
[ java ] at javax . swing . text . BoxView . setSpanOnAxis ( BoxView . java : 316 )
[ java ] at javax . swing . text . BoxView . layout ( BoxView . java : 683 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . plaf . basic . BasicTextUI$RootView . setSize ( BasicTextUI . java : 1598 )
[ java ] at javax . swing . plaf . basic . BasicTextUI . getPreferredSize ( BasicTextUI . java : 800 )
[ java ] at javax . swing . JComponent . getPreferredSize ( JComponent . java : 1272 )
[ java ] at javax . swing . JEditorPane . getPreferredSize ( JEditorPane . java : 1206 )
[ java ] at javax . swing . ScrollPaneLayout . layoutContainer ( ScrollPaneLayout . java : 769 )
[ java ] at java . awt . Container . layout ( Container . java : 1017 )
[ java ] at java . awt . Container . doLayout ( Container . java : 1007 )
[ java ] at java . awt . Container . validateTree ( Container . java : 1089 )
[ java ] at java . awt . Container . validate ( Container . java : 1064 )
[ java ] at javax . swing . RepaintManager . validateInvalidComponents ( RepaintManager . java : 353 )
[ java ] at javax . swing . SystemEventQueueUtilities$ComponentWorkRequest . run ( SystemEventQueueUtilities . java : 116 )
[ java ] at java . awt . event . InvocationEvent . dispatch ( InvocationEvent . java : 178 )
[ java ] at java . awt . EventQueue . dispatchEvent ( EventQueue . java : 448 )
[ java ] at java . awt . EventDispatchThread . pumpOneEventForHierarchy ( EventDispatchThread . java : 197 )
[ java ] at java . awt . EventDispatchThread . pumpEventsForHierarchy ( EventDispatchThread . java : 150 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 144 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 136 )
[ java ] at java . awt . EventDispatchThread . run ( EventDispatchThread . java : 99 )
[ java ] javax . swing . text . StateInvariantError : infinite loop in formatting
[ java ] at javax . swing . text . FlowView$FlowStrategy . layout ( FlowView . java : 404 )
[ java ] at javax . swing . text . FlowView . layout ( FlowView . java : 182 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . text . BoxView . updateChildSizes ( BoxView . java : 348 )
[ java ] at javax . swing . text . BoxView . setSpanOnAxis ( BoxView . java : 316 )
[ java ] at javax . swing . text . BoxView . layout ( BoxView . java : 683 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . plaf . basic . BasicTextUI$RootView . setSize ( BasicTextUI . java : 1598 )
[ java ] at javax . swing . plaf . basic . BasicTextUI . modelToView ( BasicTextUI . java : 934 )
[ java ] at javax . swing . text . DefaultCaret . repaintNewCaret ( DefaultCaret . java : 1044 )
[ java ] at javax . swing . text . DefaultCaret$1 . run ( DefaultCaret . java : 1023 )
[ java ] at java . awt . event . InvocationEvent . dispatch ( InvocationEvent . java : 178 )
[ java ] at java . awt . EventQueue . dispatchEvent ( EventQueue . java : 448 )
[ java ] at java . awt . EventDispatchThread . pumpOneEventForHierarchy ( EventDispatchThread . java : 197 )
[ java ] at java . awt . EventDispatchThread . pumpEventsForHierarchy ( EventDispatchThread . java : 150 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 144 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 136 )
[ java ] at java . awt . EventDispatchThread . run ( EventDispatchThread . java : 99 )
[ java ] javax . swing . text . StateInvariantError : infinite loop in formatting
[ java ] at javax . swing . text . FlowView$FlowStrategy . layout ( FlowView . java : 404 )
[ java ] at javax . swing . text . FlowView . layout ( FlowView . java : 182 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . text . BoxView . updateChildSizes ( BoxView . java : 348 )
[ java ] at javax . swing . text . BoxView . setSpanOnAxis ( BoxView . java : 316 )
[ java ] at javax . swing . text . BoxView . layout ( BoxView . java : 683 )
[ java ] at javax . swing . text . BoxView . setSize ( BoxView . java : 379 )
[ java ] at javax . swing . plaf . basic . BasicTextUI$RootView . setSize ( BasicTextUI . java : 1598 )
[ java ] at javax . swing . plaf . basic . BasicTextUI . getPreferredSize ( BasicTextUI . java : 800 )
[ java ] at javax . swing . JComponent . getPreferredSize ( JComponent . java : 1272 )
[ java ] at javax . swing . JEditorPane . getPreferredSize ( JEditorPane . java : 1206 )
[ java ] at javax . swing . ScrollPaneLayout . layoutContainer ( ScrollPaneLayout . java : 769 )
[ java ] at java . awt . Container . layout ( Container . java : 1017 )
[ java ] at java . awt . Container . doLayout ( Container . java : 1007 )
[ java ] at java . awt . Container . validateTree ( Container . java : 1089 )
[ java ] at java . awt . Container . validate ( Container . java : 1064 )
[ java ] at javax . swing . RepaintManager . validateInvalidComponents ( RepaintManager . java : 353 )
[ java ] at javax . swing . SystemEventQueueUtilities$ComponentWorkRequest . run ( SystemEventQueueUtilities . java : 116 )
[ java ] at java . awt . event . InvocationEvent . dispatch ( InvocationEvent . java : 178 )
[ java ] at java . awt . EventQueue . dispatchEvent ( EventQueue . java : 448 )
[ java ] at java . awt . EventDispatchThread . pumpOneEventForHierarchy ( EventDispatchThread . java : 197 )
[ java ] at java . awt . EventDispatchThread . pumpEventsForHierarchy ( EventDispatchThread . java : 150 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 144 )
[ java ] at java . awt . EventDispatchThread . pumpEvents ( EventDispatchThread . java : 136 )
[ java ] at java . awt . EventDispatchThread . run ( EventDispatchThread . java : 99 ) * /
private static boolean insertBefore ( ) {
return ! ThdlOptions . getBooleanOption ( " thdl.insert.rtf.after.not.before " ) ;
}
private static boolean replaceInsteadOfInserting ( ) {
return ! ThdlOptions . getBooleanOption ( " thdl.insert.and.remove.instead.of.replacing " ) ;
}
2003-06-15 16:27:36 +00:00
/ * * Helper function . Converts TMW - > TM if ! toUnicode & & toTM ,
TM - > TMW if ! toUnicode & & ! toTM , TMW - > Unicode if toUnicode .
2003-06-01 23:05:32 +00:00
@param errors if non - null , then notes about all exceptional
cases will be appended to this StringBuffer
2003-06-08 23:12:52 +00:00
@return false on 100 % success , true if any exceptional case
2003-06-01 23:05:32 +00:00
was encountered
2003-06-15 16:27:36 +00:00
@see convertToUnicode ( int , int )
2003-05-31 23:21:29 +00:00
@see convertToTMW ( int , int )
@see convertToTM ( int , int ) * /
2003-06-15 16:27:36 +00:00
private boolean convertHelper ( int begin , int end , boolean toTM ,
boolean toUnicode , StringBuffer errors ) {
// toTM is ignored when toUnicode is true:
ThdlDebug . verify ( ! toUnicode | | ! toTM ) ;
2003-06-01 23:05:32 +00:00
boolean toStdout = ThdlOptions . getBooleanOption ( " thdl.debug " ) ;
boolean errorReturn = false ;
2003-05-31 23:21:29 +00:00
if ( end < 0 )
end = getLength ( ) ;
if ( begin > = end )
2003-06-01 23:05:32 +00:00
return errorReturn ; // nothing to do, so no errors in the doing.
2003-05-31 23:21:29 +00:00
int i = begin ;
2003-06-01 23:05:32 +00:00
HashMap problemGlyphsTable = new HashMap ( ) ;
2003-05-31 23:21:29 +00:00
try {
2003-06-01 23:05:32 +00:00
Position endPos = createPosition ( end ) ;
2003-05-31 23:21:29 +00:00
DuffData [ ] equivalent = new DuffData [ 1 ] ;
equivalent [ 0 ] = new DuffData ( ) ;
2003-06-08 22:37:38 +00:00
int errorGlyphLocation = 0 ;
2003-06-01 23:05:32 +00:00
while ( i < endPos . getOffset ( ) ) {
2003-05-31 23:21:29 +00:00
AttributeSet attr = getCharacterElement ( i ) . getAttributes ( ) ;
String fontName = StyleConstants . getFontFamily ( attr ) ;
int fontNum
2003-06-15 16:27:36 +00:00
= ( ( toTM | | toUnicode )
2003-05-31 23:21:29 +00:00
? TibetanMachineWeb . getTMWFontNumber ( fontName )
: TibetanMachineWeb . getTMFontNumber ( fontName ) ) ;
if ( 0 ! = fontNum ) {
DuffCode dc = null ;
2003-06-15 16:27:36 +00:00
String unicode = null ;
if ( toUnicode ) {
unicode = TibetanMachineWeb . mapTMWtoUnicode ( fontNum - 1 ,
getText ( i , 1 ) . charAt ( 0 ) ) ;
2003-06-01 23:05:32 +00:00
} else {
2003-06-15 16:27:36 +00:00
if ( toTM ) {
dc = TibetanMachineWeb . mapTMWtoTM ( fontNum - 1 ,
getText ( i , 1 ) . charAt ( 0 ) ) ;
} else {
dc = TibetanMachineWeb . mapTMtoTMW ( fontNum - 1 ,
getText ( i , 1 ) . charAt ( 0 ) ) ;
}
2003-05-31 23:21:29 +00:00
}
2003-06-15 16:27:36 +00:00
if ( null ! = dc | | null ! = unicode ) {
2003-06-01 23:05:32 +00:00
// SPEED_FIXME: determining font size might be slow
2003-05-31 23:21:29 +00:00
int fontSize = tibetanFontSize ;
try {
fontSize = ( ( Integer ) getCharacterElement ( i ) . getAttributes ( ) . getAttribute ( StyleConstants . FontSize ) ) . intValue ( ) ;
} catch ( Exception e ) {
// leave it as tibetanFontSize
}
2003-06-15 16:27:36 +00:00
if ( ! toUnicode ) {
equivalent [ 0 ] . setData ( dc . getCharacter ( ) ,
dc . getFontNum ( ) ) ;
}
2003-06-01 23:05:32 +00:00
// We have two choices: remove-then-insert
// second vs. insert-then-remove and also
// insert-before vs. insert-after. It turns
// out that insert-after preserves formatting
// whereas insert-before doesn't. And we do
// insert-then-remove because we're guessing
// that helps with formatting too.
2003-06-08 23:12:52 +00:00
if ( replaceInsteadOfInserting ( ) ) {
2003-06-15 16:27:36 +00:00
if ( toUnicode ) {
replaceDuffWithUnicode ( fontSize , i , unicode ) ;
2003-06-22 04:08:33 +00:00
i + = unicode . length ( ) - 1 ; // we do i++ below
2003-06-15 16:27:36 +00:00
} else {
replaceDuff ( fontSize , i , equivalent [ 0 ] , ! toTM ) ;
}
2003-06-08 23:12:52 +00:00
} else {
2003-06-22 16:11:58 +00:00
if ( toUnicode )
throw new Error ( " Please execute 'Clear Preferences' and retry -- you've caused us to go into insert-and-remove mode, as opposed to replace mode, and replacing, the default preference, is the only way you can get TMW->Unicode conversion at present. " ) ;
2003-06-08 23:12:52 +00:00
if ( insertBefore ( ) ) {
insertDuff ( fontSize , i , equivalent , ! toTM ) ;
remove ( i + 1 , 1 ) ;
} else {
insertDuff ( fontSize , i + 1 , equivalent , ! toTM ) ;
remove ( i , 1 ) ;
}
}
2003-05-31 23:21:29 +00:00
} else {
// DLC FIXME: insert into document a string
2003-06-01 23:05:32 +00:00
// saying "<<[[there's no TM equivalent for
// this, details are ...]]>>" (For now, I'm
// inserting the alphabet in a big font in TMW
// to try and get some attention. And I've
2003-06-08 22:37:38 +00:00
// *documented* this on the website. I'm also
// putting the oddballs at the start of the
// document, but I haven't documented that
// (FIXME).)
2003-06-01 23:05:32 +00:00
errorReturn = true ;
CharacterInAGivenFont cgf
= new CharacterInAGivenFont ( getText ( i , 1 ) , fontName ) ;
if ( ! problemGlyphsTable . containsKey ( cgf ) ) {
problemGlyphsTable . put ( cgf , " yes this character appears once " ) ;
if ( null ! = errors ) {
String err
2003-06-15 16:27:36 +00:00
= ( toUnicode
? " TMW->Unicode "
: ( toTM ? " TMW->TM " : " TM->TMW " ) )
2003-06-01 23:05:32 +00:00
+ " conversion failed for a glyph: \ nFont is "
+ fontName + " , glyph number is "
+ ( int ) getText ( i , 1 ) . charAt ( 0 )
+ " ; first position found (from zero) is "
+ i + " \ n " ;
errors . append ( err ) ;
if ( toStdout ) {
System . out . print ( err ) ;
}
2003-06-08 22:37:38 +00:00
// Now also put this problem glyph at
// the beginning of the document:
equivalent [ 0 ] . setData ( getText ( i , 1 ) , fontNum ) ;
insertDuff ( 72 , errorGlyphLocation + + ,
2003-06-15 16:27:36 +00:00
equivalent , toUnicode | | toTM ) ;
2003-06-08 22:37:38 +00:00
+ + i ;
2003-06-01 23:05:32 +00:00
}
}
2003-06-15 16:27:36 +00:00
if ( ThdlOptions . getBooleanOption ( " thdl.leave.bad.tm.tmw.conversions.in.place " ) ) {
String trickyTMW
= " !- \" -#-$-%-&-'-(-)-*-+-,-.-/-0-1-2-3-4-5-6-7-8-9-:-;-<-=->-?- " ;
equivalent [ 0 ] . setData ( trickyTMW , 1 ) ;
insertDuff ( 72 , i , equivalent , true ) ;
i + = trickyTMW . length ( ) ;
}
2003-05-31 23:21:29 +00:00
}
}
i + + ;
}
2003-06-08 22:37:38 +00:00
if ( ! ThdlOptions . getBooleanOption ( " thdl.leave.bad.tm.tmw.conversions.in.place " ) ) {
// Remove all characters other than the oddballs:
if ( errorGlyphLocation > 0 ) {
remove ( errorGlyphLocation , getLength ( ) - errorGlyphLocation - 1 ) ;
}
}
2003-05-31 23:21:29 +00:00
} catch ( BadLocationException ble ) {
ble . printStackTrace ( ) ;
ThdlDebug . noteIffyCode ( ) ;
}
2003-06-01 23:05:32 +00:00
return errorReturn ;
2003-05-31 23:21:29 +00:00
}
2002-10-06 18:23:27 +00:00
}