Logo Search packages:      
Sourcecode: ted version File versions

docItemTree.c

/************************************************************************/
/*                                                    */
/*  Buffer administration routines. Functionality related to the item   */
/*  tree.                                             */
/*                                                    */
/************************************************************************/

#   include "tedConfig.h"

#   include <stdlib.h>
#   include <string.h>
#   include <stdio.h>

#   include <appDebugon.h>

#   include "docBuf.h"
#   include "docEdit.h"

#   define  CHECK_ITEMS 0

#if 0

Schema to illustrate the numbering of paragraphs and the 
administration that is kept for that purpose
=========================================================

bi->biLeftParagraphs is the number of paragraphs to the left 
of this item in its immediate parent plus the number of paragraph
descendants. I.E: For items with children, the number of paragraphs 
in the children is included in bi->biLeftParagraphs. A paragraph 
includes itself in its bi->biLeftParagraphs.

Numbers of the paragraphs and the value of bi->biLeftParagraphs:

    1     2     3     4     5     6     7     8     9    10    11    12
    +     +     +     +     +     +     +     +     +     +     +     +
    1     2     3     4     1     2     3     4     5     1     2     3
    |     |     |     |     |     |     |     |     |     |     |     |
    4-----+-----+-----+     9-----+-----+-----+-----+     12----+-----+
    |                       |                             |
    12----------------------+-----------------------------+
    |
    *

Deleting 8 yeilds:

    1     2     3     4     5     6     7           8     9    10    11
    +     +     +     +     +     +     +           +     +     +     +
    1     2     3     4     1     2     3           4     1     2     3
    |     |     |     |     |     |     |           |     |     |     |
    4-----+-----+-----+     8-----+-----+-----+-----+     11----+-----+
    |                       |                             |
    11----------------------+-----------------------------+
    |
    *

So after deleting/inserting paragraphs: Descend to the root of the 
tree. In every parent adapt bi->biLeftParagraphs of all direct 
children to the right of the child that we come from. Set
bi->biLeftParagraphs of the parent to the value in its right most 
child. Continue with the parent of the parent until we have reached 
the root.

NOTE: I am educated as a biologist. My trees have their root at the 
    bottom, not at the top like those of computer scientists that 
    turn the world upside down. (I must admit that the metaphor 
    of parents and descendants has the computer science orientation.)

#endif

/************************************************************************/
/*                                                    */
/*  Free a BufferItem.                                      */
/*                                                    */
/************************************************************************/

void docCleanItem(      BufferDocument *  bd,
                  BufferItem *            bi )
    {
    int                 i;
    TextParticule *     tp;

    for ( i= bi->biChildCount- 1; i >= 0; i-- )
      { docFreeItem( bd, bi->biChildren[i] ); }
    if  ( bi->biChildren )
      { free( bi->biChildren );     }

    switch( bi->biLevel )
      {
      case DOClevDOC:
          break;

      case DOClevSECT:
          docCleanExternalItem( bd, &(bi->biSectHeader) );
          docCleanExternalItem( bd, &(bi->biSectFirstPageHeader) );
          docCleanExternalItem( bd, &(bi->biSectLeftPageHeader) );
          docCleanExternalItem( bd, &(bi->biSectRightPageHeader) );

          docCleanExternalItem( bd, &(bi->biSectFooter) );
          docCleanExternalItem( bd, &(bi->biSectFirstPageFooter) );
          docCleanExternalItem( bd, &(bi->biSectLeftPageFooter) );
          docCleanExternalItem( bd, &(bi->biSectRightPageFooter) );

          docCleanSectionProperties( &(bi->biSectProperties) );

          break;

      case DOClevCELL:
          break;

      case DOClevROW:
          docCleanRowProperties( &(bi->biRowProperties) );
          break;

      case DOClevPARA:
          tp= bi->biParaParticules;
          for ( i= 0; i < bi->biParaParticuleCount; tp++, i++ )
            {
            if  ( tp->tpKind == DOCkindFIELDSTART     ||
                  tp->tpKind == DOCkindFIELDEND )
                {
                if  ( tp->tpObjectNumber < 0                ||
                    tp->tpObjectNumber >=
                              bd->bdFieldList.dflFieldCount )
                  {
                  LDEB(bi->biParaParticules[i].tpObjectNumber);
                  LDEB(bd->bdFieldList.dflFieldCount);
                  continue;
                  }

                docCleanField( bd->bdFieldList.dflFields+
                                          tp->tpObjectNumber );
                docInitField( bd->bdFieldList.dflFields+
                                          tp->tpObjectNumber );
                }

            if  ( tp->tpKind == DOCkindNOTE                 &&
                  docDeleteNoteOfParticule( bd, bi, tp )    )
                { LDEB(tp->tpStroff);     }
            }

          for ( i= 0; i < bi->biParaObjectCount; i++ )
            { docCleanObject( bi->biParaObjects+ i ); }

          if  ( bi->biParaString )
            { free( bi->biParaString );   }
          if  ( bi->biParaParticules )
            { free( bi->biParaParticules );     }
          if  ( bi->biParaObjects )
            { free( bi->biParaObjects );  }
          if  ( bi->biParaLines )
            { free( bi->biParaLines );    }
          if  ( bi->biParaShapes )
            { free( bi->biParaShapes );   }

          docCleanParagraphProperties( &(bi->biParaProperties) );

          break;

      default:
          /*FALLTHROUGH*/
      case DOClevOUT:
          LDEB(bi->biLevel);
          break;
      }

    bi->biLevel= DOClevOUT;
    }

void docFreeItem( BufferDocument *  bd,
                  BufferItem *            bi )
    {
    docCleanItem( bd, bi );
    free( bi );
    }

/************************************************************************/
/*                                                    */
/*  Initialise a BufferItem.                                */
/*                                                    */
/************************************************************************/

void docInitItem( BufferItem *            bi,
                  BufferItem *            parent,
                  const BufferDocument *  bd,
                  int               numberInParent,
                  int               level,
                  int               inExternalItem )
    {
    bi->biChildren= (BufferItem **)0;
    bi->biChildCount= 0;
    bi->biLeftParagraphs= 0;

    switch( level )
      {
      case DOClevDOC:
          break;

      case DOClevSECT:
          docInitExternalItem( &(bi->biSectHeader) );
          docInitExternalItem( &(bi->biSectFirstPageHeader) );
          docInitExternalItem( &(bi->biSectLeftPageHeader) );
          docInitExternalItem( &(bi->biSectRightPageHeader) );

          docInitExternalItem( &(bi->biSectFooter) );
          docInitExternalItem( &(bi->biSectFirstPageFooter) );
          docInitExternalItem( &(bi->biSectLeftPageFooter) );
          docInitExternalItem( &(bi->biSectRightPageFooter) );

          docInitSectionProperties( &(bi->biSectProperties) );

          if  ( bd )
            { bi->biSectDocumentGeometry= bd->bdProperties.dpGeometry; }

          docInitSelectionScope( &(bi->biSectSelectionScope) );

          bi->biSectSelectionScope.ssInExternalItem= inExternalItem;

          bi->biSectHeaderFooterUseForSectBi= (const BufferItem *)0;
          bi->biSectHeaderFooterUseForPage= -1;

          break;

      case DOClevCELL:
          break;

      case DOClevROW:
          bi->biRowTableFirst= -1;
          bi->biRowTablePast= -1;
          bi->biRowTableFirstIsHeader= 0;
          bi->biRowPrecededByHeader= 0;

          docInitRowProperties( &(bi->biRowProperties) );

          docInitLayoutPosition( &(bi->biRowBelowAllPosition) );
          docInitLayoutPosition( &(bi->biRowAboveHeaderPosition) );
          break;

      case DOClevPARA:
          bi->biParaStrlen= 0;
          bi->biParaString= (unsigned char *)0;

          bi->biParaParticuleCount= 0;
          bi->biParaParticules= (TextParticule *)0;

          bi->biParaLineCount= 0;
          bi->biParaLines= (TextLine *)0;

          bi->biParaObjectCount= 0;
          bi->biParaObjects= (InsertedObject *)0;

          bi->biParaShapeCount= 0;
          bi->biParaShapes= (DrawingShape *)0;

          bi->biParaAscentTwips= 0;
          bi->biParaDescentTwips= 0;
          bi->biParaLeadingTwips= 0;

          bi->biParaBorderAboveParagraph= (const BorderProperties *)0;
          bi->biParaBorderBelowParagraph= (const BorderProperties *)0;

          docInitParagraphProperties( &(bi->biParaProperties) );

          break;

      default:
          bi->biLevel= DOClevOUT;
          bi->biParent= (BufferItem *)0;
          LDEB(level); return;
      }

    bi->biLevel= level;
    bi->biInExternalItem= inExternalItem;
    bi->biParent= parent;
    bi->biNumberInParent= numberInParent;

    docInitLayoutPosition( &(bi->biTopPosition) );
    docInitLayoutPosition( &(bi->biBelowPosition) );

    bi->biTopInsetTwips= 0;
    bi->biBottomInsetTwips= 0;

    return;
    }

/************************************************************************/
/*                                                    */
/*  1)  Delete a series of items.                           */
/*  2)  Delete an item from its parent.                           */
/*                                                    */
/************************************************************************/

static void docSetSectHeadFootScopes(           BufferItem *      sectBi )
    {
    int           n= sectBi->biNumberInParent;

    if  ( sectBi->biSectHeader.eiItem )
      {
      sectBi->biSectHeader.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }
    if  ( sectBi->biSectFirstPageHeader.eiItem )
      {
      sectBi->biSectFirstPageHeader.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }
    if  ( sectBi->biSectLeftPageHeader.eiItem )
      {
      sectBi->biSectLeftPageHeader.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }
    if  ( sectBi->biSectRightPageHeader.eiItem )
      {
      sectBi->biSectRightPageHeader.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }

    if  ( sectBi->biSectFooter.eiItem )
      {
      sectBi->biSectFooter.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }
    if  ( sectBi->biSectFirstPageFooter.eiItem )
      {
      sectBi->biSectFirstPageFooter.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }
    if  ( sectBi->biSectLeftPageFooter.eiItem )
      {
      sectBi->biSectLeftPageFooter.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }
    if  ( sectBi->biSectRightPageFooter.eiItem )
      {
      sectBi->biSectLeftPageFooter.eiItem->
                      biSectSelectionScope.ssSectNrExternalTo= n;
      }

    return;
    }

/*  1  */
void docDeleteItems(    BufferDocument *  bd,
                  BufferItem *            bi,
                  int               first,
                  int               count )
    {
    int           n;
    int           f;
    int           c;
    int           paragraphsDeleted= 0;

#   if CHECK_ITEMS
    if  ( docCheckItem( &(bd->bdItem) ) )
      { LDEB(2); docListItem( 0, &(bd->bdItem) ); abort(); }
#   endif

    if  ( first > bi->biChildCount )
      {
      LLDEB(first,bi->biChildCount);
      first= bi->biChildCount;
      }

    if  ( first+ count > bi->biChildCount )
      {
      LLDEB(first+count,bi->biChildCount);
      count= bi->biChildCount- first;
      }

    if  ( count <= 0 )
      { LDEB(count); return;  }

    if  ( count > 0 )
      {
      f= 0;
      if  ( first > 0 )
          { f= bi->biChildren[first- 1]->biLeftParagraphs;  }

      c= bi->biChildren[first+ count- 1]->biLeftParagraphs;

      paragraphsDeleted= c- f;
      }

    n= first+ count- 1;
    while( n >= first )
      { docFreeItem( bd, bi->biChildren[n] ); n--; }

    bi->biChildCount -= count;

    f= first;
    while( f < bi->biChildCount )
      {
      bi->biChildren[f]= bi->biChildren[f+ count];
      bi->biChildren[f]->biNumberInParent= f;
      bi->biChildren[f]->biLeftParagraphs -= paragraphsDeleted;

      if  ( bi->biChildren[f]->biLevel == DOClevSECT )
          { docSetSectHeadFootScopes( bi->biChildren[f] ); }

      f++;
      }

    while( bi->biParent )
      {
      first= bi->biNumberInParent;
      bi= bi->biParent;

      for ( f= first; f < bi->biChildCount; f++ )
          { bi->biChildren[f]->biLeftParagraphs -= paragraphsDeleted;   }
      }

    bi->biLeftParagraphs -= paragraphsDeleted;

#   if CHECK_ITEMS
    if  ( docCheckItem( &(bd->bdItem) ) )
      { LDEB(2); docListItem( 0, &(bd->bdItem) ); abort(); }
#   endif

    return;
    }

/*  2  */
void docDeleteItem(     BufferDocument *  bd,
                  BufferItem *            bi )
    {
    if  ( bi->biParent )
      { docDeleteItems( bd, bi->biParent, bi->biNumberInParent, 1 );    }
    else{ docFreeItem( bd, bi );                            }
    }

/************************************************************************/
/*                                                    */
/*  Add a new child to a parent.                            */
/*                                                    */
/************************************************************************/

BufferItem * docInsertItem(   const BufferDocument *  bd,
                        BufferItem *            parent,
                        int               n,
                        ItemLevel         level )
    {
    int                 i;

    int                 newSize;

    BufferItem ** freshChildren;
    BufferItem *  bi;

#   if CHECK_ITEMS
    if  ( docCheckItem( &(bd->bdItem) ) )
      { LDEB(2); docListItem( 0, &(bd->bdItem) ); abort(); }
#   endif

    if  ( parent->biLevel != level- 1 )
      {
      SSDEB(docLevelStr(parent->biLevel),docLevelStr(level));
      return (BufferItem *)0;
      }

    switch( parent->biLevel )
      {
      case DOClevDOC:
      case DOClevSECT:
      case DOClevROW:
      case DOClevCELL:
          break;

      default:
          LDEB(parent->biLevel); return (BufferItem *)0;
      }

    newSize= parent->biChildCount;

    if  ( newSize % 10 )
      { newSize ++;           }
    else{ newSize += 10;      }

    newSize *= sizeof(BufferItem *);

    freshChildren= (BufferItem **)realloc( parent->biChildren, newSize );
    if  ( ! freshChildren )
      { LXDEB(newSize,freshChildren); return (BufferItem *)0; }
    parent->biChildren= freshChildren;

    bi= (BufferItem *)malloc( sizeof(BufferItem) );
    if  ( ! bi )
      { XDEB(bi); return bi;  }

    if  ( n == -1 )
      { n= parent->biChildCount; }

    docInitItem( bi, parent, bd, n, level, parent->biInExternalItem );

    if  ( n == 0 )
      { bi->biTopPosition= parent->biTopPosition;                 }
    else{ bi->biTopPosition= freshChildren[n-1]->biBelowPosition; }

    for ( i= parent->biChildCount; i > n; i-- )
      {
      freshChildren[i]= freshChildren[i-1];

      freshChildren[i]->biNumberInParent= i;

      if  ( freshChildren[i]->biLevel == DOClevSECT )
          { docSetSectHeadFootScopes( freshChildren[i] ); }
      }

    freshChildren[n]= bi;
    parent->biChildCount++;

    if  ( level != DOClevPARA )
      {
      if  ( n > 0 )
          { bi->biLeftParagraphs= freshChildren[n-1]->biLeftParagraphs; }

      return bi;
      }

    if  ( n > 0 )
      { bi->biLeftParagraphs= freshChildren[n-1]->biLeftParagraphs; }

    for ( i= n; i < parent->biChildCount; i++ )
      { parent->biChildren[i]->biLeftParagraphs++;    }

    while( parent->biParent )
      {
      n= parent->biNumberInParent;
      parent= parent->biParent;

      for ( i= n; i < parent->biChildCount; i++ )
          { parent->biChildren[i]->biLeftParagraphs++;      }
      }

    parent->biLeftParagraphs++;

#   if CHECK_ITEMS
    if  ( docCheckItem( &(bd->bdItem) ) )
      { LDEB(2); docListItem( 0, &(bd->bdItem) ); abort(); }
#   endif

    return bi;
    }

/************************************************************************/
/*                                                    */
/*  Make an empty paragraph: Needed at several locations.         */
/*                                                    */
/************************************************************************/

BufferItem * docInsertEmptyParagraph(
                        BufferDocument *  bd,
                        BufferItem *            bi,
                        int               textAttributeNumber )
    {
    if  ( bi->biLevel < DOClevSECT )
      { LDEB(bi->biLevel); return (BufferItem *)0;    }

    if  ( bi->biLevel < DOClevROW )
      {
      bi= docInsertItem( bd, bi, -1, DOClevROW );
      if  ( ! bi )
          { XDEB(bi); return (BufferItem *)0;   }
      }

    if  ( bi->biLevel < DOClevCELL )
      {
      bi= docInsertItem( bd, bi, -1, DOClevCELL );
      if  ( ! bi )
          { XDEB(bi); return (BufferItem *)0;   }
      }

    if  ( bi->biLevel < DOClevPARA )
      {
      bi= docInsertItem( bd, bi, -1, DOClevPARA );
      if  ( ! bi )
          { XDEB(bi); return (BufferItem *)0;   }
      }
    else{
      bi= docInsertItem( bd, bi->biParent, -1, DOClevPARA );
      if  ( ! bi )
          { XDEB(bi); return (BufferItem *)0;   }
      }

    if  ( ! docInsertTextParticule( bi, 0, 0, 0,
                            DOCkindTEXT, textAttributeNumber ) )
      { LDEB(1); return (BufferItem *)0;  }

    if  ( docInflateTextString( bi, 0 ) )
      { LDEB(1); return (BufferItem *)0;  }
    bi->biParaString[bi->biParaStrlen]= '\0';

    return bi;
    }

/************************************************************************/
/*                                                    */
/*  Copy a paragraph to make a new one.                           */
/*                                                    */
/************************************************************************/

BufferItem * docCopyParaItem( DocumentCopyJob * dcj,
                        EditOperation *         eo,
                        BufferItem *            biCellTo,
                        int               n,
                        BufferItem *            biParaFrom,
                        int               inTable )
    {
    BufferItem *  biParaTo;

    const int           partTo= 0;
    int                 partFrom= 0;

    int                 particulesInserted= 0;
    int                 charactersCopied= 0;

    PropertyMask  ppChgMask;
    PropertyMask  ppUpdMask;

    biParaTo= docInsertItem( dcj->dcjBdTo, biCellTo, n, DOClevPARA );
    if  ( ! biParaTo )
      { XDEB(biParaTo); return biParaTo;  }

    biParaTo->biParaInTable= inTable;

    PROPmaskCLEAR( &ppChgMask );

    PROPmaskCLEAR( &ppUpdMask );
    PROPmaskFILL( &ppUpdMask, PPprop_COUNT );
    PROPmaskUNSET( &ppUpdMask, PPpropIN_TABLE );

    if  ( biParaFrom->biParaListOverride > 0 )
      {
      int         bulletFieldNr= -1;
      int         bulletPartBegin= -1;
      int         bulletPartEnd= -1;
      int         bulletStroffBegin= -1;
      int         bulletStroffEnd= -1;

      if  ( docDelimitParaHeadField( &bulletFieldNr,
                  &bulletPartBegin, &bulletPartEnd,
                  &bulletStroffBegin, &bulletStroffEnd,
                  biParaFrom, dcj->dcjBdFrom ) )
          { LDEB(1);    }

      if  ( partFrom <= bulletPartEnd )
          { partFrom= bulletPartEnd+ 1;   }
      }

    if  ( partFrom < biParaFrom->biParaParticuleCount )
      {
      if  ( docCopyParticules( dcj, eo, biParaTo, biParaFrom, partTo,
                  partFrom, biParaFrom->biParaParticuleCount- partFrom,
                  &particulesInserted, &charactersCopied ) )
          {
          LDEB(biParaFrom->biParaParticuleCount);
          docDeleteItem( dcj->dcjBdTo, biParaTo ); return (BufferItem *)0;
          }
      }
    else{
      int               textAttributeNumberTo;
      const TextParticule *   tpFrom;

      tpFrom= biParaFrom->biParaParticules+
                            biParaFrom->biParaParticuleCount- 1;

      textAttributeNumberTo= docMapTextAttributeNumber( dcj,
                                  tpFrom->tpTextAttributeNumber );
      if  ( textAttributeNumberTo < 0 )
          { LDEB(textAttributeNumberTo); return (BufferItem *)0;  }

      if  ( ! docInsertTextParticule( biParaTo, 0, 0, 0,
                              DOCkindTEXT, textAttributeNumberTo ) )
          { LDEB(1); return (BufferItem *)0;    }

      if  ( docInflateTextString( biParaTo, 0 ) )
          { LDEB(1); return (BufferItem *)0;    }
      biParaTo->biParaString[biParaTo->biParaStrlen]= '\0';
      }

    if  ( docEditUpdParaProperties( eo, &ppChgMask, biParaTo,
                        &ppUpdMask, &(biParaFrom->biParaProperties),
                        dcj->dcjColorMap, dcj->dcjListStyleMap ) )
      { LDEB(1); return (BufferItem *)0;  }

    if  ( biParaTo->biParaListOverride > 0 )
      { dcj->dcjBulletsCopied++;    }

    return biParaTo;
    }

BufferItem * docCopyRowItem(  DocumentCopyJob * dcj,
                        EditOperation *         eo,
                        int *             pParasCopied,
                        BufferItem *            sectBiTo,
                        int               n,
                        BufferItem *            rowBiFrom,
                        int               inTable )
    {
    BufferItem *  biRowTo;
    int                 col;
    int                 parasCopied= 0;

    biRowTo= docInsertItem( dcj->dcjBdTo, sectBiTo, n, DOClevROW );
    if  ( ! biRowTo )
      { XDEB(biRowTo); return biRowTo;    }

    if  ( docCopyRowProperties( &(biRowTo->biRowProperties),
                      &(rowBiFrom->biRowProperties), dcj->dcjColorMap ) )
      { LDEB(1); return (BufferItem *)0;  }

    for ( col= 0; col < rowBiFrom->biChildCount; col++ )
      {
      BufferItem *      biCellFrom;
      BufferItem *      biCellTo;
      int         para;

      biCellFrom= rowBiFrom->biChildren[col];
      biCellTo= docInsertItem( dcj->dcjBdTo, biRowTo, col, DOClevCELL );

      if  ( ! biCellTo )
          { XDEB(biCellTo); return (BufferItem *)0;   }

      for ( para= 0; para < biCellFrom->biChildCount; para++ )
          {
          BufferItem *  biParaFrom= biCellFrom->biChildren[para];

          if  ( ! docCopyParaItem( dcj, eo,
                            biCellTo, para, biParaFrom, inTable ) )
            { LDEB(para); return (BufferItem *)0;     }

          parasCopied++;
          }
      }

    *pParasCopied= parasCopied;
    return biRowTo;
    }

BufferItem * docCopySectItem( DocumentCopyJob * dcj,
                        EditOperation *         eo,
                        BufferItem *            parentBiTo,
                        int               n,
                        BufferItem *            biSectFrom,
                        const SelectionScope *  ss )
    {
    BufferItem *        sectBiTo;
    int                       row;

    if  ( parentBiTo )
      {
      if  ( parentBiTo->biInExternalItem != ss->ssInExternalItem )
          {
          LDEB(parentBiTo->biInExternalItem);
          LDEB(ss->ssInExternalItem);
          return (BufferItem *)0;
          }

      sectBiTo= docInsertItem( dcj->dcjBdTo, parentBiTo, n, DOClevSECT );
      if  ( ! sectBiTo )
          { XDEB(sectBiTo); return (BufferItem *)0;   }
      }
    else{
      n= 0;
      sectBiTo= (BufferItem *)malloc( sizeof(BufferItem) );

      if  ( ! sectBiTo )
          { XDEB(sectBiTo); return (BufferItem *)0;   }

      docInitItem( sectBiTo, (BufferItem *)0, dcj->dcjBdTo, n,
                        DOClevSECT, ss->ssInExternalItem );
      }

    sectBiTo->biSectSelectionScope= *ss;

    if  ( docCopySectionProperties( &(sectBiTo->biSectProperties),
                              &(biSectFrom->biSectProperties) ) )
      {
      LDEB(1);
      docDeleteItem( dcj->dcjBdTo, sectBiTo );
      return (BufferItem *)0;
      }

    for ( row= 0; row < biSectFrom->biChildCount; row++ )
      {
      BufferItem *      rowBiFrom= biSectFrom->biChildren[row];
      BufferItem *      rowBiTo;
      int         parasCopied;

      rowBiTo= docCopyRowItem( dcj, eo, &parasCopied,
                              sectBiTo, row, rowBiFrom,
                              rowBiFrom->biRowHasTableParagraphs );
      if  ( ! rowBiTo )
          {
          XDEB(rowBiTo);
          docDeleteItem( dcj->dcjBdTo, sectBiTo );
          return (BufferItem *)0;
          }
      }

    return sectBiTo;
    }

/************************************************************************/
/*                                                    */
/*  Insert a new row in a table.                            */
/*                                                    */
/************************************************************************/

BufferItem * docInsertRowItem(      BufferDocument *  bd,
                        BufferItem *            sectBi,
                        int               n,
                        const RowProperties *   rp,
                        int               textAttributeNumber )
    {
    int                       col;

    BufferItem *        rowBi= (BufferItem *)0;

    rowBi= docInsertItem( bd, sectBi, n, DOClevROW );
    if  ( ! rowBi )
      { XDEB(rowBi); return (BufferItem *)0;    }

    for ( col= 0; col < rp->rpCellCount; col++ )
      {
      BufferItem *      paraBi;

      paraBi= docInsertEmptyParagraph( bd, rowBi, textAttributeNumber );
      if  ( ! paraBi )
          {
          XDEB(paraBi);
          docDeleteItem( bd, rowBi );
          return (BufferItem *)0;
          }

      paraBi->biParaInTable= 1;
      rowBi->biRowHasTableParagraphs= 1;
      }

    if  ( docCopyRowProperties( &(rowBi->biRowProperties),
                                        rp, (const int *)0 ) )
      {
      LDEB(1);
      docDeleteItem( bd, rowBi );
      return (BufferItem *)0;
      }

    return rowBi;
    }

/************************************************************************/
/*                                                    */
/*  Step in insert row actions: Copy attributes.                  */
/*                                                    */
/*  NOTE: Copying the text attribute numbers means that the rows MUST   */
/*    be in the same document. The same applies for the color numbers   */
/*    in the paragraph properties.                          */
/*                                                    */
/************************************************************************/

int docCopyRowColumnAttributes(     BufferItem *            rowBi,
                        const BufferItem *      refRowBi )
    {
    int           colCount;
    int           col;

    if  ( rowBi->biChildCount < refRowBi->biChildCount )
      { colCount= rowBi->biChildCount;    }
    else{ colCount= refRowBi->biChildCount;     }

    for ( col= 0; col < colCount; col++ )
      {
      DocumentPosition  dp;
      DocumentPosition  dpRef;

      TextParticule *         tp;
      const TextParticule *   tpRef;

      PropertyMask            ppChgMask;
      PropertyMask            ppUpdMask;

      const int * const colorMap= (const int *)0;
      const int * const listStyleMap= (const int *)0;

      if  ( docFirstPosition( &dp, rowBi->biChildren[col] ) )
          { continue;   }
      if  ( docFirstPosition( &dpRef, refRowBi->biChildren[col] ) )
          { continue;   }

      PROPmaskCLEAR( &ppChgMask );

      PROPmaskCLEAR( &ppUpdMask );
      PROPmaskFILL( &ppUpdMask, PPprop_COUNT );

      if  ( docUpdParaProperties( &ppChgMask, &(dp.dpBi->biParaProperties),
                        &ppUpdMask, &(dpRef.dpBi->biParaProperties),
                        colorMap, listStyleMap ) )
          { LDEB(1); return -1;     }

      tp= dp.dpBi->biParaParticules;
      tpRef= dpRef.dpBi->biParaParticules;

      tp->tpTextAttributeNumber= tpRef->tpTextAttributeNumber;
      }

    return 0;
    }

/************************************************************************/
/*                                                    */
/*  Split an item with childen.                                   */
/*                                                    */
/*  1)  See whether there is a parent of the given level that can be    */
/*    split.                                                */
/*                                                    */
/************************************************************************/

static int docSplitGroupItemLow(    const BufferDocument *  bd,
                              BufferItem **           pNewBi,
                              BufferItem *            oldBi,
                              int               n )
    {
    BufferItem *  newBi;
    int                 i;
    int                 prev;

    newBi= docInsertItem( bd, oldBi->biParent,
                        oldBi->biNumberInParent, oldBi->biLevel );
    if  ( ! newBi )
      { XDEB(newBi); return -1;     }

    switch( oldBi->biLevel )
      {
      case DOClevSECT:
          if  ( docCopySectionProperties( &newBi->biSectProperties,
                                  &oldBi->biSectProperties ) )
            { LDEB(1); return -1;   }
          break;

      case DOClevCELL:
          break;

      case DOClevROW:
          if  ( oldBi->biRowHasTableParagraphs )
            {
            LLDEB(oldBi->biLevel,oldBi->biRowHasTableParagraphs);
            return -1;
            }

          if  ( docCopyRowProperties( &(newBi->biRowProperties),
                        &(oldBi->biRowProperties), (const int *)0 ) )
            { LDEB(1); return -1;   }
          break;

      default:
          LDEB(oldBi->biLevel); return -1;
      }

    newBi->biChildren= (BufferItem **)malloc( n* sizeof(BufferItem *) );
    if  ( ! newBi->biChildren )
      { XDEB(newBi->biChildren); return -1;     }

    for ( i= 0; i < n; i++ )
      {
      newBi->biChildren[i]= oldBi->biChildren[i];
      newBi->biChildren[i]->biParent= newBi;
      }

    prev= 0;
    if  ( newBi->biNumberInParent > 0 )
      {
      prev= newBi->biParent->biChildren[newBi->biNumberInParent-1]->
                                          biLeftParagraphs;
      }

    if  ( n == 0 )
      { newBi->biLeftParagraphs= prev; }
    else{
      newBi->biLeftParagraphs= prev+ newBi->biChildren[n-1]->biLeftParagraphs;
      }

    newBi->biChildCount= n;
    oldBi->biChildCount -= n;

    prev= 0;
    for ( i= 0; i < oldBi->biChildCount; i++ )
      {
      BufferItem *      child= oldBi->biChildren[i+ n];;

      oldBi->biChildren[i]= child;
      child->biNumberInParent -= n;

      if  ( oldBi->biChildren[i]->biLevel == DOClevPARA )
          { prev++;     }
      else{
          if  ( child->biChildCount > 0 )
            {
            prev += child->biChildren[child->biChildCount-1]->
                                              biLeftParagraphs;
            }
          }

      oldBi->biChildren[i]->biLeftParagraphs= prev;
      }

    *pNewBi= newBi; return 0;
    }

int docSplitGroupItem(  const BufferDocument *  bd,
                  BufferItem **           pNewBi,
                  BufferItem **           pParentBi,
                  BufferItem *            parentBi,
                  int               n,
                  int               level )
    {
    BufferItem *  newBi= (BufferItem *)0;
    BufferItem *  splitBi;

#   if CHECK_ITEMS
    SDEB(docLevelStr(parentBi->biLevel));
    if  ( docCheckItem( &(bd->bdItem) ) )
      { LDEB(2); docListItem( 0, &(bd->bdItem) ); abort(); }
#   endif

    splitBi= parentBi;
    while( splitBi && splitBi->biLevel != level- 1 )
      { splitBi= splitBi->biParent; }
    if  ( ! splitBi )
      {
      SSXDEB(docLevelStr(parentBi->biLevel),docLevelStr(level),splitBi);
      return -1;
      }

    if  ( n < 0 || n >= parentBi->biChildCount )
      { LLDEB(n,parentBi->biChildCount); return -1;   }

    for (;;)
      {
      /*
      oldBi= parentBi->biChildren[n];
      */

      if  ( n > 0 || parentBi->biLevel == level )
          {
          if  ( docSplitGroupItemLow( bd, &newBi, parentBi, n ) )
            { LDEB(n); return -1;   }
          }

      if  ( parentBi->biLevel == level )
          { break;      }

      n= parentBi->biNumberInParent;
      parentBi= parentBi->biParent;
      }

#   if CHECK_ITEMS
    SDEB(docLevelStr(parentBi->biLevel));
    if  ( docCheckItem( &(bd->bdItem) ) )
      { LDEB(2); docListItem( 0, &(bd->bdItem) ); abort(); }
#   endif

    *pNewBi= newBi;
    *pParentBi= parentBi;
    return 0;
    }

/************************************************************************/
/*                                                    */
/*  Return the number of a paragraph.                             */
/*                                                    */
/************************************************************************/

int docNumberOfParagraph(     const BufferItem *      bi )
    {
    int           n= 0;

    if  ( bi->biLevel != DOClevPARA )
      { SDEB(docLevelStr(bi->biLevel)); return -1;    }

    n= bi->biLeftParagraphs;

    while( bi->biParent )
      {
      bi= bi->biParent;

      if  ( bi->biParent && bi->biNumberInParent > 0 )
          {
          if  ( bi->biNumberInParent >= bi->biParent->biChildCount )
            { LLDEB(bi->biNumberInParent,bi->biParent->biChildCount); }

          n += bi->biParent->biChildren[
                        bi->biNumberInParent- 1]->biLeftParagraphs;
          }
      }

    return n;
    }

BufferItem * docGetParagraphByNumber(     BufferItem *      bi,
                              int         n )
    {
    if  ( bi->biParent )
      { XDEB(bi->biParent); return (BufferItem *)0;   }

    while( bi->biChildCount > 0 )
      {
      int         i;

      for ( i= 0; i < bi->biChildCount; i++ )
          {
          if  ( bi->biChildren[i]->biLeftParagraphs >= n )
            { break;    }
          }

      if  ( i >= bi->biChildCount )
          {
          LLSDEB(n,bi->biChildCount,docLevelStr(bi->biLevel));
          return (BufferItem *)0;
          }

      if  ( i > 0 )
          { n -= bi->biChildren[i-1]->biLeftParagraphs;     }

      bi= bi->biChildren[i];
      }

    if  ( bi->biLevel != DOClevPARA )
      { SDEB(docLevelStr(bi->biLevel)); return (BufferItem *)0;   }

    if  ( n != 1 )
      { LDEB(n); return (BufferItem *)0; }

    return bi;
    }

/************************************************************************/
/*                                                    */
/*  Change the kind of external item for a node and all its children.   */
/*                                                    */
/************************************************************************/

void docSetExternalItemKind(  BufferItem *            bi,
                        int               extItKind )
    {
    int           i;

    bi->biInExternalItem= extItKind;

    if  ( bi->biLevel == DOClevSECT )
      { bi->biSectSelectionScope.ssInExternalItem= extItKind; }

    for ( i= 0; i < bi->biChildCount; i++ )
      { docSetExternalItemKind( bi->biChildren[i], extItKind );   }

    return;
    }


Generated by  Doxygen 1.6.0   Back to index