View | Details | Raw Unified | Return to bug 11010
Collapse All | Expand All

(-)src/java/org/apache/poi/hssf/dev/BiffViewer.java (+3 lines)
Line 627 Link Here
627
            case NameRecord.sid:
628
                retval = new NameRecord( rectype, size, data );
629
                break;
(-)src/java/org/apache/poi/hssf/record/FormatRecord.java (-23 / +39 lines)
Line 76 Link Here
76
    private short             field_3_zero;   // undocumented 2 bytes of 0
76
    private short             field_3_unicode_len;      // unicode string length
77
--
77
    private boolean          field_3_unicode_flag;     // it is not undocumented - it is unicode flag
Lines 121-124 Link Here
121
        field_2_formatstring_len = data[ 2 + offset ];
122
        // field_2_formatstring_len = data[ 2 + offset ];
122
        field_3_zero             = LittleEndian.getShort(data, 3 + offset);
123
        field_3_unicode_len      = LittleEndian.getShort( data, 2 + offset );
123
        field_4_formatstring     = new String(data, 5 + offset,
124
        field_3_unicode_flag     = ( data[ 4 + offset ] & (byte)0x01 ) != 0;
124
                                              LittleEndian.ubyteToInt(field_2_formatstring_len));
125
                                              
125
--
126
                                              
127
      if ( field_3_unicode_flag  ) {
128
          // unicode
129
          field_4_formatstring = StringUtil.getFromUnicodeHigh( data, 5 + offset, field_3_unicode_len );
130
      }
131
      else {
132
          // not unicode
133
          field_4_formatstring = new String(data, 5 + offset, field_3_unicode_len );
134
      }
Line 145 Link Here
145
155
    
146
--
Line 206 Link Here
216
        /*
Lines 209-210 Link Here
209
        buffer.append("    .zero            = ")
220
        */
210
            .append(Integer.toHexString(field_3_zero)).append("\n");
221
        buffer.append("    .unicode length  = ")
211
--
222
            .append(Integer.toHexString(field_3_unicode_len)).append("\n");
223
        buffer.append("    .isUnicode       = ")
224
            .append( field_3_unicode_flag ).append("\n");
Lines 220-223 Link Here
220
        LittleEndian.putShort(data, 2 + offset,
234
        LittleEndian.putShort(data, 2 + offset, (short)( 2 + 2 + 1 + ( (field_3_unicode_flag) 
221
                              ( short ) (5 + getFormatStringLength()));
235
                                                                  ? 2 * field_3_unicode_len 
222
236
                                                                  : field_3_unicode_len ) ) );
223
        // 9 - 4(len/sid) + format string length
237
                                                  // index + len + flag + format string length
224
--
Lines 225-227 Link Here
225
        data[ 6 + offset ] = getFormatStringLength();
239
        LittleEndian.putShort(data, 6 + offset, field_3_unicode_len);
226
        LittleEndian.putShort(data, 7 + offset, ( short ) 0);
240
        data[ 8 + offset ] = (byte)( (field_3_unicode_flag) ? 0x01 : 0x00 );
227
        StringUtil.putCompressedUnicode(getFormatString(), data, 9 + offset);
241
228
--
242
      if ( field_3_unicode_flag ) {
243
          // unicode
244
          StringUtil.putUncompressedUnicode( getFormatString(), data, 9 + offset );
245
      }
246
      else {
247
          // not unicode
248
          StringUtil.putCompressedUnicode( getFormatString(), data, 9 + offset );
249
      }
250
      
Line 233 Link Here
233
        return 9 + getFormatStringLength();
256
        return 9 + ( ( field_3_unicode_flag ) ? 2 * field_3_unicode_len : field_3_unicode_len );
234
--
(-)src/java/org/apache/poi/hssf/record/NameRecord.java (-55 / +185 lines)
Line 58 Link Here
58
import org.apache.poi.util.HexDump;
Line 73 Link Here
74
 * @author  Sergei Kozello (sergeikozello at mail.ru)
Line 91 Link Here
93
    private byte              field_12_builtIn_name;
Line 93 Link Here
93
    private byte[]            field_13_raw_name_definition = null; // raw data
96
    private byte[]            field_13_raw_name_definition;       // raw data
94
--
Line 381 Link Here
381
        LittleEndian.putShort(data, 2 + offset, (short)( 15 + getTextsLength()));
384
        // size defined below
382
--
Lines 393-417 Link Here
393
396
        
394
        StringUtil.putCompressedUnicode(getNameText(), data , 19 + offset);
397
      if ( ( field_1_option_flag & (short)0x20 ) != 0 ) {
395
398
          LittleEndian.putShort(data, 2 + offset, (short)( 16 + field_13_raw_name_definition.length ));
396
        int start_of_name_definition    = 19  + field_3_length_name_text;
399
          
397
        if (this.field_13_name_definition != null) {
400
            data [19 + offset] =  field_12_builtIn_name;
398
            serializePtgs(data, start_of_name_definition + offset);
401
            System.arraycopy( field_13_raw_name_definition, 0, data, 20 + offset, field_13_raw_name_definition.length );
399
        } else {
402
            
400
            System.arraycopy(field_13_raw_name_definition,0,data
403
            return 20 + field_13_raw_name_definition.length;
401
            ,start_of_name_definition + offset,field_13_raw_name_definition.length);
404
      }
402
        }
405
      else {
403
406
          LittleEndian.putShort(data, 2 + offset, (short)( 15 + getTextsLength()));
404
        int start_of_custom_menu_text   = start_of_name_definition + field_4_length_name_definition;
407
          
405
        StringUtil.putCompressedUnicode(getCustomMenuText(), data , start_of_custom_menu_text + offset);
408
          
406
409
            StringUtil.putCompressedUnicode(getNameText(), data , 19 + offset);
407
        int start_of_description_text   = start_of_custom_menu_text + field_8_length_description_text;
410
    
408
        StringUtil.putCompressedUnicode(getDescriptionText(), data , start_of_description_text + offset);
411
            int start_of_name_definition    = 19  + field_3_length_name_text;
409
412
            if (this.field_13_name_definition != null) {
410
        int start_of_help_topic_text    = start_of_description_text + field_9_length_help_topic_text;
413
                serializePtgs(data, start_of_name_definition + offset);
411
        StringUtil.putCompressedUnicode(getHelpTopicText(), data , start_of_help_topic_text + offset);
414
            } else {
412
415
                System.arraycopy(field_13_raw_name_definition,0,data
413
        int start_of_status_bar_text       = start_of_help_topic_text + field_10_length_status_bar_text;
416
                ,start_of_name_definition + offset,field_13_raw_name_definition.length);
414
        StringUtil.putCompressedUnicode(getStatusBarText(), data , start_of_status_bar_text + offset);
417
            }
415
418
    
416
419
            int start_of_custom_menu_text   = start_of_name_definition + field_4_length_name_definition;
417
        return getRecordSize();
420
            StringUtil.putCompressedUnicode(getCustomMenuText(), data , start_of_custom_menu_text + offset);
418
--
421
    
422
            int start_of_description_text   = start_of_custom_menu_text + field_8_length_description_text;
423
            StringUtil.putCompressedUnicode(getDescriptionText(), data , start_of_description_text + offset);
424
    
425
            int start_of_help_topic_text    = start_of_description_text + field_9_length_help_topic_text;
426
            StringUtil.putCompressedUnicode(getHelpTopicText(), data , start_of_help_topic_text + offset);
427
    
428
            int start_of_status_bar_text       = start_of_help_topic_text + field_10_length_status_bar_text;
429
            StringUtil.putCompressedUnicode(getStatusBarText(), data , start_of_status_bar_text + offset);
430
            
431
          return getRecordSize();
432
      }
Lines 582-605 Link Here
582
        field_11_compressed_unicode_flag= data [14 + offset];
597
        
583
        field_12_name_text = new String(data, 15 + offset,
598
        if ( ( field_1_option_flag & (short)0x20 ) != 0 ) {
584
        LittleEndian.ubyteToInt(field_3_length_name_text));
599
            // DEBUG
585
600
            // System.out.println( "Built-in name" );
586
        int start_of_name_definition    = 15 + field_3_length_name_text;
601
            
587
        field_13_name_definition = getParsedExpressionTokens(data, field_4_length_name_definition,
602
            field_11_compressed_unicode_flag = data[ 14 + offset ];
588
        offset, start_of_name_definition);
603
            field_12_builtIn_name = data[ 15 + offset ];
589
604
590
        int start_of_custom_menu_text   = start_of_name_definition + field_4_length_name_definition;
605
            if ( (field_12_builtIn_name & (short)0x07) != 0 ) {
591
        field_14_custom_menu_text       = new String(data, start_of_custom_menu_text + offset,
606
                field_12_name_text = "Print_Titles";
592
        LittleEndian.ubyteToInt(field_7_length_custom_menu));
607
                
593
608
                // DEBUG
594
        int start_of_description_text   = start_of_custom_menu_text + field_8_length_description_text;
609
                // System.out.println( field_12_name_text );
595
        field_15_description_text       = new String(data, start_of_description_text + offset,
610
                
596
        LittleEndian.ubyteToInt(field_8_length_description_text));
611
                field_13_raw_name_definition = new byte[ field_4_length_name_definition ];
597
612
                System.arraycopy( data, 16 + offset, field_13_raw_name_definition, 0, field_13_raw_name_definition.length );
598
        int start_of_help_topic_text    = start_of_description_text + field_9_length_help_topic_text;
613
                
599
        field_16_help_topic_text        = new String(data, start_of_help_topic_text + offset,
614
                // DEBUG
600
        LittleEndian.ubyteToInt(field_9_length_help_topic_text));
615
                // System.out.println( HexDump.toHex( field_13_raw_name_definition ) );
601
616
            }
602
        int start_of_status_bar_text       = start_of_help_topic_text + field_10_length_status_bar_text;
617
        }
603
        field_17_status_bar_text        = new String(data, start_of_status_bar_text +  offset,
618
        else {
604
        LittleEndian.ubyteToInt(field_10_length_status_bar_text));
619
    
605
620
            field_11_compressed_unicode_flag= data [14 + offset];
606
--
621
            field_12_name_text = new String(data, 15 + offset,
622
            LittleEndian.ubyteToInt(field_3_length_name_text));
623
        
624
            int start_of_name_definition    = 15 + field_3_length_name_text;
625
            field_13_name_definition = getParsedExpressionTokens(data, field_4_length_name_definition,
626
            offset, start_of_name_definition);
627
    
628
            int start_of_custom_menu_text   = start_of_name_definition + field_4_length_name_definition;
629
            field_14_custom_menu_text       = new String(data, start_of_custom_menu_text + offset,
630
            LittleEndian.ubyteToInt(field_7_length_custom_menu));
631
    
632
            int start_of_description_text   = start_of_custom_menu_text + field_8_length_description_text;
633
            field_15_description_text       = new String(data, start_of_description_text + offset,
634
            LittleEndian.ubyteToInt(field_8_length_description_text));
635
    
636
            int start_of_help_topic_text    = start_of_description_text + field_9_length_help_topic_text;
637
            field_16_help_topic_text        = new String(data, start_of_help_topic_text + offset,
638
            LittleEndian.ubyteToInt(field_9_length_help_topic_text));
639
    
640
            int start_of_status_bar_text       = start_of_help_topic_text + field_10_length_status_bar_text;
641
            field_17_status_bar_text        = new String(data, start_of_status_bar_text +  offset,
642
            LittleEndian.ubyteToInt(field_10_length_status_bar_text));
643
        }
Line 637 Link Here
675
    }
676
    /*
677
      20 00 
678
      00 
679
      01 
680
      1A 00 // sz = 0x1A = 26
681
      00 00 
682
      01 00 
683
      00 
684
      00 
685
      00 
686
      00 
687
      00 // unicode flag
688
      07 // name
689
      
690
      29 17 00 3B 00 00 00 00 FF FF 00 00 02 00 3B 00 //{ 26
691
      00 07 00 07 00 00 00 FF 00 10                   //  }
692
      
693
      
694
      
695
      20 00 
696
      00 
697
      01 
698
      0B 00 // sz = 0xB = 11
699
      00 00 
700
      01 00 
701
      00 
702
      00 
703
      00 
704
      00 
705
      00 // unicode flag
706
      07 // name
707
      
708
      3B 00 00 07 00 07 00 00 00 FF 00   // { 11 }
709
  */
710
    /*
711
      18, 00, 
712
      1B, 00, 
713
      
714
      20, 00, 
715
      00, 
716
      01, 
717
      0B, 00, 
718
      00, 
719
      00, 
720
      00, 
721
      00, 
722
      00, 
723
      07, 
724
      3B 00 00 07 00 07 00 00 00 FF 00 ]     
725
     */
726
727
    /**
728
     * @see Object#toString()
729
     */
730
    public String toString() {
731
        StringBuffer buffer = new StringBuffer();
732
733
        buffer.append("[NAME]\n");
734
        buffer.append("    .option flags         = ").append( HexDump.toHex( field_1_option_flag ) )
735
            .append("\n");
736
        buffer.append("    .keyboard shortcut    = ").append( HexDump.toHex( field_2_keyboard_shortcut ) )
737
            .append("\n");
738
        buffer.append("    .length of the name   = ").append( field_3_length_name_text )
739
            .append("\n");
740
        buffer.append("    .size of the formula data = ").append( field_4_length_name_definition )
741
            .append("\n");
742
        buffer.append("    .unused                 = ").append( field_5_index_to_sheet )
743
            .append("\n");
744
        buffer.append("    .( 0 = Global name, otherwise index to sheet (one-based) ) = ").append( field_6_equals_to_index_to_sheet )
745
            .append("\n");
746
        buffer.append("    .Length of menu text (character count)        = ").append( field_7_length_custom_menu )
747
            .append("\n");
748
        buffer.append("    .Length of description text (character count) = ").append( field_8_length_description_text )
749
            .append("\n");
750
        buffer.append("    .Length of help topic text (character count)  = ").append( field_9_length_help_topic_text )
751
            .append("\n");
752
        buffer.append("    .Length of status bar text (character count)  = ").append( field_10_length_status_bar_text )
753
            .append("\n");
754
        buffer.append("    .Name (Unicode flag)  = ").append( field_11_compressed_unicode_flag )
755
            .append("\n");
756
        buffer.append("    .Name (Unicode text)  = ").append( field_12_name_text )
757
            .append("\n");
758
        buffer.append("    .Formula data (RPN token array without size field)      = ").append( HexDump.toHex( field_13_raw_name_definition ) )
759
            .append("\n");
760
        buffer.append("    .Menu text (Unicode string without length field)        = ").append( field_14_custom_menu_text )
761
            .append("\n");
762
        buffer.append("    .Description text (Unicode string without length field) = ").append( field_15_description_text )
763
            .append("\n");
764
        buffer.append("    .Help topic text (Unicode string without length field)  = ").append( field_16_help_topic_text )
765
            .append("\n");
766
        buffer.append("    .Status bar text (Unicode string without length field)  = ").append( field_17_status_bar_text )
767
            .append("\n");
768
        buffer.append("[/NAME]\n");
769
        
770
        return buffer.toString();
(-)src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java (+18 lines)
Line 188 Link Here
188
                
189
                //
190
                // for some reasons we have to make the workbook to be at least 4096 bytes
191
                // but if we have such workbook we fill the end of it with zeros (many zeros)
192
                //
193
                // it is not good:
194
                // if the length( all zero records ) % 4 = 1
195
                // e.g.: any zero record would be readed as  4 bytes at once ( 2 - id and 2 - size ).
196
                // And the last 1 byte will be readed WRONG ( the id must be 2 bytes )
197
                //
198
                // So we should better to check if the sid is zero and not to read more data
199
                // The zero sid shows us that rest of the stream data is a fake to make workbook 
200
                // certain size
201
                //
202
                if ( sid == 0 )
203
                    break;
204
205
(-)src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java (-2 / +20 lines)
Line 205 Link Here
205
    public final static byte ENCODING_COMPRESSED_UNICODE = 0;
206
    public final static byte ENCODING_UTF_16             = 1;
207
    
Line 213 Link Here
216
        workbook.setSheetName( sheet, name, ENCODING_COMPRESSED_UNICODE );
217
    }
218
219
    public void setSheetName( int sheet, String name, short encoding )
220
    {
Line 217 Link Here
217
        workbook.setSheetName(sheet, name);
225
        
218
--
226
        switch ( encoding ) {
227
        case ENCODING_COMPRESSED_UNICODE:
228
        case ENCODING_UTF_16:
229
            break;
230
            
231
        default:
232
            // TODO java.io.UnsupportedEncodingException
233
            throw new RuntimeException( "Unsupported encoding" );
234
        }
235
        
236
        workbook.setSheetName( sheet, name, encoding );
(-)src/java/org/apache/poi/util/StringUtil.java (-20 / +41 lines)
Line 65 Link Here
65
 * 
66
 * Now it is quite confusing: the method pairs, in which
67
 * one of them write data and other read written data are:
68
 * putUncompressedUnicodeHigh and getFromUnicode
69
 * putUncompressedUnicode     and getFromUnicodeHigh
Line 67 Link Here
72
 *@author     Sergei Kozello (sergeikozello at mail.ru)
Line 82 Link Here
88
     * { 0x16, 0x00 } -> 0x16
89
     * 
Lines 106-112 Link Here
106
        byte[] bstring = new byte[len];
114
        
107
        int index = offset;
115
        char[] chars = new char[ len ];
108
        // start with high bits.
116
        for ( int i = 0; i < chars.length; i++ ) {
109
117
            chars[i] = (char)( string[ offset + ( 2*i ) ] + 
110
        for (int k = 0; k < len; k++) {
118
                             ( string[ offset + ( 2*i+1 ) ] << 8 ) );
111
            bstring[k] = string[index];
112
            index += 2;
113
--
Line 114 Link Here
114
        return new String(bstring);
120
115
--
121
        return new String( chars );
Line 118 Link Here
125
    /**
126
     *  given a byte array of 16-bit unicode characters, compress to 8-bit and
127
     *  return a string
128
     * 
129
     * { 0x16, 0x00 } -> 0x16
130
     *
131
     *@param  string  the byte array to be converted
132
     *@return         the converted string
133
     */
134
135
    public static String getFromUnicodeHigh( final byte[] string ) {
136
        return getFromUnicodeHigh( string, 0, string.length / 2 );
137
    }
138
Line 122 Link Here
143
     * 
144
     * { 0x00, 0x16 } -> 0x16
Lines 147-153 Link Here
147
        byte[] bstring = new byte[len];
170
148
        int index = offset + 1;
171
        
149
        // start with low bits.
172
        char[] chars = new char[ len ];
150
173
        for ( int i = 0; i < chars.length; i++ ) {
151
        for (int k = 0; k < len; k++) {
174
            chars[i] = (char)( ( string[ offset + ( 2*i ) ] << 8 ) +
152
            bstring[k] = string[index];
175
                              string[ offset + ( 2*i+1 ) ] );
153
            index += 2;
154
--
Line 155 Link Here
155
        return new String(bstring);
177
        
156
--
178
        return new String( chars );
Line 162 Link Here
185
     * 
186
     * { 0x00, 0x16 } -> 0x16
(-)src/testcases/org/apache/poi/util/TestStringUtil.java (+43 lines)
Line 67 Link Here
67
 * @author  Sergei Kozello (sergeikozello at mail.ru)
Line 100 Link Here
101
    }
102
103
    /**
104
     * test simple form of getFromUnicode with symbols with code below and more 127
105
     */
106
107
    public void testGetFromUnicodeSymbolsWithCodesMoreThan127()
108
    {
109
        byte[] test_data = new byte[] {   0x04, 0x22,
110
                                          0x04, 0x35,
111
                                          0x04, 0x41,
112
                                          0x04, 0x42,
113
                                          0x00, 0x20,
114
                                          0x00, 0x74,
115
                                          0x00, 0x65,
116
                                          0x00, 0x73,
117
                                          0x00, 0x74,
118
                                          };
119
120
        assertEquals("\u0422\u0435\u0441\u0442 test",
121
                     StringUtil.getFromUnicode(test_data));
122
    }
123
124
    /**
125
     * test getFromUnicodeHigh for symbols with code below and more 127
126
     */
127
128
    public void testGetFromUnicodeHighSymbolsWithCodesMoreThan127()
129
    {
130
        byte[] test_data = new byte[] {   0x22, 0x04,
131
                                          0x35, 0x04,
132
                                          0x41, 0x04,
133
                                          0x42, 0x04,
134
                                          0x20, 0x00,
135
                                          0x74, 0x00,
136
                                          0x65, 0x00,
137
                                          0x73, 0x00,
138
                                          0x74, 0x00,
139
                                          };
140
141
        assertEquals("\u0422\u0435\u0441\u0442 test",
142
                     StringUtil.getFromUnicodeHigh( test_data ) );

Return to bug 11010