]> source.dussan.org Git - poi.git/commitdiff
Hopefully handle the building and using of RichTextRuns correctly. Should include...
authorNick Burch <nick@apache.org>
Tue, 13 Jun 2006 14:57:34 +0000 (14:57 +0000)
committerNick Burch <nick@apache.org>
Tue, 13 Jun 2006 14:57:34 +0000 (14:57 +0000)
git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@413912 13f79535-47bb-0310-9956-ffa450edef68

src/scratchpad/src/org/apache/poi/hslf/model/TextRun.java
src/scratchpad/src/org/apache/poi/hslf/usermodel/RichTextRun.java

index 8cc4215fb011b2df6bed46c70486dbdd22f25351..a245ea4b9c5327dea1fd892f6de3c62047f4d0a0 100644 (file)
@@ -20,6 +20,7 @@
 package org.apache.poi.hslf.model;
 
 import java.util.LinkedList;
+import java.util.Vector;
 
 import org.apache.poi.hslf.record.*;
 import org.apache.poi.hslf.record.StyleTextPropAtom.TextPropCollection;
@@ -92,51 +93,149 @@ public class TextRun
                        cStyles = _styleAtom.getCharacterStyles();
                }
 
-               _rtRuns = new RichTextRun[cStyles.size()];
-               
                // Handle case of no current style, with a default
-               if(_rtRuns.length == 0) {
+               if(pStyles.size() == 0 || cStyles.size() == 0) { 
                        _rtRuns = new RichTextRun[1];
                        _rtRuns[0] = new RichTextRun(this, 0, runRawText.length());
                } else {
-                       // Build up Rich Text Runs, one for each character style block
-                       // TODO: Handle case of shared character styles
+                       // Build up Rich Text Runs, one for each 
+                       //  character/paragraph style pair
+                       Vector rtrs = new Vector();
+
                        int pos = 0;
                        
                        int curP = 0;
-                       int pLenRemain = ((TextPropCollection)pStyles.get(curP)).getCharactersCovered();
+                       int curC = 0;
+                       int pLenRemain = -1;
+                       int cLenRemain = -1;
                        
-                       // Build one for each character style
-                       for(int i=0; i<_rtRuns.length; i++) {
+                       // Build one for each run with the same style
+                       while(pos <= runRawText.length() && curP < pStyles.size() && curC < cStyles.size()) {
                                // Get the Props to use
                                TextPropCollection pProps = (TextPropCollection)pStyles.get(curP);
-                               TextPropCollection cProps = (TextPropCollection)cStyles.get(i);
+                               TextPropCollection cProps = (TextPropCollection)cStyles.get(curC);
                                
-                               // Get the length to extend over
-                               // (Last run is often 1 char shorter than the cProp claims)
-                               int len = cProps.getCharactersCovered();
-                               if(len+pos > runRawText.length()) {
-                                       len = runRawText.length()-pos;
-                               }
+                               int pLen = pProps.getCharactersCovered();
+                               int cLen = cProps.getCharactersCovered();
+                               
+                               // Handle new pass
+                               boolean freshSet = false;
+                               if(pLenRemain == -1 && cLenRemain == -1) { freshSet = true; }
+                               if(pLenRemain == -1) { pLenRemain = pLen; }
+                               if(cLenRemain == -1) { cLenRemain = cLen; }
                                
-                               // Build the rich text run
-                               // TODO: Tell the RichTextRun if the styles are shared
-                               _rtRuns[i] = new RichTextRun(this, pos, len, pProps, cProps, false, false);
-                               pos += len;
+                               // So we know how to build the eventual run
+                               int runLen = -1;
+                               boolean pShared = false;
+                               boolean cShared = false;
                                
-                               // See if we need to move onto the next paragraph style
-                               pLenRemain -= len;
-                               if(pLenRemain == 0) {
+                               // Same size, new styles - neither shared
+                               if(pLen == cLen && freshSet) {
+                                       runLen = cLen;
+                                       pShared = false;
+                                       cShared = false;
                                        curP++;
-                                       if(curP < pStyles.size()) {
-                                               pLenRemain = ((TextPropCollection)pStyles.get(curP)).getCharactersCovered();
+                                       curC++;
+                                       pLenRemain = -1;
+                                       cLenRemain = -1;
+                               } else {
+                                       // Some sharing
+                                       
+                                       // See if we are already in a shared block
+                                       if(pLenRemain < pLen) {
+                                               // Existing shared p block
+                                               pShared = true;
+                                               
+                                               // Do we end with the c block, or either side of it?
+                                               if(pLenRemain == cLenRemain) {
+                                                       // We end at the same time
+                                                       cShared = false;
+                                                       runLen = pLenRemain;
+                                                       curP++;
+                                                       curC++;
+                                                       pLenRemain = -1;
+                                                       cLenRemain = -1;
+                                               } else if(pLenRemain < cLenRemain) {
+                                                       // We end before the c block
+                                                       cShared = true;
+                                                       runLen = pLenRemain;
+                                                       curP++;
+                                                       cLenRemain -= pLenRemain;
+                                                       pLenRemain = -1;
+                                               } else {
+                                                       // We end after the c block
+                                                       cShared = false;
+                                                       runLen = cLenRemain;
+                                                       curC++;
+                                                       pLenRemain -= cLenRemain;
+                                                       cLenRemain = -1;
+                                               }
+                                       } else if(cLenRemain < cLen) {
+                                               // Existing shared c block
+                                               cShared = true;
+                                               
+                                               // Do we end with the p block, or either side of it?
+                                               if(pLenRemain == cLenRemain) {
+                                                       // We end at the same time
+                                                       pShared = false;
+                                                       runLen = cLenRemain;
+                                                       curP++;
+                                                       curC++;
+                                                       pLenRemain = -1;
+                                                       cLenRemain = -1;
+                                               } else if(cLenRemain < pLenRemain) {
+                                                       // We end before the p block
+                                                       pShared = true;
+                                                       runLen = cLenRemain;
+                                                       curC++;
+                                                       pLenRemain -= cLenRemain;
+                                                       cLenRemain = -1;
+                                               } else {
+                                                       // We end after the p block
+                                                       pShared = false;
+                                                       runLen = pLenRemain;
+                                                       curP++;
+                                                       cLenRemain -= pLenRemain;
+                                                       pLenRemain = -1;
+                                               }
+                                       } else {
+                                               // Start of a shared block
+                                               if(pLenRemain < cLenRemain) {
+                                                       // Shared c block
+                                                       pShared = false;
+                                                       cShared = true;
+                                                       runLen = pLenRemain;
+                                                       curP++;
+                                                       cLenRemain -= pLenRemain;
+                                                       pLenRemain = -1;
+                                               } else {
+                                                       // Shared p block
+                                                       pShared = true;
+                                                       cShared = false;
+                                                       runLen = cLenRemain;
+                                                       curC++;
+                                                       pLenRemain -= cLenRemain;
+                                                       cLenRemain = -1;
+                                               }
                                        }
                                }
-                               if(pLenRemain < 0) {
-                                       System.err.println("Paragraph style ran out before character style did! Short by " + (0-pLenRemain) + " characters.");
-                                       System.err.println("Calling RichTextRun functions is likely to break things - see Bug #38544");
+                               
+                               // Wind on
+                               int prevPos = pos;
+                               pos += runLen;
+                               // Adjust for end-of-run extra 1 length
+                               if(pos > runRawText.length()) {
+                                       runLen--; 
                                }
+                               
+                               // Save
+                               RichTextRun rtr = new RichTextRun(this, prevPos, runLen, pProps, cProps, pShared, cShared);
+                               rtrs.add(rtr);
                        }
+                       
+                       // Build the array
+                       _rtRuns = new RichTextRun[rtrs.size()];
+                       rtrs.copyInto(_rtRuns);
                }
        }
        
@@ -212,21 +311,31 @@ public class TextRun
                ensureStyleAtomPresent();
                
                // Update the text length for its Paragraph and Character stylings
+               // If it's shared:
+               //   * calculate the new length based on the run's old text
+               //   * this should leave in any +1's for the end of block if needed
+               // If it isn't shared:
+               //   * reset the length, to the new string's length
+               //   * add on +1 if the last block
+               // The last run needs its stylings to be 1 longer than the raw
+               //  text is. This is to define the stylings that any new text
+               //  that is added will inherit
                TextPropCollection pCol = run._getRawParagraphStyle();
                TextPropCollection cCol = run._getRawCharacterStyle();
-               // Character style covers the new run
-               cCol.updateTextSize(s.length());
-               // Paragraph might cover other runs to, so remove old size and add new one
-               pCol.updateTextSize( pCol.getCharactersCovered() - run.getLength() + s.length());
-               
-               // If we were dealing with the last RichTextRun in the set, then
-               //  we need to tell the Character TextPropCollections a size 1 bigger 
-               //  than it really is
-               // (The Paragraph one will keep the extra 1 length from before)
-               // This extra style length is used to indicate that new text in
-               //  the paragraph should go into this set of styling
+               int newSize = s.length();
                if(runID == _rtRuns.length-1) {
-                       cCol.updateTextSize( cCol.getCharactersCovered() + 1 );
+                       newSize++;
+               }
+               
+               if(run._isParagraphStyleShared()) {
+                       pCol.updateTextSize( pCol.getCharactersCovered() - run.getLength() + s.length() );
+               } else {
+                       pCol.updateTextSize(newSize);
+               }
+               if(run._isCharacterStyleShared()) {
+                       cCol.updateTextSize( cCol.getCharactersCovered() - run.getLength() + s.length() );
+               } else {
+                       cCol.updateTextSize(newSize);
                }
                
                // Build up the new text
index 763c3a17d482eb12ec32588550284f7e9b2d7570..5f4cd2422fdbc5643f1c81035fb2e52b30de6690 100644 (file)
@@ -82,6 +82,8 @@ public class RichTextRun
                length = len;
                paragraphStyle = pStyle;
                characterStyle = cStyle;
+               sharingParagraphStyle = pShared;
+               sharingCharacterStyle = cShared;
        }
 
        /**