Handle saving unicode text where the underlying record was byte based, by

swapping the record


git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353792 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2005-11-13 13:28:34 +00:00
parent 67901ee8f9
commit cf4e00a052
2 changed files with 70 additions and 21 deletions

View File

@ -36,12 +36,14 @@ import org.apache.poi.util.StringUtil;
public class TextRun
{
private TextHeaderAtom _headerAtom;
private TextBytesAtom _byteAtom;
private TextCharsAtom _charAtom;
private StyleTextPropAtom _styleAtom;
private boolean _isUnicode;
private RichTextRun[] _rtRuns;
// Note: These fields are protected to help with unit testing
// Other classes shouldn't really go playing with them!
protected TextHeaderAtom _headerAtom;
protected TextBytesAtom _byteAtom;
protected TextCharsAtom _charAtom;
protected StyleTextPropAtom _styleAtom;
protected boolean _isUnicode;
protected RichTextRun[] _rtRuns;
/**
* Constructs a Text Run from a Unicode text block
@ -101,6 +103,13 @@ public class TextRun
* Saves the given string to the records. Doesn't touch the stylings.
*/
private void storeText(String s) {
// Remove a single trailing \n, as there is an implicit one at the
// end of every record
if(s.endsWith("\n")) {
s = s.substring(0, s.length()-1);
}
// Store in the appropriate record
if(_isUnicode) {
// The atom can safely convert to unicode
_charAtom.setText(s);
@ -113,7 +122,27 @@ public class TextRun
StringUtil.putCompressedUnicode(s,text,0);
_byteAtom.setText(text);
} else {
throw new RuntimeException("Setting of unicode text is currently only possible for Text Runs that are Unicode in the file, sorry. For now, please convert that text to us-ascii and re-try it");
// Need to swap a TextBytesAtom for a TextCharsAtom
// Build the new TextCharsAtom
_charAtom = new TextCharsAtom();
_charAtom.setText(s);
// Use the TextHeaderAtom to do the swap on the parent
RecordContainer parent = _headerAtom.getParentRecord();
Record[] cr = parent.getChildRecords();
for(int i=0; i<cr.length; i++) {
// Look for TextBytesAtom
if(cr[i].equals(_byteAtom)) {
// Found it, so replace, then all done
cr[i] = _charAtom;
break;
}
}
// Flag the change
_byteAtom = null;
_isUnicode = true;
}
}
}
@ -151,19 +180,25 @@ public class TextRun
// The building relies on the old text still being present
StringBuffer newText = new StringBuffer();
for(int i=0; i<_rtRuns.length; i++) {
// Update start position
if(i > runID) {
// Do we need to update the start position of this run?
if(i <= runID) {
// Change is after this, so don't need to change start position
} else {
// Change has occured, so update start position
_rtRuns[i].updateStartPosition(newText.length());
}
// Grab new text
// Build up the new text
if(i != runID) {
// Not the affected run, so keep old text
newText.append(_rtRuns[i].getRawText());
} else {
// Affected run, so use new text
newText.append(s);
}
}
// Save the new text
// Now we can save the new text
storeText(newText.toString());
}
@ -177,7 +212,11 @@ public class TextRun
storeText(s);
// Now handle record stylings:
// If there isn't styling
// no change, stays with no styling
// If there is styling:
// everthing gets the same style that the first block has
if(_styleAtom != null) {
LinkedList pStyles = _styleAtom.getParagraphStyles();
while(pStyles.size() > 1) { pStyles.removeLast(); }
@ -188,6 +227,7 @@ public class TextRun
TextPropCollection cCol = (TextPropCollection)cStyles.getFirst();
pCol.updateTextSize(s.length());
cCol.updateTextSize(s.length());
}
// Finally, zap and re-do the RichTextRuns
_rtRuns = new RichTextRun[1];

View File

@ -71,6 +71,15 @@ public class TextCharsAtom extends RecordAtom
_text = new byte[len-8];
System.arraycopy(source,start+8,_text,0,len-8);
}
/**
* Create an empty TextCharsAtom
*/
public TextCharsAtom() {
// 0 length header
_header = new byte[] { 0, 0, 0xA0-256, 0x0f, 0, 0, 0, 0 };
// Empty text
_text = new byte[0];
}
/**
* We are of type 4000