merge the formfield patch from ooo-build
[ooovba.git] / lotuswordpro / source / filter / explode.cxx
blob5f5162aec73ca65261e5aa6beb06c3180c0f90e7
1 /*************************************************************************
3 * The Contents of this file are made available subject to the terms of
4 * either of the following licenses
6 * - GNU Lesser General Public License Version 2.1
7 * - Sun Industry Standards Source License Version 1.1
9 * Sun Microsystems Inc., October, 2000
11 * GNU Lesser General Public License Version 2.1
12 * =============================================
13 * Copyright 2000 by Sun Microsystems, Inc.
14 * 901 San Antonio Road, Palo Alto, CA 94303, USA
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License version 2.1, as published by the Free Software Foundation.
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
28 * MA 02111-1307 USA
31 * Sun Industry Standards Source License Version 1.1
32 * =================================================
33 * The contents of this file are subject to the Sun Industry Standards
34 * Source License Version 1.1 (the "License"); You may not use this file
35 * except in compliance with the License. You may obtain a copy of the
36 * License at http://www.openoffice.org/license.html.
38 * Software provided under this License is provided on an "AS IS" basis,
39 * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
40 * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
41 * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
42 * See the License for the specific provisions governing your rights and
43 * obligations concerning the Software.
45 * The Initial Developer of the Original Code is: IBM Corporation
47 * Copyright: 2008 by IBM Corporation
49 * All Rights Reserved.
51 * Contributor(s): _______________________________________
54 ************************************************************************/
55 #include <assert.h>
56 #include "explode.hxx"
57 #include <math.h>
58 const static char Tree1String[][32] = {
59 "101",
60 "11",
61 "100",
62 "011",
63 "0101",
64 "0100",
65 "0011",
66 "00101",
67 "00100",
68 "00011",
69 "00010",
70 "000011",
71 "000010",
72 "000001",
73 "0000001",
74 "0000000",
77 const static char Tree2String[][32] = {
78 "11" ,
79 "1011" ,
80 "1010" ,
81 "10011" ,
82 "10010" ,
83 "10001" ,
84 "10000" ,
85 "011111" ,
86 "011110" ,
87 "011101" ,
88 "011100" ,
89 "011011" ,
90 "011010" ,
91 "011001" ,
92 "011000" ,
93 "010111" ,
94 "010110" ,
95 "010101" ,
96 "010100" ,
97 "010011" ,
98 "010010" ,
99 "010001" ,
100 "0100001" ,
101 "0100000" ,
102 "0011111" ,
103 "0011110" ,
104 "0011101" ,
105 "0011100" ,
106 "0011011" ,
107 "0011010" ,
108 "0011001" ,
109 "0011000" ,
110 "0010111" ,
111 "0010110" ,
112 "0010101" ,
113 "0010100" ,
114 "0010011" ,
115 "0010010" ,
116 "0010001" ,
117 "0010000" ,
118 "0001111" ,
119 "0001110" ,
120 "0001101" ,
121 "0001100" ,
122 "0001011" ,
123 "0001010" ,
124 "0001001" ,
125 "0001000" ,
126 "00001111",
127 "00001110",
128 "00001101",
129 "00001100",
130 "00001011",
131 "00001010",
132 "00001001",
133 "00001000",
134 "00000111",
135 "00000110",
136 "00000101",
137 "00000100",
138 "00000011",
139 "00000010",
140 "00000001",
141 "00000000",
144 Decompression::Decompression(SvStream * pInStream, SvStream * pOutStream):
145 m_pInStream(pInStream), m_pOutStream(pOutStream), m_pBuffer(m_Buffer), m_nOutputBufferPos(0),
146 m_nBitsLeft(0), m_nBytesLeft(0), m_nCurrent4Byte(0)
148 if (!m_pInStream || !m_pOutStream )
150 assert(sal_False);
152 ConstructTree1();
153 ConstructTree2();
154 fillArray();
157 * @descr read specified bits from input stream
158 * @argument iCount - number of bits to be read, less than 31
159 * @argument nBits - bits read
160 * @return 0 - read OK, otherwise error
162 sal_uInt32 Decompression::ReadBits(sal_uInt16 iCount, sal_uInt32 & nBits)
164 if ( (iCount == 0) || (iCount > 32 ) )
166 return 1;
169 sal_uInt32 val = 0; /* bit accumulator */
171 /* load at least need bits into val */
172 val = m_nCurrent4Byte;
173 while (m_nBitsLeft < iCount)
175 if (m_nBytesLeft == 0)
177 m_nBytesLeft = m_pInStream->Read(m_Buffer, CHUNK);
178 m_pBuffer = m_Buffer;
179 if (m_nBytesLeft == 0) return 1;
181 val |= (sal_uInt32)(*m_pBuffer++) << m_nBitsLeft; /* load eight bits */
182 m_nBytesLeft --;
183 m_nBitsLeft += 8;
186 /* drop need bits and update buffer, always zero to seven bits left */
187 m_nCurrent4Byte = val >> iCount;
188 m_nBitsLeft -= iCount;
190 /* return need bits, zeroing the bits above that */
191 nBits = val & ((1 << iCount) - 1);
193 return 0;
196 * @descr decompress input and write output
197 * @return 0 - read OK, otherwise error
199 sal_Int32 Decompression::explode()
201 /* The first 2 bytes are parameters */
202 sal_uInt32 P1;
203 if (0 != ReadBits(8, P1))/* 0 or 1 */
204 return -1;
206 /* I think this means 0=binary and 1=ascii file, but in RESOURCEs I saw always 0 */
207 if (P1 >= 1) // changed per 's review comments
208 return -1;
210 sal_uInt32 P2;
211 if (0 != ReadBits(8, P2))
212 return -1;
214 /* must be 4,5 or 6 and it is a parameter for the decompression algorithm */
215 if (P2 < 4 || P2 > 6)
216 return -2;
218 m_nOutputBufferPos = 0;
219 /* Now, a bit stream follows, which is decoded as described below: */
220 /* The algorithm terminates as soon as it runs out of bits. */
221 while(sal_True)
223 // read 1 bit (take bits from the lowest value (LSB) to the MSB i.e. bit 0, bit 1 etc ...)
224 sal_uInt32 iBit;
225 if (0 != ReadBits(1, iBit))
226 break;
227 if ( 0 == (iBit & 0x01) )
229 //if the bit is 0 read 8 bits and write it to the output as it is.
230 sal_uInt32 symbol;
231 if (0 != ReadBits(8, symbol))
232 break;
233 m_Output[m_nOutputBufferPos++] = (sal_uInt8)symbol;
234 if (m_nOutputBufferPos == MAXWIN)
236 m_pOutStream->Write(m_Output, m_nOutputBufferPos);
237 m_nOutputBufferPos = 0;
239 continue;
241 // if the bit is 1 we have here a length/distance pair:
242 // -decode a number with Hufmman Tree #1; variable bit length, result is 0x00 .. 0x0F -> L1
243 sal_uInt32 L1 = Decode(m_Tree1);
244 sal_uInt32 Length;
245 if (L1 <= 7)
247 //if L1 <= 7:
248 // LENGTH = L1 + 2
249 Length = L1 + 2;
251 else
253 // if L1 > 7
254 // read more (L1-7) bits -> L2
255 // LENGTH = L2 + M[L1-7] + 2
256 sal_uInt32 L2;
257 if (0 != ReadBits((sal_uInt16)(L1 - 7), L2))
258 break;
259 Length = L2 + 2 + m_iArrayOfM[L1 -7];
261 if (Length == 519)
263 // end of compressed data
264 break;
267 // - decode another number with Hufmann Tree #2 giving result 0x00..0x3F -> D1
268 sal_uInt32 D1 = Decode(m_Tree2);
269 sal_uInt32 D2;
270 if (Length == 2)
272 // if LENGTH == 2
273 // D1 = D1 << 2
274 // read 2 bits -> D2
275 D1 = D1 << 2;
276 if (0 != ReadBits(2, D2))
277 break;
279 else
281 // else
282 // D1 = D1 << P2 // the parameter 2
283 // read P2 bits -> D2
284 D1 = D1 << P2;
285 if (0 != ReadBits((sal_uInt16)P2, D2))
286 break;
288 // DISTANCE = (D1 | D2) + 1
289 sal_uInt32 distance = (D1 | D2) + 1;
291 // - now copy LENGTH bytes from (output_ptr-DISTANCE) to output_ptr
292 // write current buffer to output
293 m_pOutStream->Write(m_Output, m_nOutputBufferPos);
294 m_nOutputBufferPos = 0;
296 // remember current position
297 sal_uInt32 nOutputPos = m_pOutStream->Tell();
298 if (distance > nOutputPos)
299 return -3; // format error
301 m_pOutStream->Flush();
302 // point back to copy position and read bytes
303 m_pOutStream->SeekRel((long)-distance);
304 sal_uInt8 sTemp[MAXWIN];
305 sal_uInt32 nRead = distance > Length? Length:distance;
306 m_pOutStream->Read(sTemp, nRead);
307 if (nRead != Length)
309 // fill the buffer with read content repeatly until full
310 for (sal_uInt32 i=nRead; i<Length; i++)
312 sTemp[i] = sTemp[i-nRead];
316 // restore output stream position
317 m_pOutStream->Seek(nOutputPos);
319 // write current buffer to output
320 m_pOutStream->Write(sTemp, Length);
322 return 0;
325 * @descr bits to string
326 * @return
328 void Decompression::ToString(sal_uInt32 nBits, sal_Char *pChar, sal_uInt32 nLen)
330 sal_uInt32 nBit;
331 for (sal_uInt32 i=nLen; i > 0; i--)
333 nBit = (nBits >> (i -1) ) & 0x01;
334 pChar[nLen - i] = nBit ? '1':'0';
336 pChar[nLen] = '\0';
337 return;
341 * @descr decode tree 1 for length
342 * @return the decoded value
344 sal_uInt32 Decompression::Decode(HuffmanTreeNode * pRoot)
346 sal_uInt32 nRet;
347 sal_uInt32 nRead, nReadAlready;
349 if( 0 != ReadBits(1, nReadAlready))
350 return 0; // something wrong
352 for (sal_uInt16 i=2; i <= 8; i++)
354 if ( 0 != ReadBits(1, nRead))
355 return 0; // something wrong
357 nReadAlready = (nReadAlready << 1) | (nRead & 0x01);
359 sal_Char sCode[16];
360 ToString(nReadAlready, sCode, i);
361 nRet = pRoot->QueryValue(sCode);
362 if (nRet != 0xffffffff)
364 break;
367 return nRet;
370 * @descr construct tree 1 for length
371 * @return
373 void Decompression::ConstructTree1()
374 { // Huffman Tree #1
375 // The first huffman tree (the Section called Decompression algorithm HUFFMAN) contains the length values. It is described by the following table:
376 // value (hex) code (binary)
377 // 0 101
378 // 1 11
379 // 2 100
380 // 3 011
381 // 4 0101
382 // 5 0100
383 // 6 0011
384 // 7 0010 1
385 // 8 0010 0
386 // 9 0001 1
387 // a 0001 0
388 // b 0000 11
389 // c 0000 10
390 // d 0000 01
391 // e 0000 001
392 // f 0000 000
393 m_Tree1 = new HuffmanTreeNode();
394 for (sal_uInt32 i=0; i< 16; i++)
396 m_Tree1->InsertNode(i, Tree1String[i]);
399 m_Tree1->InsertNode(0, "101");
400 m_Tree1->InsertNode(1, "11");
401 m_Tree1->InsertNode(2, "100");
402 m_Tree1->InsertNode(3, "011");
403 m_Tree1->InsertNode(4, "0101");
404 m_Tree1->InsertNode(5, "0100");
405 m_Tree1->InsertNode(6, "0011");
406 m_Tree1->InsertNode(7, "00101");
407 m_Tree1->InsertNode(8, "00100");
408 m_Tree1->InsertNode(9, "00011");
409 m_Tree1->InsertNode(10, "00010");
410 m_Tree1->InsertNode(11, "000011");
411 m_Tree1->InsertNode(12, "000010");
412 m_Tree1->InsertNode(13, "000001");
413 m_Tree1->InsertNode(14, "0000001");
414 m_Tree1->InsertNode(15, "0000000");
418 * @descr construct tree 2 for distance
419 * @return
421 void Decompression::ConstructTree2()
424 m_Tree2 = new HuffmanTreeNode();
425 for (sal_uInt32 i=0; i< 64; i++)
427 m_Tree2->InsertNode(i, Tree2String[i]);
429 #if 0
430 m_Tree2 = new HuffmanTreeNode();
431 //Huffman Tree #2
432 //The second huffman code tree contains the distance values. It can be built from the following table:
433 //value (hex) code (binary)
434 //00 11
435 //01 1011
436 //02 1010
437 //03 1001 1
438 //04 1001 0
439 //05 1000 1
440 //06 1000 0
441 //07 0111 11
442 //08 0111 10
443 //09 0111 01
444 //0a 0111 00
445 //0b 0110 11
446 //0c 0110 10
447 //0d 0110 01
448 //0e 0110 00
449 //0f 0101 11
450 m_Tree2->InsertNode(0x0, "11");
451 m_Tree2->InsertNode(0x1, "1011");
452 m_Tree2->InsertNode(0x2, "1010");
453 m_Tree2->InsertNode(0x3, "10011");
454 m_Tree2->InsertNode(0x4, "10010");
455 m_Tree2->InsertNode(0x5, "10001");
456 m_Tree2->InsertNode(0x6, "10000");
457 m_Tree2->InsertNode(0x7, "011111");
458 m_Tree2->InsertNode(0x8, "011110");
459 m_Tree2->InsertNode(0x9, "011101");
460 m_Tree2->InsertNode(0x0a, "011100");
461 m_Tree2->InsertNode(0x0b, "011011");
462 m_Tree2->InsertNode(0x0c, "011010");
463 m_Tree2->InsertNode(0x0d, "011001");
464 m_Tree2->InsertNode(0x0e, "011000");
465 m_Tree2->InsertNode(0x0f, "010111");
466 //10 0101 10
467 //11 0101 01
468 //12 0101 00
469 //13 0100 11
470 //14 0100 10
471 //15 0100 01
472 //16 0100 001
473 //17 0100 000
474 //18 0011 111
475 //19 0011 110
476 // 1a 0011 101
477 // 1b 0011 100
478 // 1c 0011 011
479 // 1d 0011 010
480 // 1e 0011 001
481 // 1f 0011 000
482 m_Tree2->InsertNode(0x10, "010110");
483 m_Tree2->InsertNode(0x11, "010101");
484 m_Tree2->InsertNode(0x12, "010100");
485 m_Tree2->InsertNode(0x13, "010011");
486 m_Tree2->InsertNode(0x14, "010010");
487 m_Tree2->InsertNode(0x15, "010001");
488 m_Tree2->InsertNode(0x16, "0100001");
489 m_Tree2->InsertNode(0x17, "0100000");
490 m_Tree2->InsertNode(0x18, "0011111");
491 m_Tree2->InsertNode(0x19, "0011110");
492 m_Tree2->InsertNode(0x1a, "0011101");
493 m_Tree2->InsertNode(0x1b, "0011100");
494 m_Tree2->InsertNode(0x1c, "0011011");
495 m_Tree2->InsertNode(0x1d, "0011010");
496 m_Tree2->InsertNode(0x1e, "0011001");
497 m_Tree2->InsertNode(0x1f, "0011000");
498 //20 0010 111
499 //21 0010 110
500 //22 0010 101
501 //23 0010 100
502 //24 0010 011
503 //25 0010 010
504 //26 0010 001
505 //27 0010 000
506 //28 0001 111
507 //29 0001 110
508 // 2a 0001 101
509 // 2b 0001 100
510 // 2c 0001 011
511 // 2d 0001 010
512 // 2e 0001 001
513 // 2f 0001 000
514 m_Tree2->InsertNode(0x20, "0010111");
515 m_Tree2->InsertNode(0x21, "0010110");
516 m_Tree2->InsertNode(0x22, "0010101");
517 m_Tree2->InsertNode(0x23, "0010100");
518 m_Tree2->InsertNode(0x24, "0010011");
519 m_Tree2->InsertNode(0x25, "0010010");
520 m_Tree2->InsertNode(0x26, "0010001");
521 m_Tree2->InsertNode(0x27, "0010000");
522 m_Tree2->InsertNode(0x28, "0001111");
523 m_Tree2->InsertNode(0x29, "0001110");
524 m_Tree2->InsertNode(0x2a, "0001101");
525 m_Tree2->InsertNode(0x2b, "0001100");
526 m_Tree2->InsertNode(0x2c, "0001011");
527 m_Tree2->InsertNode(0x2d, "0001010");
528 m_Tree2->InsertNode(0x2e, "0001001");
529 m_Tree2->InsertNode(0x2f, "0001000");
530 //30 0000 1111
531 //31 0000 1110
532 //32 0000 1101
533 //33 0000 1100
534 //34 0000 1011
535 //35 0000 1010
536 //36 0000 1001
537 //37 0000 1000
538 //38 0000 0111
539 //39 0000 0110
540 // 3a 0000 0101
541 // 3b 0000 0100
542 // 3c 0000 0011
543 // 3d 0000 0010
544 // 3e 0000 0001
545 // 3f 0000 0000
546 m_Tree2->InsertNode(0x30, "00001111");
547 m_Tree2->InsertNode(0x31, "00001110");
548 m_Tree2->InsertNode(0x32, "00001101");
549 m_Tree2->InsertNode(0x33, "00001100");
550 m_Tree2->InsertNode(0x34, "00001011");
551 m_Tree2->InsertNode(0x35, "00001010");
552 m_Tree2->InsertNode(0x36, "00001001");
553 m_Tree2->InsertNode(0x37, "00001000");
554 m_Tree2->InsertNode(0x38, "00000111");
555 m_Tree2->InsertNode(0x39, "00000110");
556 m_Tree2->InsertNode(0x3a, "00000101");
557 m_Tree2->InsertNode(0x3b, "00000100");
558 m_Tree2->InsertNode(0x3c, "00000011");
559 m_Tree2->InsertNode(0x3d, "00000010");
560 m_Tree2->InsertNode(0x3e, "00000001");
561 m_Tree2->InsertNode(0x3f, "00000000");
562 #endif
563 //where bits should be read from the left to the right.
566 * @descr
567 * @return
569 void Decompression::fillArray()
571 m_iArrayOfM[0] = 7;
572 for (int i=1; i < 16; i++)
574 double dR = 2.0;
575 m_iArrayOfM[i] = m_iArrayOfM[i - 1]+ (sal_uInt32)pow(dR, i-1);//2
579 HuffmanTreeNode::HuffmanTreeNode(sal_uInt32 nValue , HuffmanTreeNode * pLeft , HuffmanTreeNode * pRight )
581 value = nValue;
582 left = pLeft;
583 right = pRight;
585 HuffmanTreeNode::~HuffmanTreeNode()
587 if (left)
589 delete left;
590 left = NULL;
592 if (right)
594 delete right;
595 right = NULL;
599 HuffmanTreeNode * HuffmanTreeNode::InsertNode(sal_uInt32 nValue, const sal_Char * pInCode)
601 HuffmanTreeNode *pNew = new HuffmanTreeNode(nValue);
602 sal_Char pCode[32];
603 strcpy(pCode, pInCode );
605 // query its parents
606 sal_Char cLast = pCode[strlen(pCode) - 1];
607 pCode[strlen(pCode) - 1] = '\0';
608 HuffmanTreeNode * pParent = QueryNode(pCode);
609 if (!pParent)
611 pParent = InsertNode(0xffffffff, pCode);
613 if (cLast == '0')
614 pParent->left = pNew;
615 else // (cChar == '1')
616 pParent->right = pNew;
618 return pNew;
620 HuffmanTreeNode * HuffmanTreeNode::QueryNode(const sal_Char * pCode)
622 sal_uInt32 nLen = strlen(pCode);
624 HuffmanTreeNode * pNode = this; // this is the root
625 for(sal_uInt32 i=0; i<nLen && pNode; i++)
627 sal_Char cChar= pCode[i];
628 if (cChar == '0')
630 pNode = pNode->left;
632 else // (cChar == '1')
634 pNode = pNode->right;
637 return pNode;
640 sal_uInt32 HuffmanTreeNode::QueryValue(const sal_Char * pCode)
642 HuffmanTreeNode * pNode =QueryNode(pCode);
643 if (pNode)
644 return pNode->value;
646 return 0xffffffff;