From 90bc3e260a0edfaa1e2dc75539c1c81bf64e86ba Mon Sep 17 00:00:00 2001 From: Avik Sengupta Date: Thu, 28 Apr 2005 13:35:38 +0000 Subject: [PATCH] PR:17039 - DBCS chars in header and footer Obtained from: kamoshida.toshiaki@future.co.jp Tweaked and tests added by self. git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353654 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/record/FooterRecord.java | 68 ++++++++++++++--- .../apache/poi/hssf/record/HeaderRecord.java | 69 +++++++++++++++--- .../org/apache/poi/hssf/data/DBCSHeader.xls | Bin 0 -> 16384 bytes .../hssf/usermodel/TestHSSFHeaderFooter.java | 62 ++++++++++++++++ 4 files changed, 180 insertions(+), 19 deletions(-) create mode 100644 src/testcases/org/apache/poi/hssf/data/DBCSHeader.xls diff --git a/src/java/org/apache/poi/hssf/record/FooterRecord.java b/src/java/org/apache/poi/hssf/record/FooterRecord.java index a4ec36c937..06a1497e8b 100644 --- a/src/java/org/apache/poi/hssf/record/FooterRecord.java +++ b/src/java/org/apache/poi/hssf/record/FooterRecord.java @@ -36,7 +36,8 @@ public class FooterRecord { public final static short sid = 0x15; private byte field_1_footer_len; - private String field_2_footer; + private byte field_2_unicode_flag; + private String field_3_footer; public FooterRecord() { @@ -82,11 +83,46 @@ public class FooterRecord if (size > 0) { field_1_footer_len = data[ 0 + offset ]; - field_2_footer = StringUtil.getFromCompressedUnicode(data, 3 + offset, // [Shawn] Changed 1 to 3 for offset of string - LittleEndian.ubyteToInt( field_1_footer_len) ); + field_2_unicode_flag = data[ 2 + offset ]; + if(isMultibyte()) + { + field_3_footer = StringUtil.getFromUnicodeLE( + data,3 + offset,LittleEndian.ubyteToInt(field_1_footer_len)); + } + else + { + field_3_footer = new String(data, 3 + offset, // [Shawn] Changed 1 to 3 for offset of string + LittleEndian.ubyteToInt( field_1_footer_len) ); + } } } + /** + * see the unicode flag + * + * @return boolean flag + * true:footer string has at least one multibyte character + */ + public boolean isMultibyte() { + return ((field_2_unicode_flag & 0xFF) == 1); + } + + /** + * check the parameter has multibyte character + * + * @param value string to check + * @return boolean result + * true:string has at least one multibyte character + */ + private static boolean hasMultibyte(String value){ + if( value == null )return false; + for(int i = 0 ; i < value.length() ; i++ ){ + char c = value.charAt(i); + if(c > 0xFF )return true; + } + return false; + } + /** * set the length of the footer string * @@ -108,7 +144,9 @@ public class FooterRecord public void setFooter(String footer) { - field_2_footer = footer; + field_3_footer = footer; + field_2_unicode_flag = + (byte) (hasMultibyte(field_3_footer) ? 1 : 0); } /** @@ -132,7 +170,7 @@ public class FooterRecord public String getFooter() { - return field_2_footer; + return field_3_footer; } public String toString() @@ -156,13 +194,23 @@ public class FooterRecord { len+=3; // [Shawn] Fixed for two null bytes in the length } + short bytelen = (short)(isMultibyte() ? + getFooterLength()*2 : getFooterLength() ); LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 2 + offset, - ( short ) ((len - 4) + getFooterLength())); + ( short ) ((len - 4) + bytelen )); if (getFooterLength() > 0) { data[ 4 + offset ] = (byte)getFooterLength(); - StringUtil.putCompressedUnicode(getFooter(), data, 7 + offset); // [Shawn] Place the string in the correct offset + data[ 6 + offset ] = field_2_unicode_flag; + if(isMultibyte()) + { + StringUtil.putUnicodeLE(getFooter(), data, 7 + offset); + } + else + { + StringUtil.putCompressedUnicode(getFooter(), data, 7 + offset); // [Shawn] Place the string in the correct offset + } } return getRecordSize(); } @@ -175,7 +223,8 @@ public class FooterRecord { retval+=3; // [Shawn] Fixed for two null bytes in the length } - return retval + getFooterLength(); + return (isMultibyte() ? + (retval + getFooterLength()*2) : (retval + getFooterLength())); } public short getSid() @@ -186,7 +235,8 @@ public class FooterRecord public Object clone() { FooterRecord rec = new FooterRecord(); rec.field_1_footer_len = field_1_footer_len; - rec.field_2_footer = field_2_footer; + rec.field_2_unicode_flag = field_2_unicode_flag; + rec.field_3_footer = field_3_footer; return rec; } } diff --git a/src/java/org/apache/poi/hssf/record/HeaderRecord.java b/src/java/org/apache/poi/hssf/record/HeaderRecord.java index f5a48ec9fb..9af6297f8b 100644 --- a/src/java/org/apache/poi/hssf/record/HeaderRecord.java +++ b/src/java/org/apache/poi/hssf/record/HeaderRecord.java @@ -36,7 +36,8 @@ public class HeaderRecord { public final static short sid = 0x14; private byte field_1_header_len; - private String field_2_header; + private byte field_2_unicode_flag; + private String field_3_header; public HeaderRecord() { @@ -82,11 +83,46 @@ public class HeaderRecord if (size > 0) { field_1_header_len = data[ 0 + offset ]; - field_2_header = StringUtil.getFromCompressedUnicode(data, 3 + offset, // [Shawn] Changed 1 to 3 for offset of string - LittleEndian.ubyteToInt(field_1_header_len)); + field_2_unicode_flag = data[ 2 + offset ]; + if(isMultibyte()) + { + field_3_header = StringUtil.getFromUnicodeLE( + data,3 + offset,LittleEndian.ubyteToInt(field_1_header_len)); + } + else + { + field_3_header = new String(data, 3 + offset, // [Shawn] Changed 1 to 3 for offset of string + LittleEndian.ubyteToInt( field_1_header_len) ); + } } } + /** + * see the unicode flag + * + * @return boolean flag + * true:footer string has at least one multibyte character + */ + public boolean isMultibyte() { + return ((field_2_unicode_flag & 0xFF) == 1); + } + + /** + * check the parameter has multibyte character + * + * @param value string to check + * @return boolean result + * true:string has at least one multibyte character + */ + private static boolean hasMultibyte(String value){ + if( value == null )return false; + for(int i = 0 ; i < value.length() ; i++ ){ + char c = value.charAt(i); + if(c > 0xFF )return true; + } + return false; + } + /** * set the length of the header string * @@ -108,7 +144,9 @@ public class HeaderRecord public void setHeader(String header) { - field_2_header = header; + field_3_header = header; + field_2_unicode_flag = + (byte) (hasMultibyte(field_3_header) ? 1 : 0); } /** @@ -132,7 +170,7 @@ public class HeaderRecord public String getHeader() { - return field_2_header; + return field_3_header; } public String toString() @@ -156,14 +194,24 @@ public class HeaderRecord { len+=3; // [Shawn] Fixed for two null bytes in the length } + short bytelen = (short)(isMultibyte() ? + getHeaderLength()*2 : getHeaderLength() ); LittleEndian.putShort(data, 0 + offset, sid); LittleEndian.putShort(data, 2 + offset, - ( short ) ((len - 4) + getHeaderLength())); + ( short ) ((len - 4) + bytelen)); if (getHeaderLength() > 0) { data[ 4 + offset ] = (byte)getHeaderLength(); - StringUtil.putCompressedUnicode(getHeader(), data, 7 + offset); // [Shawn] Place the string in the correct offset + data[ 6 + offset ] = field_2_unicode_flag; + if(isMultibyte()) + { + StringUtil.putUnicodeLE(getHeader(), data, 7 + offset); + } + else + { + StringUtil.putCompressedUnicode(getHeader(), data, 7 + offset); // [Shawn] Place the string in the correct offset + } } return getRecordSize(); } @@ -176,8 +224,8 @@ public class HeaderRecord { retval+=3; // [Shawn] Fixed for two null bytes in the length } - retval += getHeaderLength(); - return retval; + return (isMultibyte() ? + (retval + getHeaderLength()*2) : (retval + getHeaderLength())); } public short getSid() @@ -188,7 +236,8 @@ public class HeaderRecord public Object clone() { HeaderRecord rec = new HeaderRecord(); rec.field_1_header_len = field_1_header_len; - rec.field_2_header = field_2_header; + rec.field_2_unicode_flag = field_2_unicode_flag; + rec.field_3_header = field_3_header; return rec; } } diff --git a/src/testcases/org/apache/poi/hssf/data/DBCSHeader.xls b/src/testcases/org/apache/poi/hssf/data/DBCSHeader.xls new file mode 100644 index 0000000000000000000000000000000000000000..d97daf1edbd9c532187777e8149cd96d1925157d GIT binary patch literal 16384 zcmeHOTWnNC82-<8x7{s;Zf{&`IkX79(G)O(0&P(sV5v4m1BRMXx=UKSu%z8`d67jS z;Q~@!Il{Q@FKl$hK z&+VUYE@x)WobSIY8aeyf>?@K&O_C#bVm`@r$PKt>+kU@DIoy=piN#_R&jG`!=>bB( z=S4&2dgSXlm-2?AaJodUh)d47hhd8R3htEMk|(mWJJ37SKWI)0J)?B!HmJizbh1@O zF8Z1az4A27X);S`SFFquWqzvSeyPk=QY`yqrEIPLyJ|UdU_agBYEkiyDYH_U(_k8M zL8bXwNfx7re~b9B18=fxgFMD+8IV5dmXJ(bXob66JTgP1a(-o1eN|OsSIvsfYTMIU zQ{kS6v4|08ix9rGBN%ukIZ`DW>aj$mhQ{Q4;Ad6~#VeJmu~Kr2M_nehvP7hds??gc zW^r$4wGwpJtcVLL7ga*9uIiR9l+qwIc#zbYuGVxWsx^~RG)uiaom`kzgXHp*YK|hC zn-hgTDRpS2M4@*2(Q@s?s^~<@5h+!zeIsTn+cGYil(Qo!`E@(!?sE3obn!FEnQOZE z53}45lhuopjc1*O!_8EAO$K>=26=4;xo?d8xXUg6XikiFQ8ZWC#ZkAiOQLzomZ&JZ zH0p_MQ**^(%s?kS)G}8#^#+5H#gx39?~p8^WZM*nWa&|Hqc0gUY`$7Nr?@avJ18F!r>gm@0A@f6mAeS0h#&df{@~gVZQI+MyOg|E$?KH) zx{^d4B|nbZW6qO<2pM*l%3SDfERc;-=qvLrkZ0v7U#oA1uLv|5#?GZn`9BjY@=cmF}FBsX*&&fj`53} zapfFvyNDqv06P!!I_Gej_kygP)8|y4Au!P1)5;)*AAuTHJB7Vh^J_7C&M%Q!v}M-( zl5{dbuSn=l7uzBo*~Qy-x;T>|W5;g?N1JaAM zDAO|T2@EsQi5_wo9FS?JMnEHQzaVf2CpR9orcKs}llsWvcmKNeLa+bBx4crf@bjPe z{y7ikik0E(!Cb4fgDKkvE(Y%gbK!dg%=hC7@Ko>_a0&P$Fke8wAu->gOdCI3NbC0_ zysfWiAUqh}5i!^9>j{ReNx1Fz8-KQbW3(VVI`7m~+by~8HC=-|{(eHJCXIkbKqH_L z&4rJ}<8NdCUw`Wp?*I8|&IjiHpZoqo zFu&K}%e5Q=bKidy%so5z{oL=L2J?LSeK5}fxc}$5z-6%W9H0vR4Uu3d)VI&vgsuMG z?tvg2p`l1$c-Np=-CkpEj08lTJAXViUzLR<8SM%v!7~8dU5J0BOE{M#oJ*wu5vd3d zBUpjW;eq}^e%2dQ>Ge4RFwvwD&KZZYsy;L1$zMZbjL%}aeKtB8T*mxr73bznX=BZl1=spTe2CY4@kdkS9 zC1I4m1|{?;9fGO_#;4En|4@Hb^?3a!v;EIqIQS0l<=_Vu3oux^{U^Wu3IC7QFjeQc z|7ZSZpU;Mz?*bmP>UTmms7-vFyS@K8PdVTJy3HoOJtn(^Oy7SvC!~J=Sp%6T<(tq- zbf8D|o6srLo$F*$3z%c+Iv5na4TBiEA>`Vi05;dxCT#vQ(;N3Q4%f|HvKoJAtXFG+ z4*Vsx2P==D?8Sdo`>{F*!My=11uHMEzq_zr;|iq@VO%k6msb&|2P+n<9In%u=MW^l zYCV&Pk07N3{}IU)XAN>5#7*81%GfW@!`zAdtva1UMY!Jg!DijgN6NmM3!D3fbxNZk z(hB|}Lw&*2GXO1yu+HNus{x_>qjnE`gV3*AxmqBJpo|cnKK#AgfZBwS*2;$%wWZ`^ OqUK}sK}1biBk(W&iJw6L literal 0 HcmV?d00001 diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java index ca6173ba13..310d2f6e10 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFHeaderFooter.java @@ -24,6 +24,8 @@ import org.apache.poi.hssf.usermodel.HSSFFooter; import org.apache.poi.hssf.usermodel.HSSFSheet; import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -86,5 +88,65 @@ public class TestHSSFHeaderFooter extends TestCase { assertEquals("Bottom Center", foot.getCenter()); assertEquals("Bottom Right", foot.getRight()); } + + /** + * Testcase for Bug 17039 HSSFHeader doesnot support DBCS + */ + public void testHeaderHas16bitCharacter() throws Exception { + HSSFWorkbook b = new HSSFWorkbook(); + HSSFSheet s = b.createSheet("Test"); + HSSFHeader h = s.getHeader(); + h.setLeft("\u0391"); + h.setCenter("\u0392"); + h.setRight("\u0393"); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + b.write(out); + + HSSFWorkbook b2 = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray())); + HSSFHeader h2 = b2.getSheet("Test").getHeader(); + + assertEquals(h2.getLeft(),"\u0391"); + assertEquals(h2.getCenter(),"\u0392"); + assertEquals(h2.getRight(),"\u0393"); + } + + /** + * Testcase for Bug 17039 HSSFFooter doesnot support DBCS + */ + public void testFooterHas16bitCharacter() throws Exception{ + HSSFWorkbook b = new HSSFWorkbook(); + HSSFSheet s = b.createSheet("Test"); + HSSFFooter f = s.getFooter(); + f.setLeft("\u0391"); + f.setCenter("\u0392"); + f.setRight("\u0393"); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + b.write(out); + + HSSFWorkbook b2 = new HSSFWorkbook(new ByteArrayInputStream(out.toByteArray())); + HSSFFooter f2 = b2.getSheet("Test").getFooter(); + + assertEquals(f2.getLeft(),"\u0391"); + assertEquals(f2.getCenter(),"\u0392"); + assertEquals(f2.getRight(),"\u0393"); + } + + public void testReadDBCSHeaderFooter() throws Exception{ + String readFilename = System.getProperty("HSSF.testdata.path"); + FileInputStream in = new FileInputStream(readFilename+File.separator+"DBCSHeader.xls"); + HSSFWorkbook wb = new HSSFWorkbook(in); + HSSFSheet s = wb.getSheetAt(0); + HSSFHeader h = s.getHeader(); + assertEquals("Header Left " ,h.getLeft(),"\u090f\u0915"); + assertEquals("Header Center " ,h.getCenter(),"\u0939\u094b\u0917\u093e"); + assertEquals("Header Right " ,h.getRight(),"\u091c\u093e"); + + HSSFFooter f = s.getFooter(); + assertEquals("Footer Left " ,f.getLeft(),"\u091c\u093e"); + assertEquals("Footer Center " ,f.getCenter(),"\u091c\u093e"); + assertEquals("Footer Right " ,f.getRight(),"\u091c\u093e"); + } }