| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.hwpf.usermodel; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.logging.log4j.LogManager; |
| import org.apache.logging.log4j.Logger; |
| import org.apache.poi.hwpf.sprm.SprmBuffer; |
| import org.apache.poi.hwpf.sprm.TableSprmUncompressor; |
| |
| import static org.apache.logging.log4j.util.Unbox.box; |
| |
| public final class TableRow extends Range |
| { |
| private static final Logger LOG = LogManager.getLogger(TableRow.class); |
| |
| private static final short SPRM_DXAGAPHALF = (short) 0x9602; |
| private static final short SPRM_DYAROWHEIGHT = (short) 0x9407; |
| private static final short SPRM_FCANTSPLIT = 0x3403; |
| private static final short SPRM_FTABLEHEADER = 0x3404; |
| private static final short SPRM_TJC = 0x5400; |
| |
| private static final char TABLE_CELL_MARK = '\u0007'; |
| |
| private TableCell[] _cells; |
| private boolean _cellsFound; |
| |
| int _levelNum; |
| private SprmBuffer _papx; |
| private TableProperties _tprops; |
| |
| public TableRow( int startIdxInclusive, int endIdxExclusive, Table parent, |
| int levelNum ) |
| { |
| super( startIdxInclusive, endIdxExclusive, parent ); |
| |
| Paragraph last = getParagraph( numParagraphs() - 1 ); |
| _papx = last._papx; |
| _tprops = TableSprmUncompressor.uncompressTAP( _papx ); |
| _levelNum = levelNum; |
| initCells(); |
| } |
| |
| public boolean cantSplit() |
| { |
| return _tprops.getFCantSplit(); |
| } |
| |
| public BorderCode getBarBorder() |
| { |
| throw new UnsupportedOperationException( "not applicable for TableRow" ); |
| } |
| |
| public BorderCode getBottomBorder() |
| { |
| return _tprops.getBrcBottom(); |
| } |
| |
| public TableCell getCell( int index ) |
| { |
| initCells(); |
| return _cells[index]; |
| } |
| |
| public int getGapHalf() |
| { |
| return _tprops.getDxaGapHalf(); |
| } |
| |
| public BorderCode getHorizontalBorder() |
| { |
| return _tprops.getBrcHorizontal(); |
| } |
| |
| public BorderCode getLeftBorder() |
| { |
| return _tprops.getBrcLeft(); |
| } |
| |
| public BorderCode getRightBorder() |
| { |
| return _tprops.getBrcRight(); |
| } |
| |
| public int getRowHeight() |
| { |
| return _tprops.getDyaRowHeight(); |
| } |
| |
| public int getRowJustification() |
| { |
| return _tprops.getJc(); |
| } |
| |
| public BorderCode getTopBorder() |
| { |
| return _tprops.getBrcTop(); |
| } |
| |
| public BorderCode getVerticalBorder() |
| { |
| return _tprops.getBrcVertical(); |
| } |
| |
| private void initCells() |
| { |
| if ( _cellsFound ) |
| return; |
| |
| final short expectedCellsCount = _tprops.getItcMac(); |
| |
| int lastCellStart = 0; |
| List<TableCell> cells = new ArrayList<>( |
| expectedCellsCount + 1); |
| for ( int p = 0; p < numParagraphs(); p++ ) |
| { |
| Paragraph paragraph = getParagraph( p ); |
| String s = paragraph.text(); |
| |
| if ( ( ( s.length() > 0 && s.charAt( s.length() - 1 ) == TABLE_CELL_MARK ) || paragraph |
| .isEmbeddedCellMark() ) |
| && paragraph.getTableLevel() == _levelNum ) |
| { |
| TableCellDescriptor tableCellDescriptor = _tprops.getRgtc() != null |
| && _tprops.getRgtc().length > cells.size() ? _tprops |
| .getRgtc()[cells.size()] : new TableCellDescriptor(); |
| final short leftEdge = _tprops.getRgdxaCenter() != null |
| && _tprops.getRgdxaCenter().length > cells.size() ? _tprops |
| .getRgdxaCenter()[cells.size()] : 0; |
| final short rightEdge = _tprops.getRgdxaCenter() != null |
| && _tprops.getRgdxaCenter().length > cells.size() + 1 ? _tprops |
| .getRgdxaCenter()[cells.size() + 1] : 0; |
| |
| TableCell tableCell = new TableCell( getParagraph( |
| lastCellStart ).getStartOffset(), getParagraph( p ) |
| .getEndOffset(), this, _levelNum, tableCellDescriptor, |
| leftEdge, rightEdge - leftEdge ); |
| cells.add( tableCell ); |
| lastCellStart = p + 1; |
| } |
| } |
| |
| if ( lastCellStart < ( numParagraphs() - 1 ) ) |
| { |
| TableCellDescriptor tableCellDescriptor = _tprops.getRgtc() != null |
| && _tprops.getRgtc().length > cells.size() ? _tprops |
| .getRgtc()[cells.size()] : new TableCellDescriptor(); |
| final short leftEdge = _tprops.getRgdxaCenter() != null |
| && _tprops.getRgdxaCenter().length > cells.size() ? _tprops |
| .getRgdxaCenter()[cells.size()] : 0; |
| final short rightEdge = _tprops.getRgdxaCenter() != null |
| && _tprops.getRgdxaCenter().length > cells.size() + 1 ? _tprops |
| .getRgdxaCenter()[cells.size() + 1] : 0; |
| |
| TableCell tableCell = new TableCell( lastCellStart, |
| ( numParagraphs() - 1 ), this, _levelNum, |
| tableCellDescriptor, leftEdge, rightEdge - leftEdge ); |
| cells.add( tableCell ); |
| } |
| |
| // sometimes there are "fake" cells which we need to exclude |
| if ( !cells.isEmpty() && cells.size() != expectedCellsCount ) |
| { |
| TableCell lastCell = cells.get( cells.size() - 1 ); |
| if ( lastCell.numParagraphs() == 1 |
| && ( lastCell.getParagraph( 0 ).isTableRowEnd() ) ) |
| { |
| // remove "fake" cell |
| cells.remove( cells.size() - 1 ); |
| } |
| } |
| |
| if ( cells.size() != expectedCellsCount ) |
| { |
| LOG.atWarn().log("Number of found table cells ({}) for table row [{}c; {}c] not equals to stored property value {}", |
| cells.size(), box(getStartOffset()),box(getEndOffset()),box(expectedCellsCount)); |
| _tprops.setItcMac( (short) cells.size() ); |
| } |
| |
| _cells = cells.toArray(new TableCell[0]); |
| _cellsFound = true; |
| } |
| |
| public boolean isTableHeader() |
| { |
| return _tprops.getFTableHeader(); |
| } |
| |
| public int numCells() |
| { |
| initCells(); |
| return _cells.length; |
| } |
| |
| @Override |
| protected void reset() |
| { |
| _cellsFound = false; |
| } |
| |
| public void setCantSplit( boolean cantSplit ) |
| { |
| _tprops.setFCantSplit( cantSplit ); |
| _papx.updateSprm( SPRM_FCANTSPLIT, (byte) ( cantSplit ? 1 : 0 ) ); |
| } |
| |
| public void setGapHalf( int dxaGapHalf ) |
| { |
| _tprops.setDxaGapHalf( dxaGapHalf ); |
| _papx.updateSprm( SPRM_DXAGAPHALF, (short) dxaGapHalf ); |
| } |
| |
| public void setRowHeight( int dyaRowHeight ) |
| { |
| _tprops.setDyaRowHeight( dyaRowHeight ); |
| _papx.updateSprm( SPRM_DYAROWHEIGHT, (short) dyaRowHeight ); |
| } |
| |
| public void setRowJustification( int jc ) |
| { |
| _tprops.setJc( (short) jc ); |
| _papx.updateSprm( SPRM_TJC, (short) jc ); |
| } |
| |
| public void setTableHeader( boolean tableHeader ) |
| { |
| _tprops.setFTableHeader( tableHeader ); |
| _papx.updateSprm( SPRM_FTABLEHEADER, (byte) ( tableHeader ? 1 : 0 ) ); |
| } |
| |
| } |