Logo Search packages:      
Sourcecode: abiword version File versions

fl_DocListener.cpp

/* AbiWord
 * Copyright (C) 1998 AbiSource, Inc.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  
 * 02111-1307, USA.
 */

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

#include "ut_types.h"
#include "ut_debugmsg.h"
#include "ut_assert.h"
#include "ut_string.h"
#include "pt_Types.h"
#include "px_ChangeRecord.h"
#include "px_CR_Object.h"
#include "px_CR_ObjectChange.h"
#include "px_CR_Span.h"
#include "px_CR_SpanChange.h"
#include "px_CR_Strux.h"
#include "px_CR_StruxChange.h"
#include "px_CR_FmtMark.h"
//###TF#include "px_CR_Bookmark.h"
#include "px_CR_FmtMarkChange.h"
#include "px_CR_Glob.h"
#include "fl_DocListener.h"
#include "fl_DocLayout.h"
#include "fl_SectionLayout.h"
#include "fl_BlockLayout.h"
#include "fl_ContainerLayout.h"
#include "fl_FootnoteLayout.h"
#include "fl_TableLayout.h"
#include "fl_TOCLayout.h"
#include "fp_Line.h"
#include "fp_Run.h"
#include "gr_Graphics.h"
#include "pd_Document.h"
#include "pp_AttrProp.h"
#include "xap_Frame.h"
#include "xap_Prefs.h"
#include "fv_View.h"

#define UPDATE_LAYOUT_ON_SIGNAL

static HdrFtrType s_convertToHdrFtrType(const XML_Char * pszHFType);

/*!
 Create DocListener
 \param doc Client of this DocListener
 \param pLayout Layout notified by this DocListener
*/
00065 fl_DocListener::fl_DocListener(PD_Document* doc, FL_DocLayout *pLayout)
{
      m_pDoc = doc;
      m_pLayout = pLayout;
      if(pLayout->getGraphics() != NULL)
      {
            m_bScreen = pLayout->getGraphics()->queryProperties(GR_Graphics::DGP_SCREEN);
      }
      else
      {
            m_bScreen = false;
      }
      m_iGlobCounter = 0;
      m_pCurrentSL = NULL;
//
// Put a NULL on th stack to signify the top.
//
      m_sLastContainerLayout.push(NULL);
      m_bFootnoteInProgress = false;
      m_bEndFootnoteProcessedInBlock = false;
      m_bCacheChanges = false;
      m_chgMaskCached = AV_CHG_NONE;
}

/*!
 Destruct DocListener
*/
00092 fl_DocListener::~fl_DocListener()
{
      UT_ASSERT(m_sLastContainerLayout.getDepth() == 1);
}

/*!
 */
bool fl_DocListener::populate(PL_StruxFmtHandle sfh,
                                            const PX_ChangeRecord * pcr)
{
      UT_ASSERT(m_pLayout);
      UT_DEBUGMSG(("fl_DocListener::populate type %d \n",pcr->getType()));

      bool bResult = false;

      switch (pcr->getType())
      {
      case PX_ChangeRecord::PXT_InsertSpan:
      {
            const PX_ChangeRecord_Span * pcrs = static_cast<const PX_ChangeRecord_Span *> (pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            if(pL->getType() != PTX_Block)
            {
                  m_pDoc->miniDump(pL->getStruxDocHandle(),8);
                  UT_DEBUGMSG(("Illegal strux is %x \n",pL->getStruxDocHandle()));
            }                 
            UT_ASSERT(pL->getType() == PTX_Block);

            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            if(pCL->getPrev()!= NULL && pCL->getPrev()->getLastContainer()==NULL)
            {
                  UT_DEBUGMSG(("In DocListner no LastLine in Previous Block Fixing this now \n"));
                  UT_DEBUGMSG(("getPrev = %d this = %d \n",pCL->getPrev(),pCL));
                  if( pCL->getSectionLayout()->getType() != FL_SECTION_HDRFTR)
                        pCL->getPrev()->format();
            }

            PT_BlockOffset blockOffset = pcrs->getBlockOffset();
            UT_uint32 len = pcrs->getLength();
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = static_cast<fl_HdrFtrShadow *>(pCLSL)->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_populateSpan(pCL, pcrs, blockOffset, len);
            }
            else
                  bResult = pCLSL->bl_doclistener_populateSpan(pCL, pcrs, blockOffset, len);
            if(pCL->getLastContainer()==NULL)
            {
                  UT_DEBUGMSG(("In  DocListner no LastLine in this block fixing this now \n"));
                  UT_DEBUGMSG(("getPrev = %d this = %d \n",pCL->getPrev(),pCL));
                  if(pCL->getSectionLayout()->getType() != FL_SECTION_HDRFTR && pCL->getPrev()!= NULL)
                        pCL->format();
                  //UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
            }

            goto finish_up;
      }

      case PX_ChangeRecord::PXT_InsertObject:
      {
            const PX_ChangeRecord_Object * pcro = static_cast<const PX_ChangeRecord_Object *>(pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            if(pL->getType() != PTX_Block)
            {
                  m_pDoc->miniDump(pL->getStruxDocHandle(),8);
            }
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            PT_BlockOffset blockOffset = pcro->getBlockOffset();

            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_populateObject(pCL, blockOffset,pcro);
            }
            else
                  bResult = pCLSL->bl_doclistener_populateObject(pCL, blockOffset,pcro);

#if 0
            // if the inserted object is a bookmark, we have to notify TOCs of bookmark change in case
            // any of them is restricted by the given bookmark
            if(pcro->getObjectType() == PTO_Bookmark)
            {
                  if(pL->getType() == PTX_Block)
                  {
                        fl_BlockLayout * pBL = static_cast<fl_BlockLayout *>(pL);
                        fp_Run * pRun = pBL->findRunAtOffset(pcro->getBlockOffset());
                        if(pRun && pRun->getType() == FPRUN_BOOKMARK)
                        {
                              fp_BookmarkRun * pB = static_cast<fp_BookmarkRun*>(pRun);

                              // only do this when the end-object is inserted ...
                              if(!pB->isStartOfBookmark())
                                    m_pLayout->updateTOCsOnBookmarkChange(pB->getName());
                        }
                        else if(pRun && pRun->getType() != FPRUN_BOOKMARK)
                        {
                              UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
                        }
                  }
            }
#endif
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_InsertFmtMark:
      {
            const PX_ChangeRecord_FmtMark * pcrfm = static_cast<const PX_ChangeRecord_FmtMark *>(pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            if(pL->getType() != PTX_Block)
            {
                  m_pDoc->miniDump(pL->getStruxDocHandle(),8);
                  UT_DEBUGMSG(("Illegal strux is %x \n",pL->getStruxDocHandle()));
                  UT_return_val_if_fail((pL->getType() == PTX_Block),false);
            }                 
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_insertFmtMark(pCL, pcrfm);
            }
            else
                  bResult = pCLSL->bl_doclistener_insertFmtMark(pCL, pcrfm);
            goto finish_up;
      }
      default:
            UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
            return false;
      }

 finish_up:
      if (0 == m_iGlobCounter)
      {
#ifndef UPDATE_LAYOUT_ON_SIGNAL
            m_pLayout->updateLayout();
#endif
      }
      
      return bResult;
}

static UT_uint32 countStrux = 0;
/*!
 */
bool fl_DocListener::populateStrux(PL_StruxDocHandle sdh,
                                                   const PX_ChangeRecord * pcr,
                                                   PL_StruxFmtHandle * psfh)
{
      UT_ASSERT(m_pLayout);

      UT_ASSERT(pcr->getType() == PX_ChangeRecord::PXT_InsertStrux);
      const PX_ChangeRecord_Strux * pcrx = static_cast<const PX_ChangeRecord_Strux *> (pcr);

      XAP_Frame * pFrame = XAP_App::getApp()->getLastFocussedFrame();
      if(pFrame)
      {
            if(pcrx->getStruxType() == PTX_Block && !m_bFootnoteInProgress)
            {
                  if(!m_bEndFootnoteProcessedInBlock)
                  {
                        xxx_UT_DEBUGMSG(("Null Update in Populate Strux \n"));
                        pFrame->nullUpdate();
                        PT_DocPosition pos = pcrx->getPosition();
                        UT_uint32 percentFilled = 100*pos/m_pLayout->getDocSize();
                        m_pLayout->setPercentFilled(percentFilled);
                        UT_DEBUGMSG(("Percent filled = %d \n",percentFilled));
                        if(countStrux > 60)
                        {
                              if(countStrux < 300)
                              {
                                    if(m_pLayout->getView() && (m_pLayout->getView()->getPoint() == 0))
                                    {
                                          fl_DocSectionLayout * pDSL = m_pLayout->getFirstSection();
                                          pDSL->format();
                                          countStrux = 300;
                                    }
                              }
                        }
                        countStrux++;
                  }
                  else
                  {
                        m_bEndFootnoteProcessedInBlock = false;
                        UT_DEBUGMSG(("EndFootnote strux processed Populate Strux \n"));
                  }
            }
      }
      else
      {
            UT_DEBUGMSG(("No valid frame!!! \n"));
      }
//
// This piece of code detects if there is enough document to notify
// listeners and other things.
//
// If so it moves the insertion point from 0.
//
      if(m_pLayout->getView() && (m_pLayout->getView()->getPoint() == 0))
      {
            fl_DocSectionLayout * pDSL = m_pLayout->getFirstSection();
            if(pDSL)
            {
                  fl_ContainerLayout * pCL = pDSL->getFirstLayout();
                  UT_uint32 i = 0;
                  while(pCL && i< 2)
                  {
                        i++;
                        pCL = pCL->getNext();
                  }
                  if(i >= 2)
                  {
                        m_pLayout->getView()->moveInsPtTo(FV_DOCPOS_BOD);
                  }
            }
      }

      switch (pcrx->getStruxType())
      {
      case PTX_Section:
      {
            PT_AttrPropIndex indexAP = pcr->getIndexAP();
            const PP_AttrProp* pAP = NULL;
            UT_DEBUGMSG(("SEVIOR: Doing Populate Section in DocListener \n"));
            if (m_pDoc->getAttrProp(indexAP, &pAP) && pAP)
            {
                  const XML_Char* pszSectionType = NULL;
                  pAP->getAttribute("type", pszSectionType);
                  UT_DEBUGMSG(("fl_DocListener::populateStrux for '%s'\n",
                                     pszSectionType ? pszSectionType : "(null)"));
                  if (!pszSectionType     || (0 == UT_strcmp(pszSectionType, "doc")))
                  {
                        // Append a SectionLayout to this DocLayout
                        //
                        // Format Previous section is it exists to get page mapping sane.
                        //
                        UT_DEBUGMSG(("SEVIOR: Doing Populate DocSection in DocListener \n"));
                        fl_DocSectionLayout * pPDSL = m_pLayout->getLastSection();
                        if(pPDSL != NULL)
                        {
                              pPDSL->format();
                        }
                        
                        fl_DocSectionLayout* pSL = new fl_DocSectionLayout(m_pLayout, sdh, pcr->getIndexAP(), FL_SECTION_DOC);
                        if (!pSL)
                        {
                              UT_DEBUGMSG(("no memory for SectionLayout"));
                              return false;
                        }
                        
                        m_pLayout->addSection(pSL);
                        
                        *psfh = (PL_StruxFmtHandle)pSL;
                        
                        m_pCurrentSL = pSL;
                  }
                  else
                  {
                        HdrFtrType hfType = s_convertToHdrFtrType(pszSectionType);

                        if(hfType != FL_HDRFTR_NONE)
                        {
                              const XML_Char* pszID = NULL;
                              pAP->getAttribute("id", pszID);
                              UT_DEBUGMSG(("Populating header/footer header strux \n"));
                              fl_DocSectionLayout* pDocSL = m_pLayout->findSectionForHdrFtr((char*)pszID);
                              UT_ASSERT(pDocSL);
                  
                              // Append a HdrFtrSectionLayout to this DocLayout
                              fl_HdrFtrSectionLayout* pSL = new fl_HdrFtrSectionLayout(hfType, m_pLayout, pDocSL, sdh, pcr->getIndexAP());
                              if (!pSL)
                              {
                                    UT_DEBUGMSG(("no memory for SectionLayout"));
                                    return false;
                              }
                              //
                              // Add the hdrFtr section to the linked list of SectionLayouts
                              //
                              m_pLayout->addHdrFtrSection(pSL);
                              pDocSL->setHdrFtr(hfType, pSL);
                              *psfh = (PL_StruxFmtHandle)pSL;
                              
                              m_pCurrentSL = pSL;
                        }
                        else
                        {
                              UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                              return false;
                        }
                  }
            }
            else
            {
                  // TODO fail?
               UT_DEBUGMSG(("fl_DocListener::populateStrux - m_doc->getAttrProp() failed for structure %d\n",indexAP));
                  return false;
            }
      }
      break;

      case PTX_SectionFootnote:
      case PTX_SectionEndnote:
      {
            bool isFoot = (pcrx->getStruxType() == PTX_SectionFootnote);
            UT_ASSERT(m_pCurrentSL);
            m_bFootnoteInProgress = true;
          fl_SectionLayout * pSL = NULL;
            if(isFoot)
            {
                  UT_DEBUGMSG(("fl_DocListener::populateStrux for 'SectionFootnote'\n"));
                  pSL = (fl_SectionLayout *) m_pCurrentSL->append(sdh, pcr->getIndexAP(),FL_CONTAINER_FOOTNOTE);
            }
            else
            {
                  UT_DEBUGMSG(("fl_DocListener::populateStrux for 'SectionEndnote'\n"));
                  pSL = (fl_SectionLayout *) m_pCurrentSL->append(sdh, pcr->getIndexAP(),FL_CONTAINER_ENDNOTE);
            }
            *psfh = (PL_StruxFmtHandle)pSL;
            m_pCurrentSL = (fl_SectionLayout*)pSL;
            break;
      }

      case PTX_EndFootnote:
      case PTX_EndEndnote:
      {
//
// CurrentSL is a Footnote. Return this and set the m_pCurrentSL to it's 
// container
//
            bool isFoot = (pcrx->getStruxType() == PTX_EndFootnote);
            fl_ContainerLayout * pCL = m_pCurrentSL;
            m_bFootnoteInProgress = false;
            m_bEndFootnoteProcessedInBlock = true;
#if DEBUG
            if(isFoot)
            {
                  UT_DEBUGMSG(("fl_DocListener::populateStrux for 'EndFootnote'\n"));
                  UT_ASSERT(pCL->getContainerType() == FL_CONTAINER_FOOTNOTE);
            }
            else
            {
                  UT_DEBUGMSG(("fl_DocListener::populateStrux for 'EndEndnote'\n"));
                  UT_ASSERT(pCL->getContainerType() == FL_CONTAINER_ENDNOTE);
            }
#endif
            *psfh = (PL_StruxFmtHandle) pCL;
            m_pCurrentSL = (fl_SectionLayout *) static_cast<fl_FootnoteLayout *>(m_pCurrentSL)->getDocSectionLayout();
            fl_BlockLayout * pBL = NULL;
            if(isFoot)
            {
                  fl_FootnoteLayout * pFL = (fl_FootnoteLayout *) pCL;
                  pFL->setFootnoteEndIn();
                  pBL = (fl_BlockLayout *) pFL->getFirstLayout();
            }
            else
            {
                  fl_EndnoteLayout * pEL = (fl_EndnoteLayout *) pCL;
                  pEL->setFootnoteEndIn();
                  pBL = (fl_BlockLayout *) pEL->getFirstLayout();
            }
            UT_ASSERT(pBL);
            if(pBL)
            {
                  pBL->updateEnclosingBlockIfNeeded();
            }
            UT_ASSERT(m_pCurrentSL);
            UT_ASSERT(m_pCurrentSL->getContainerType() == FL_CONTAINER_DOCSECTION);
            break;
      }
      case PTX_SectionTOC:
      {
            UT_ASSERT(m_pCurrentSL);
          fl_SectionLayout * pSL = NULL;
            UT_DEBUGMSG(("fl_DocListener::populateStrux for 'SectionTOC'\n"));
            pSL = (fl_SectionLayout *) m_pCurrentSL->append(sdh, pcr->getIndexAP(),FL_CONTAINER_TOC);
            *psfh = (PL_StruxFmtHandle)pSL;
            m_pCurrentSL = (fl_SectionLayout*)pSL;
            break;
      }

      case PTX_EndTOC:
      {
//
// CurrentSL is a TOC. Return this and set the m_pCurrentSL to it's 
// container
//
            fl_ContainerLayout * pCL = m_pCurrentSL;
#if DEBUG
            UT_DEBUGMSG(("fl_DocListener::populateStrux for 'EndTOC'\n"));
            UT_ASSERT(pCL->getContainerType() == FL_CONTAINER_TOC);
#endif
            *psfh = (PL_StruxFmtHandle) pCL;
            static_cast<fl_TOCLayout *>(pCL)->setTOCEndIn();
            m_pCurrentSL = (fl_SectionLayout *) static_cast<fl_TOCLayout *>(m_pCurrentSL)->getDocSectionLayout();
            break;
      }
      case PTX_SectionHdrFtr:
            // This path is taken on a change of page type. Eg A4 => letter.
      {
         UT_DEBUGMSG(("fl_DocListener::populateStrux for '%s'\n","SectionHdrFtr"));
            PT_AttrPropIndex indexAP = pcr->getIndexAP();
            const PP_AttrProp* pAP = NULL;
            if (m_pDoc->getAttrProp(indexAP, &pAP) && pAP)
            {
                  const XML_Char* pszSectionType = NULL;
                  pAP->getAttribute("type", pszSectionType);
                  if (
                        !pszSectionType
                        || (0 == UT_strcmp(pszSectionType, "doc"))
                        )
                  {
                        UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  }
                  else
                  {
                        HdrFtrType hfType = s_convertToHdrFtrType(pszSectionType);
                        if(hfType != FL_HDRFTR_NONE)
                        {
                              const XML_Char* pszID = NULL;
                              pAP->getAttribute("id", pszID);

                              fl_DocSectionLayout* pDocSL = m_pLayout->findSectionForHdrFtr((char*)pszID);
                              if (pDocSL == NULL)
                              {
                                    UT_DEBUGMSG(("Could not find HeaderFooter %s\n",(char*)pszID));
                                    return false;
                              }
                  
                              // Append a HdrFtrSectionLayout to this DocLayout
                              fl_HdrFtrSectionLayout* pSL = new fl_HdrFtrSectionLayout(hfType, m_pLayout, pDocSL, sdh, pcr->getIndexAP());
                              if (!pSL)
                              {
                                    UT_DEBUGMSG(("no memory for SectionLayout"));
                                    return false;
                              }
                              //
                              // Add the hdrFtr section to the linked list of SectionLayouts
                              //
                              m_pLayout->addHdrFtrSection(pSL);
                              pDocSL->setHdrFtr(hfType, pSL);
                              *psfh = (PL_StruxFmtHandle)pSL;
                              UT_DEBUGMSG(("Sevior: HeaderFooter created %x \n",pSL));
                              
                              m_pCurrentSL = pSL;
                        }
                        else
                        {
                              return false;
                        }
                        break;
                  }
            }
            UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
      }
      case PTX_Block:
      {
            UT_DEBUGMSG(("SEVIOR: Doing populate block sdh %x \n",sdh));
            if(m_pCurrentSL == NULL)
            {
                  m_pDoc->miniDump(sdh,6);
            }
            UT_ASSERT(m_pCurrentSL);
//
// Look if we're inside a table. If so append this block to a cell.
//
            fl_ContainerLayout*     pCL = NULL;
            fl_ContainerLayout * pCon = getTopContainerLayout();
            if((pCon != NULL)  && (m_pCurrentSL->getContainerType() != FL_CONTAINER_FOOTNOTE) && (m_pCurrentSL->getContainerType() != FL_CONTAINER_ENDNOTE))
            {
                  if(pCon->getContainerType() != FL_CONTAINER_CELL)
                  {
#ifdef DEBUG
                  m_pDoc->miniDump(sdh,6);
#endif

                        UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                        return false;
                  }
                  fl_CellLayout * pCell = (fl_CellLayout *) pCon;
                  UT_DEBUGMSG(("SEVIOR: Appending block to cell %x \n",pCell));
                  // Append a new BlockLayout to this cell

                  pCL = pCell->append(sdh, pcr->getIndexAP(),FL_CONTAINER_BLOCK);
                  if (!pCL)
                  {
                        UT_DEBUGMSG(("no memory for BlockLayout"));
                        return false;
                  }
                  // BUGBUG: this is *not* thread-safe, but should work for now
                  if (m_bScreen)
                  {
                        UT_uint32 reason =  0;
                        if( m_pLayout->getAutoSpellCheck())
                        {
                              reason = (UT_uint32) FL_DocLayout::bgcrSpelling;
                        }
                        m_pLayout->queueBlockForBackgroundCheck(reason, (fl_BlockLayout *)pCL,true);
                  }
            }
            else
            {
                  UT_return_val_if_fail( m_pCurrentSL,false );
                  pCL = m_pCurrentSL->append(sdh, pcr->getIndexAP(),FL_CONTAINER_BLOCK);
                  if (!pCL)
                  {
                        UT_DEBUGMSG(("no memory for BlockLayout"));
                        return false;
                  }

                  // BUGBUG: this is *not* thread-safe, but should work for now
                  if (m_bScreen)
                  {
                        UT_uint32 reason =  0;
                        if( m_pLayout->getAutoSpellCheck())
                        {
                              reason = (UT_uint32) FL_DocLayout::bgcrSpelling;
                        }
                        m_pLayout->queueBlockForBackgroundCheck(reason, (fl_BlockLayout *)pCL,true);
                  }
            }

            *psfh = (PL_StruxFmtHandle)pCL;
            if(pCL->getLastContainer()==NULL)
            {
                  if(pCL->getSectionLayout()->getType() != FL_SECTION_HDRFTR && pCL->getPrev() != NULL)
                  {
                        UT_DEBUGMSG(("In DocListner no LastLine in block append. Fixing this now \n"));
                        UT_DEBUGMSG(("getPrev = %d this = %d \n",pCL->getPrev(),pCL));
                        pCL->format();
                  }
            }

      }
      break;
      case PTX_SectionTable:
      {
            UT_ASSERT(m_pCurrentSL);
            
            // Append a new TableLayout to the SectionLayout or CellLayout
            
            fl_ContainerLayout * pCon = getTopContainerLayout();
            fl_ContainerLayout*     pCL = NULL;
            UT_DEBUGMSG(("!!!!Appending Table \n"));
            if(m_pCurrentSL->getHdrFtrLayout())
            {
                  UT_DEBUGMSG(("Appending Table into HdrFtr %x \n",m_pCurrentSL->getHdrFtrLayout()));
            }
            if(pCon == NULL)
            {
                  pCL = m_pCurrentSL->append(sdh, pcr->getIndexAP(),FL_CONTAINER_TABLE);
                  if (!pCL)
                  {
                        UT_DEBUGMSG(("no memory for TableLayout"));
                        return false;
                  }
            }
            else
            {
                  fl_CellLayout * pCell = (fl_CellLayout *) pCon;
                  pCL = pCell->append(sdh,pcr->getIndexAP(),FL_CONTAINER_TABLE);
            }
            pushContainerLayout(pCL);
            *psfh = (PL_StruxFmtHandle)pCL;
//
// Don't layout until a endTable strux
//
            m_pDoc->setDontImmediatelyLayout(true);
      }
      break;
      case PTX_SectionFrame:
      {
            UT_ASSERT(m_pCurrentSL);
            UT_ASSERT(m_pCurrentSL->getContainerType() == FL_CONTAINER_DOCSECTION);
            fl_ContainerLayout*     pCL = NULL;
//
// Look to see if we're in a table.
//
            fl_ContainerLayout * pCon = getTopContainerLayout();
            if((pCon != NULL))
            {
                  if(pCon->getContainerType() == FL_CONTAINER_CELL)
                  {
                        fl_ContainerLayout * pCL = pCon->append(sdh,pcr->getIndexAP(),FL_CONTAINER_FRAME);
                        m_pCurrentSL = static_cast<fl_SectionLayout *>(pCL);
                        *psfh = (PL_StruxFmtHandle)pCL;
                        break;
                  }
#ifdef DEBUG
                  m_pDoc->miniDump(sdh,6);
#endif
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
            }

            // Append a new FrameLayout to the SectionLayout


            UT_DEBUGMSG(("!!!!Appending Frame \n"));
            pCL = m_pCurrentSL->append(sdh, pcr->getIndexAP(),FL_CONTAINER_FRAME);
            if (!pCL)
            {
                  UT_DEBUGMSG(("no memory for TableLayout"));
                  return false;
            }
            m_pCurrentSL = static_cast<fl_SectionLayout *>(pCL);
            *psfh = (PL_StruxFmtHandle)pCL;
      }
      break;
      case PTX_EndFrame:
      {
            UT_ASSERT(m_pCurrentSL);
            UT_ASSERT(m_pCurrentSL->getContainerType() == FL_CONTAINER_FRAME);
            // Append a new FrameLayout to the SectionLayout

            fl_ContainerLayout*     pCL = NULL;
            UT_DEBUGMSG(("!!!!Appending EndFrame \n"));
            pCL = m_pCurrentSL;
            *psfh = (PL_StruxFmtHandle)pCL;
            m_pCurrentSL = static_cast<fl_SectionLayout *>(pCL->myContainingLayout());
            if(m_pCurrentSL->getContainerType() == FL_CONTAINER_CELL)
            {
                  m_pCurrentSL = static_cast<fl_CellLayout *>(m_pCurrentSL)->getDocSectionLayout();
            }
            UT_ASSERT(m_pCurrentSL->getContainerType() == FL_CONTAINER_DOCSECTION);
      }
      break;

      case PTX_SectionCell:
      {
            UT_ASSERT(m_pCurrentSL);
            UT_DEBUGMSG(("!!!! Append Section Cell \n"));
            
            // Append a new CallLayout to the Current TableLayout
            fl_ContainerLayout * pCon = getTopContainerLayout();
            if(pCon->getContainerType() != FL_CONTAINER_TABLE)
            {
#ifdef DEBUG
                  m_pDoc->miniDump(sdh,6);
#endif
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  return false;
            }
            fl_TableLayout * pTable = (fl_TableLayout *) pCon;
            if(pTable->getHdrFtrLayout())
            {
                  UT_DEBUGMSG(("Appending a Cell to a Table in a HDrFtr %x \n",pTable->getHdrFtrLayout()));
            }
            fl_ContainerLayout*     pCL = pTable->append(sdh, pcr->getIndexAP(),FL_CONTAINER_CELL);
            UT_DEBUGMSG(("SEVIOR: Appending Cell: layout is %x \n",pCL));
            pTable->attachCell(pCL);
            if (!pCL)
            {
                  UT_DEBUGMSG(("no memory for CellLayout"));
                  return false;
            }
            pushContainerLayout(pCL);
            *psfh = (PL_StruxFmtHandle)pCL;
      }
      break;
      case PTX_EndTable:
      {
            UT_ASSERT(m_pCurrentSL);
            fl_ContainerLayout *  pCon = popContainerLayout();
            UT_DEBUGMSG(("!!!! Append End Table \n"));
            if(pCon->getContainerType() != FL_CONTAINER_TABLE)
            {
#ifndef NDEBUG
                  m_pDoc->miniDump(sdh,6);
#endif
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  return false;
            }
            *psfh = (PL_StruxFmtHandle)pCon;
            fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pCon);
            UT_DEBUGMSG(("SEVIOR: End table in doclistener \n"));
            pTL->setDirty();
            pTL->setEndTableIn();
            pCon = getTopContainerLayout();
            if(pCon == NULL)
            {
//
// Reached the top of the stack. Allow the table layout now.
//
                  if(!holdTableLayout())
                  {
                        m_pDoc->setDontImmediatelyLayout(false);
                  }
                  pTL->format();
            }
      }
      break;
      case PTX_EndCell:
      {
            UT_ASSERT(m_pCurrentSL);
            UT_DEBUGMSG(("!!!! Append End Cell \n"));
            fl_ContainerLayout *  pCon = popContainerLayout();
            UT_ASSERT(pCon);
            if(pCon == NULL)
            {
#ifndef NDEBUG
                  m_pDoc->miniDump(sdh,12);
#endif
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  return false;
            }
            if(pCon->getContainerType() != FL_CONTAINER_CELL)
            {
#ifndef NDEBUG
                  m_pDoc->miniDump(sdh,12);
#endif
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  return false;
            }
            *psfh = (PL_StruxFmtHandle) pCon;
      }
      break;
                  
      default:
            UT_ASSERT(0);
            return false;
      }

      if (0 == m_iGlobCounter)
      {
#ifndef UPDATE_LAYOUT_ON_SIGNAL
            m_pLayout->updateLayout();
#endif
      }
      
      return true;
}

/*!
 * Push the given ContainerLayout onto the top of the stack.
 */
00832 void fl_DocListener::pushContainerLayout(fl_ContainerLayout * pCL)
{
      m_sLastContainerLayout.push((void *) pCL);
}

/*!
 * View the topmost containerLayout on the stack.
 */
00840 fl_ContainerLayout * fl_DocListener::getTopContainerLayout(void)
{
      static fl_ContainerLayout * pCL;
      m_sLastContainerLayout.viewTop((void**)&pCL);
      return pCL;
}

/*!
 * Pop the most recent ContainerLayout off the top of the stack.
 */
00850 fl_ContainerLayout * fl_DocListener::popContainerLayout(void)
{
      static fl_ContainerLayout * pCL;
      m_sLastContainerLayout.pop((void**)&pCL);
      return pCL;
}

/*!
 * Change a strux or span.
 */
00860 bool fl_DocListener::change(PL_StruxFmtHandle sfh,
                                          const PX_ChangeRecord * pcr)
{
      //UT_DEBUGMSG(("fl_DocListener::change\n"));
      bool bResult = false;
      AV_ChangeMask chgMask = AV_CHG_NONE;
      
      switch (pcr->getType())
      {
      case PX_ChangeRecord::PXT_GlobMarker:
      {
            UT_ASSERT(sfh == 0);                                        // globs are not strux-relative
            const PX_ChangeRecord_Glob * pcrg = static_cast<const PX_ChangeRecord_Glob *> (pcr);
            switch (pcrg->getFlags())
            {
            default:
            case PX_ChangeRecord_Glob::PXF_Null:                  // not a valid glob type
                  UT_ASSERT(0);
                  bResult = false;
                  goto finish_up;
                        
            case PX_ChangeRecord_Glob::PXF_MultiStepStart:
                  m_iGlobCounter++;
                  bResult = true;
                  goto finish_up;
                  
            case PX_ChangeRecord_Glob::PXF_MultiStepEnd:
                  m_iGlobCounter--;
                  bResult = true;
                  goto finish_up;
                        
            case PX_ChangeRecord_Glob::PXF_UserAtomicStart: // TODO decide what (if anything) we need
            case PX_ChangeRecord_Glob::PXF_UserAtomicEnd:   // TODO to do here.
                  bResult = true;
                  goto finish_up;
            }
      }
                  
      case PX_ChangeRecord::PXT_InsertSpan:
      {
            const PX_ChangeRecord_Span * pcrs = static_cast<const PX_ChangeRecord_Span *> (pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            if(pL->getType() != PTX_Block)
            {
                  m_pDoc->miniDump(pL->getStruxDocHandle(),6);
            }
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  pHdr->bl_doclistener_insertSpan(pCL, pcrs);
            }
            else
            {
                  bResult = pCLSL->bl_doclistener_insertSpan(pCL, pcrs);
            }
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_DeleteSpan:
      {
            const PX_ChangeRecord_Span * pcrs = static_cast<const PX_ChangeRecord_Span *> (pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_deleteSpan(pCL, pcrs);
            }
            else
                  bResult = pCLSL->bl_doclistener_deleteSpan(pCL, pcrs);
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_ChangeSpan:
      {
            chgMask = AV_CHG_FMTCHAR;
            const PX_ChangeRecord_SpanChange * pcrsc = static_cast<const PX_ChangeRecord_SpanChange *>(pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_changeSpan(pCL, pcrsc);
            }
            else
                  bResult = pCLSL->bl_doclistener_changeSpan(pCL, pcrsc);
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_InsertFmtMark:
      {
            const PX_ChangeRecord_FmtMark * pcrfm = static_cast<const PX_ChangeRecord_FmtMark *>(pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            xxx_UT_DEBUGMSG(("DocListener: InsertFmtMark strux type = %d \n",pL->getType()));
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_insertFmtMark(pCL, pcrfm);
            }
            else
                  bResult = pCLSL->bl_doclistener_insertFmtMark(pCL, pcrfm);
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_DeleteFmtMark:
      {
            const PX_ChangeRecord_FmtMark * pcrfm = static_cast<const PX_ChangeRecord_FmtMark *>(pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_deleteFmtMark(pCL, pcrfm);
            }
            else
                  bResult = pCLSL->bl_doclistener_deleteFmtMark(pCL, pcrfm);
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_ChangeFmtMark:
      {
            const PX_ChangeRecord_FmtMarkChange * pcrfmc = static_cast<const PX_ChangeRecord_FmtMarkChange *>(pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_changeFmtMark(pCL, pcrfmc);
            }
            else
                  bResult = pCLSL->bl_doclistener_changeFmtMark(pCL, pcrfmc);
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_DeleteStrux:
      {
            const PX_ChangeRecord_Strux * pcrx = static_cast<const PX_ChangeRecord_Strux *> (pcr);

            switch (pcrx->getStruxType())
            {
            case PTX_Section:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_Section);
                  fl_DocSectionLayout * pSL = static_cast<fl_DocSectionLayout *>(pL);
                  bResult = pSL->doclistener_deleteStrux(pcrx);
                  goto finish_up;
            }
            case PTX_Block:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_Block);
                  fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                  fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                  if(pCLSL->getType() == FL_SECTION_SHADOW)
                  {
                        fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                        bResult = pHdr->bl_doclistener_deleteStrux(pCL, pcrx);
                  }
                  else
                        bResult = pCLSL->bl_doclistener_deleteStrux(pCL, pcrx);
                  goto finish_up;
            }
            case PTX_SectionHdrFtr:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionHdrFtr);
                  fl_HdrFtrSectionLayout * pSL = static_cast<fl_HdrFtrSectionLayout *>(pL);
//
// Nuke the HdrFtrSectionLayout and the shadows associated with it.
//
                  pSL->doclistener_deleteStrux(pcrx); 
                  m_pLayout->updateLayout();
                  goto finish_up;
            }
            case PTX_SectionTOC:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionTOC);
                  fl_TOCLayout * pFL = static_cast<fl_TOCLayout *>(pL);
                  pFL->doclistener_deleteStrux(pcrx);
                  goto finish_up;
            }
            case PTX_SectionFootnote:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionFootnote);
                  fl_FootnoteLayout * pFL = (fl_FootnoteLayout *) pL;
                  pFL->doclistener_deleteStrux(pcrx);
                  goto finish_up;
            }
            case PTX_SectionEndnote:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionEndnote);
                  fl_EndnoteLayout * pEL = (fl_EndnoteLayout *) pL;
                  pEL->doclistener_deleteStrux(pcrx);
                  goto finish_up;
            }
            case PTX_SectionTable:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionTable);
                  fl_TableLayout * pTL = (fl_TableLayout *) pL;
                  pTL->doclistener_deleteStrux(pcrx);
                  goto finish_up;
            }
            case PTX_SectionCell:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionCell);
                  fl_CellLayout * pCellL = (fl_CellLayout *) pL;
                  pCellL->doclistener_deleteStrux(pcrx);
                  goto finish_up;
            }
            case PTX_SectionFrame:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionFrame);
                  fl_FrameLayout * pFrameL = (fl_FrameLayout *) pL;
                  pFrameL->doclistener_deleteStrux(pcrx);
                  goto finish_up;
            }
            case PTX_EndFrame:
            {
                  goto finish_up;
            }
            case PTX_EndTable:
            {
                  goto finish_up;
            }
            case PTX_EndCell:
            {
                  goto finish_up;
            }
            case PTX_EndTOC:
            {
                  goto finish_up;
            }
            case PTX_EndFootnote:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionFootnote);
                  fl_FootnoteLayout * pFL = static_cast<fl_FootnoteLayout *>(pL);
                  pFL->doclistener_deleteEndEmbed(pcrx);

                  goto finish_up;
            }
            case PTX_EndEndnote:
            {
                  fl_Layout * pL = (fl_Layout *)sfh;
                  UT_ASSERT(pL->getType() == PTX_SectionEndnote);
                  fl_EndnoteLayout * pEL = static_cast<fl_EndnoteLayout *>( pL);
                  pEL->doclistener_deleteEndEmbed(pcrx);

                  goto finish_up;
            }
            default:
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  bResult = false;
                  goto finish_up;
            }
      }
                              
      case PX_ChangeRecord::PXT_ChangeStrux:
      {
            const PX_ChangeRecord_StruxChange * pcrxc = static_cast<const PX_ChangeRecord_StruxChange *> (pcr);

            fl_Layout * pL = (fl_Layout *)sfh;

            // TODO getOldIndexAP() is only intended for use by the document.
            // TODO this assert is probably wrong. --- BUT EVERYTIME IT HAS
            // TODO GONE OFF, I'VE FOUND A BUG, SO MAYBE WE SHOULD KEEP IT :-)
            // UT_ASSERT(pL->getAttrPropIndex() == pcrxc->getOldIndexAP());
            // UT_ASSERT(pL->getAttrPropIndex() != pcr->getIndexAP());

            switch (pL->getType())
            {
            case PTX_Section:
            case PTX_SectionEndnote:
            case PTX_SectionFootnote:
            {
                  fl_DocSectionLayout* pSL = static_cast<fl_DocSectionLayout*>(pL);
                  
                  PT_AttrPropIndex indexAP = pcr->getIndexAP();
                  const PP_AttrProp* pAP = NULL;
                  
                  bool bres = (m_pDoc->getAttrProp(indexAP, &pAP) && pAP);
                  UT_ASSERT(bres);
                  PL_StruxDocHandle sdh = pL->getStruxDocHandle();
      
                  const XML_Char* pszSectionType = NULL;
                  pAP->getAttribute("type", pszSectionType);
                  //
                  // OK Sevior adds code to actually change a 
                  // sectionlayout to
                  // a header/footer layout
                  //
                  // Strategy: Collapse all the blocks in this section.
                  // create a header/footer sectionlayout ala populate_strux
                  // transfer the blocks in this sectionlayout to the
                  // new header/footer and format just the shadows
                  //
                  HdrFtrType hfType = s_convertToHdrFtrType(pszSectionType);
                  if(hfType != FL_HDRFTR_NONE)
                  {
                        //
                        //  OK first we need a previous section with a
                        //  matching ID
                        //
                        const XML_Char* pszID = NULL;
                        pAP->getAttribute("id", pszID);

                        fl_DocSectionLayout* pDocSL = m_pLayout->findSectionForHdrFtr((char*)pszID);
                        UT_ASSERT(pDocSL); 
                          
                        // Append a HdrFtrSectionLayout to this DocLayout
                        fl_HdrFtrSectionLayout* pHeadSL = new fl_HdrFtrSectionLayout(hfType, m_pLayout, pDocSL, sdh, pcr->getIndexAP());
                        if (!pHeadSL)
                        {
                              UT_DEBUGMSG(("no memory for SectionLayout"));
                              return false;
                        }
                        //
                        // Add the hdrFtr section to the linked list of SectionLayouts
                        //
                        m_pLayout->addHdrFtrSection(pHeadSL);
                        //
                        // Set the pointers to this header/footer
                        //
                        pDocSL->setHdrFtr(hfType, pHeadSL);

                        // OK now clean up the old section and transfer
                        // blocks into this header section.
                        
                        pHeadSL->changeIntoHdrFtrSection(pSL);

                        bResult = true;
                        goto finish_up;
                  }
                  if(pSL->getType() == FL_SECTION_DOC)
                  {
                        fl_DocSectionLayout * pDSL = (fl_DocSectionLayout *) pSL;
                        m_pLayout->changeDocSections(pcrxc,pDSL);
                        bResult = true;
                        goto finish_up;
                  }
                  bResult = pSL->doclistener_changeStrux(pcrxc);
                  goto finish_up;
            }
            
            case PTX_Block:
            {
                  // among other things, this is the case where style
                  // definitions vere changed and we are updating the block;
                  // we need to notify view listeners for both block and
                  // char fmt changes (i.e., we want the font combo updated,
                  // etc.) This is not ideal, we should probably have some
                  // way of telling the change includes a style change
                  // Tomas, June 7, 2003
                  
                  chgMask = AV_CHG_FMTBLOCK | AV_CHG_FMTCHAR;
                  fl_SectionLayout * pCL = static_cast<fl_SectionLayout *>(pL);
                  fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                  if(pCLSL->getType() == FL_SECTION_SHADOW)
                  {
                        fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                        bResult = pHdr->bl_doclistener_changeStrux( pCL, pcrxc);
                  }
                  else 
                        bResult = pCLSL->bl_doclistener_changeStrux(pCL, pcrxc);
                  goto finish_up;
            }
            case PTX_SectionHdrFtr:
            {
//
// OK A previous "insertStrux" has created a HdrFtrSectionLayout but it
// Doesn't know if it's a header or a footer or the DocSection and hences pages
// It associated with. Tell it now.
//
                  fl_HdrFtrSectionLayout* pHFSL = static_cast<fl_HdrFtrSectionLayout*>(pL);
                  
                  PT_AttrPropIndex indexAP = pcr->getIndexAP();
//
// Save this new index to the Attributes/Properties of this section in the
// HdrFtrSection Class
//
                  pHFSL->setAttrPropIndex(pcrxc->getIndexAP());
                  const PP_AttrProp* pHFAP = NULL;
                  
                  bool bres = (m_pDoc->getAttrProp(indexAP, &pHFAP) && pHFAP);
                  UT_ASSERT(bres);
      
                  const XML_Char* pszHFSectionType = NULL;
                  pHFAP->getAttribute("type", pszHFSectionType);
                  //
            // Look for type of Hdr/Ftr
                  //
                  HdrFtrType hfType = s_convertToHdrFtrType(pszHFSectionType);
                  if(hfType !=  FL_HDRFTR_NONE )
                  {
                        //
                        //  OK now we need a previous section with a
                        //  matching ID
                        //
                        const XML_Char* pszHFID = NULL;
                        pHFAP->getAttribute("id", pszHFID);

                        fl_DocSectionLayout* pDocSL = m_pLayout->findSectionForHdrFtr((char*)pszHFID);
                        
                        UT_ASSERT(pDocSL); 
                          
                        // Set the Headerness and overall docSectionLayout
                        //
                        pHFSL->setDocSectionLayout(pDocSL);
                        pHFSL->setHdrFtr(hfType);
                        //
                        // Set the pointers to this header/footer
                        //
                        pDocSL->setHdrFtr(hfType, pHFSL);

                        // OK now Format this and attach it to it's pages
                        
                        pHFSL->format();

                        bResult = true;
                        goto finish_up;
                  }
                  UT_DEBUGMSG(("SEVIOR: Unknown change record on a SectionHdrFtr strux \n"));
                  UT_DEBUGMSG(("SEVIOR: Most like we're undoing an Insert HdrFtr. Carry on! \n"));
                  bResult = true;
                  goto finish_up;
            }
        case PTX_SectionTable:
            {
                  fl_TableLayout * pTL = (fl_TableLayout *) pL;
                  UT_ASSERT(pTL->getContainerType() == FL_CONTAINER_TABLE);
                  bResult = pTL->doclistener_changeStrux(pcrxc);
                  goto finish_up;
            }
            case PTX_SectionCell:
            {
                  fl_CellLayout * pCL = (fl_CellLayout *) pL;
                  UT_ASSERT(pCL->getContainerType() == FL_CONTAINER_CELL);
                  bResult = pCL->doclistener_changeStrux(pcrxc);
                  goto finish_up;
            }
            case PTX_SectionFrame:
            {
                  fl_FrameLayout * pFL = (fl_FrameLayout *) pL;
                  UT_ASSERT(pFL->getContainerType() == FL_CONTAINER_FRAME);
                  bResult = pFL->doclistener_changeStrux(pcrxc);
                  goto finish_up;
            }
            case PTX_SectionTOC:
            {
                  fl_TOCLayout * pTOCL = (fl_TOCLayout *) pL;
                  UT_ASSERT(pTOCL->getContainerType() == FL_CONTAINER_TOC);
                  bResult = pTOCL->doclistener_changeStrux(pcrxc);
                  goto finish_up;
            }
            default:
            {
                  UT_ASSERT(0);
                  bResult = false;
                  goto finish_up;
            }
            }
      }

      case PX_ChangeRecord::PXT_InsertStrux:
      {
            UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
            bResult = false;
            goto finish_up;
      }
      case PX_ChangeRecord::PXT_InsertObject:
      {
            const PX_ChangeRecord_Object * pcro = static_cast<const PX_ChangeRecord_Object *> (pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_insertObject(pCL, pcro);
            }
            else
                  bResult = pCLSL->bl_doclistener_insertObject(pCL, pcro);

            // if the inserted object is a bookmark, we have to notify TOCs of bookmark change in case
            // any of them is restricted by the given bookmark
            if(pcro->getObjectType() == PTO_Bookmark)
            {
                  if(pL->getType() == PTX_Block)
                  {
                        fl_BlockLayout * pBL = static_cast<fl_BlockLayout *>(pL);
                        fp_Run * pRun = pBL->findRunAtOffset(pcro->getBlockOffset());
                        if(pRun && pRun->getType() == FPRUN_BOOKMARK)
                        {
                              fp_BookmarkRun * pB = static_cast<fp_BookmarkRun*>(pRun);

                              // only do this when the end-object is inserted ...
                              if(!pB->isStartOfBookmark())
                                    m_pLayout->updateTOCsOnBookmarkChange(pB->getName());
                        }
                        else if(pRun && pRun->getType() != FPRUN_BOOKMARK)
                        {
                              UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
                        }
                  }
            }
            
            goto finish_up;
      }
      case PX_ChangeRecord::PXT_DeleteObject:
      {
            const PX_ChangeRecord_Object * pcro = static_cast<const PX_ChangeRecord_Object *> (pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);

            // if the deleted object is a bookmark, we have to notify TOCs of bookmark change in case
            // any of them is restricted by the given bookmark;
            //
            // this has to be done in two steps: before the layout is updated, we have to find out the
            // name of the bookmark; after the layout is updated, we need to notify the TOCs.
            UT_UTF8String sBookmark;
            
            if(pcro->getObjectType() == PTO_Bookmark)
            {
                  if(pL->getType() == PTX_Block)
                  {
                        fl_BlockLayout * pBL = static_cast<fl_BlockLayout *>(pL);
                        fp_Run * pRun = pBL->findRunAtOffset(pcro->getBlockOffset());
                        if(pRun && pRun->getType() == FPRUN_BOOKMARK)
                        {
                              fp_BookmarkRun * pB = static_cast<fp_BookmarkRun*>(pRun);

                              // only do this when the end-object is deleted ...
                              // (in case of deletion, this is an arbitrary choice)
                              if(!pB->isStartOfBookmark())
                                    sBookmark = pB->getName();
                        }
                        else if(pRun && pRun->getType() != FPRUN_BOOKMARK)
                        {
                              UT_ASSERT_HARMLESS( UT_SHOULD_NOT_HAPPEN );
                        }
                  }
            }

            // now we can proceed to delete the object representation ...
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_deleteObject(pCL, pcro);
            }
            else
                  bResult = pCLSL->bl_doclistener_deleteObject(pCL, pcro);

            // now notify TOCs if necessary
            if(sBookmark.size())
                  m_pLayout->updateTOCsOnBookmarkChange(sBookmark.utf8_str());

            goto finish_up;
      }

      case PX_ChangeRecord::PXT_ChangeObject:
      {
            const PX_ChangeRecord_ObjectChange * pcroc = static_cast<const PX_ChangeRecord_ObjectChange *> (pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            if(pCLSL->getType() == FL_SECTION_SHADOW)
            {
                  fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                  bResult = pHdr->bl_doclistener_changeObject(pCL, pcroc);
            }
            else
                  bResult = pCLSL->bl_doclistener_changeObject(pCL, pcroc);
            goto finish_up;
      }

      case PX_ChangeRecord::PXT_ChangePoint:
      {
            FV_View* pView = m_pLayout->getView();
            if (pView && pView->isActive())
                  pView->_setPoint(pcr->getPosition());
            goto finish_up;
      }
      case PX_ChangeRecord::PXT_ListUpdate:
      {
            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            pCL->listUpdate();
            goto finish_up;

      }
      case PX_ChangeRecord::PXT_StopList:
      {
            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_BlockLayout * pCL = static_cast<fl_BlockLayout *>(pL);
            pCL->StopListInBlock();
            goto finish_up;
      }
      case PX_ChangeRecord::PXT_UpdateField:
      {
            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            pCL->format();
            FV_View* pView = m_pLayout->getView();
            pView->updateScreen();
            goto finish_up;
      }
      case PX_ChangeRecord::PXT_RemoveList:
      {
            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_BlockLayout * pCL = static_cast<fl_BlockLayout *>(pL);
            pCL->m_bStopList = true;
            pCL->_deleteListLabel();
            pCL->m_pAutoNum = NULL;
            pCL->m_bListItem = false;
            pCL->m_bStopList = false;
            goto finish_up;
      }
      case PX_ChangeRecord::PXT_UpdateLayout:
      {
            fl_Layout * pL = (fl_Layout *)sfh;
            UT_ASSERT(pL->getType() == PTX_Block);
            fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            pCL->getDocLayout()->updateLayout();
            FV_View * pView = pCL->getDocLayout()->getView();
            if(pView)
            {
                  pView->notifyListeners(AV_CHG_HDRFTR);
            }

            goto finish_up;
      }
#if 0 //###TF
      case PX_ChangeRecord::PXT_InsertBookmark:
      {
            const PX_ChangeRecord_Bookmark * pcrfm = static_cast<const PX_ChangeRecord_Bookmark *>(pcr);

            fl_Layout * pL = (fl_Layout *)sfh;
            UT_DEBUGMSG(("DocListener: InsertBookmark strux type = %d \n",pL->getType()));
            //UT_ASSERT(pL->getType() == PTX_Block);
            //fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
            //fl_SectionLayout* pCLSL = pCL->getSectionLayout();
            //if(pCLSL->getType() == FL_SECTION_SHADOW)
            //{
            //    fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
            //    bResult = pHdr->bl_doclistener_insertFmtMark(pCL, pcrfm);
            //}
            //else
            //    bResult = pCLSL->bl_doclistener_insertFmtMark(pCL, pcrfm);
            goto finish_up;
      }
#endif
      
      default:
      {
            UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
            bResult = false;
            goto finish_up;
      }
      }

 finish_up:
      if (0 == m_iGlobCounter)
      {
#ifndef UPDATE_LAYOUT_ON_SIGNAL
            m_pLayout->updateLayout();
#endif
      }

      // need to make view to notify its various listeners to update
      if(chgMask != AV_CHG_NONE)
      {
            UT_return_val_if_fail(getLayout() && getLayout()->getView(),bResult);
            if (m_bCacheChanges)
            {
                  m_chgMaskCached |= chgMask;
            }
            else
            {
                  UT_return_val_if_fail(getLayout() && getLayout()->getView(),bResult);
                  // first of all, increase view tick, so that the view's
                  // property caches are invalidated ...
                  getLayout()->getView()->incTick();
                  fl_ContainerLayout * pCL = (fl_ContainerLayout *)sfh;
                  bool doNotify = true;
                  if(pCL->isCollapsed())
                  {
                        doNotify = false;
                  }
                  if(doNotify)
                  {
                        UT_DEBUGMSG(("Doing view notification \n"));
                        getLayout()->getView()->notifyListeners(chgMask);
                  }
                  else
                  {
                        m_chgMaskCached |= chgMask;
                  }
            }
      }
      
      return bResult;
}

void fl_DocListener::deferNotifications(void)
{
      m_bCacheChanges = true;
      m_chgMaskCached = AV_CHG_NONE;
}

void fl_DocListener::processDeferredNotifications(void)
{
      if (m_chgMaskCached != AV_CHG_NONE)
      {
            if (getLayout() && getLayout()->getView())
            {
                  // first of all, increase view tick, so that the view's
                  // property caches are invalidated ...
                  getLayout()->getView()->incTick();
                  getLayout()->getView()->notifyListeners(m_chgMaskCached);
            }
            m_chgMaskCached = AV_CHG_NONE;
      }
      m_bCacheChanges = false;
}


/*!
 */
bool fl_DocListener::insertStrux(PL_StruxFmtHandle sfh,
                                                 const PX_ChangeRecord * pcr,
                                                 PL_StruxDocHandle sdh,
                                                 PL_ListenerId lid,
                                                 void (* pfnBindHandles)(PL_StruxDocHandle sdhNew,
                                                                                     PL_ListenerId lid,
                                                                                     PL_StruxFmtHandle sfhNew))
{
      UT_DEBUGMSG(("fl_DocListener::insertStrux at pos %d \n",pcr->getPosition()));
      UT_return_val_if_fail( sdh && pcr, false );
      UT_ASSERT(pcr->getType() == PX_ChangeRecord::PXT_InsertStrux);
      
      const PX_ChangeRecord_Strux * pcrx = static_cast<const PX_ChangeRecord_Strux *> (pcr);
#if DEBUG
#if 1
      if(pcrx->getStruxType() == PTX_Block)
      {
            UT_DEBUGMSG(("Inserting Block strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_Section)
      {
            UT_DEBUGMSG(("Inserting Section strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_SectionFootnote)
      {
            UT_DEBUGMSG(("Inserting SectionFootnote strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_EndFootnote)
      {
            UT_DEBUGMSG(("Inserting EndFootnote strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_SectionTOC)
      {
            UT_DEBUGMSG(("Inserting SectionTOC strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_EndTOC)
      {
            UT_DEBUGMSG(("Inserting EndToc strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_SectionEndnote)
      {
            UT_DEBUGMSG(("Inserting SectionEndnote strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_EndEndnote)
      {
            UT_DEBUGMSG(("Inserting EndEndnote strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_SectionTable)
      {
            UT_DEBUGMSG(("Inserting SectionTable strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_EndTable)
      {
            UT_DEBUGMSG(("Inserting EndTable strux at pos %d \n",pcr->getPosition()));
            m_pDoc->miniDump(sdh,8);

      }
      else if(pcrx->getStruxType() == PTX_SectionCell)
      {
            UT_DEBUGMSG(("Inserting Cell strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_EndCell)
      {
            UT_DEBUGMSG(("Inserting EndCell strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_SectionFrame)
      {
            UT_DEBUGMSG(("Inserting Frame strux at pos %d \n",pcr->getPosition()));
      }
      else if(pcrx->getStruxType() == PTX_EndFrame)
      {
            UT_DEBUGMSG(("Inserting EndFrame strux at pos %d \n",pcr->getPosition()));
      }
#endif
#endif
      fl_Layout * pL = (fl_Layout *)sfh;
      xxx_UT_DEBUGMSG(("Previous strux %x type %d \n",pL, pL->getType()));
      xxx_UT_DEBUGMSG(("Insert strux type %d \n",pcrx->getStruxType()));
      switch (pL->getType())                    // see what the immediately prior strux is.
      {
      case PTX_Section:          // the immediately prior strux is a section.
      case PTX_SectionHdrFtr:    //  ... or a HdrFtr.
      case PTX_SectionFootnote:  //  ... or a Footnote.
      case PTX_SectionEndnote:  //  ... or a Endnote.
    {
            switch (pcrx->getStruxType()) // see what we are inserting.
            {
            case PTX_Section:                   // we are inserting a section.
            case PTX_SectionHdrFtr:             //  ... or a HdrFtr section.
            case PTX_SectionFootnote:        //  ... or a Footnote section.
            case PTX_SectionEndnote:        //  ... or a Endnote section.
            case PTX_SectionTOC:  //  ... or a Table Of Contents.
                  // We are inserting a section immediately after a section
                  // (with no intervening block).  This is probably a bug,
                  // because there should at least be an empty block between
                  // them (so that the user can set
                  // the cursor there and start typing, if nothing else).
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  return false;
            case PTX_Block:                           // we are inserting a block.
            {
                  // The immediately prior strux is a section.  So, this
                  // will become the first block of the section and have no
                  // text.

                  fl_SectionLayout * pSL = static_cast<fl_SectionLayout *>(pL);
                  return pSL->bl_doclistener_insertBlock(NULL, pcrx,sdh,lid,pfnBindHandles);
            }
#if 0
//
// FIXME When I get brave I'll see if we can't make a table the first layout
// in a section.
//
            case PTX_SectionTable:
            {
                  UT_DEBUGMSG(("Insert Table immediately after Section \n"));
                  fl_SectionLayout * pSL = static_cast<fl_SectionLayout *>(pL);
                  return pSL->bl_doclistener_insertTable(NULL, pcrx,sdh,lid,pfnBindHandles);
            }
#endif
            default:                                  // unknown strux.
                  UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                  return false;
            }
      }     
      case PTX_SectionTOC:        //  ... or a TOC section.
      {
            switch (pcrx->getStruxType()) // see what we are inserting.
            {
            case PTX_EndTOC:
               {
                     fl_TOCLayout * pCL = static_cast<fl_TOCLayout*>(pL);

                     fl_DocSectionLayout* pDSL = 
                           static_cast<fl_DocSectionLayout *>(pCL->myContainingLayout());
                     UT_ASSERT(pCL->getContainerType() == FL_CONTAINER_TOC);
                     UT_ASSERT(pDSL->getContainerType() == FL_CONTAINER_DOCSECTION);
                     bool bResult = pCL->bl_doclistener_insertEndTOC(pCL, pcrx,sdh,lid,pfnBindHandles);
                     m_pCurrentSL = static_cast<fl_SectionLayout *>(pDSL);
                     return bResult;
               }
            default:
               {
                     m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                     return false;
               }
            }
      }
    case PTX_Block:                                   // the immediately prior strux is a block.
    {
            switch (pcrx->getStruxType()) // see what we are inserting.
            {
            case PTX_Section:                   // we are inserting a section.
               {
                     // The immediately prior strux is a block.  Everything
                     // from this point forward (to the next section) needs to
                     // be re-parented to this new section.  We also need to
                     // verify that there is a block immediately after this new
                     // section -- a section must be followed by a block
                     // because a section cannot contain content.
                  
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     xxx_UT_DEBUGMSG(("Doing Insert Strux Section Into Prev Block \n"));
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                     bool bResult = pCLSL->bl_doclistener_insertSection(pCL, FL_SECTION_DOC, pcrx,sdh,lid,pfnBindHandles);
      
                     return bResult;
               }
            
            case PTX_Block:                           // we are inserting a block.
               {
                     // The immediately prior strux is also a block.  Insert the new
                     // block and split the content between the two blocks.
                     UT_DEBUGMSG(("InsertBlock into Block \n"));
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                     bool bResult = true;
                     if(pCLSL->getType() == FL_SECTION_SHADOW)
                     {
                           fl_HdrFtrSectionLayout * pHdr = pCLSL->getHdrFtrSectionLayout();
                           bResult = pHdr->bl_doclistener_insertBlock(pCL, pcrx,sdh,lid,pfnBindHandles);
                     }
                     else
                     {
                           bResult = pCLSL->bl_doclistener_insertBlock(pCL, pcrx,sdh,lid,pfnBindHandles);
                     }
                     return bResult;
               }
          case PTX_SectionHdrFtr:
               {
                     // The immediately prior strux is a block.  Everything
                     // from this point forward (to the next section) needs to
                     // be re-parented to this new HdrFtr section.  We also need to
                     // verify that there is a block immediately after this new
                     // section -- a section must be followed by a block
                     // because a section cannot contain content.
                  
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     xxx_UT_DEBUGMSG(("Doing Insert Strux HdrFtr Into Prev Block \n"));
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                     bool bResult = pCLSL->bl_doclistener_insertSection(pCL, FL_SECTION_HDRFTR, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionTOC:
               {
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();

                     bool bResult = pCLSL->bl_doclistener_insertSection(pCL, FL_SECTION_TOC, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionFootnote:
               {
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();

                     bool bResult = pCLSL->bl_doclistener_insertSection(pCL, FL_SECTION_FOOTNOTE, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionEndnote:
               {
                       UT_DEBUGMSG(("Doing valid endnote insertion into block \n"));
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();

                     bool bResult = pCLSL->bl_doclistener_insertSection(pCL, FL_SECTION_ENDNOTE, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionTable:                    // we are inserting a section.
               {
                     // The immediately prior strux is a block.  
                     // OK this creates a table in the document.
                     UT_DEBUGMSG(("Insert Table into Block \n"));
                  
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     UT_DEBUGMSG(("Containing Section is %d \n",pL->getType()));
                     UT_DEBUGMSG(("Doing Insert Strux Table Into Prev Block \n"));
                     xxx_UT_DEBUGMSG(("Doing Insert Table Correctly \n"));
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                     bool bResult = (pCLSL->bl_doclistener_insertTable(pCL,FL_SECTION_TABLE, pcrx,sdh,lid,pfnBindHandles) != 0);
                     return bResult;
               }
            case PTX_SectionFrame:                    // we are inserting a section.
               {
                     // The immediately prior strux is a block.  
                     // OK this creates a table in the document.
                     UT_DEBUGMSG(("Insert Frame after this Block \n"));
                  
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     UT_DEBUGMSG(("Doing Insert Strux Frame Into Prev Block \n"));
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                     bool bResult = (pCLSL->bl_doclistener_insertFrame(pCL,FL_SECTION_FRAME, pcrx,sdh,lid,pfnBindHandles) != 0);
                     return bResult;
               }
            case PTX_EndFrame:                        // we are inserting an endFrame.
               {
                     // The immediately prior strux is a block.  
                     // OK this finishes a Frame on this page

                     UT_DEBUGMSG(("Insert endFrame into Block \n"));
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     UT_DEBUGMSG(("Doing Insert Strux EndFrame adter Prev Block \n"));
//
// This gets us a fl_FRAMELAYOUTCell.
//
                     fl_FrameLayout* pCLSL = (fl_FrameLayout *) pCL->myContainingLayout();
                     if(pCLSL->getContainerType() != FL_CONTAINER_FRAME)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }
                     UT_ASSERT(pCLSL->getContainerType() == FL_CONTAINER_FRAME);
                     bool bResult = pCLSL->bl_doclistener_insertEndFrame(pCL, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_EndFootnote:
               {
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout*>(pL);

                     fl_FootnoteLayout* pCLSL = 
                           static_cast<fl_FootnoteLayout *>(pCL->myContainingLayout());
                     UT_ASSERT(pCLSL->getContainerType() == FL_CONTAINER_FOOTNOTE);
                     bool bResult = pCLSL->bl_doclistener_insertEndEmbed(pCL, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_EndEndnote:
               {
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout*>(pL);

                     fl_EndnoteLayout* pCLSL = 
                           (fl_EndnoteLayout *)pCL->myContainingLayout();
                     UT_ASSERT(pCLSL->getContainerType() == FL_CONTAINER_ENDNOTE);
                     bool bResult = pCLSL->bl_doclistener_insertEndEmbed(pCL, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_EndCell:                   // we are inserting an endcell.
               {
                     // The immediately prior strux is a block.  
                     // OK this finishes a cell in the table

                     UT_DEBUGMSG(("Insert endCell into Block \n"));
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     UT_DEBUGMSG(("Doing Insert Strux EndCell Into Prev Block \n"));
//
// This gets us a fl_SectionCell.
//
                     fl_CellLayout* pCLSL = (fl_CellLayout *) pCL->myContainingLayout();
                     if(pCLSL->getContainerType() != FL_CONTAINER_CELL)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }
                     UT_ASSERT(pCLSL->getContainerType() == FL_CONTAINER_CELL);
                     bool bResult = pCLSL->bl_doclistener_insertEndCell(pCL, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            default:
               {
                     m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                     return false;
               }
            }
      }
    case PTX_SectionTable:                                  // The immediately prior strux is a table.
    {
            switch (pcrx->getStruxType()) // see what we are inserting.
            {
            case PTX_SectionCell:                     // we are inserting a cell. This is valid
              {
                     // The immediately prior strux is a Table.  
                     // OK this creates a table in the document.
                     UT_DEBUGMSG(("Insert Cell into Table \n"));
                  
                     fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pL);
                     xxx_UT_DEBUGMSG(("Doing Insert Cell Correctly \n"));
                     bool bResult = pTL->bl_doclistener_insertCell(NULL,pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_Block:                     // we are inserting a block after a endTable. This is valid
              {
                     // The immediately prior strux is a EndTable.  
                     // This isnerts a block after that. This happens on undo after
               // deleting a table.
                     UT_DEBUGMSG(("Insert Block into Table/EndTable \n"));
                     m_pDoc->miniDump(pL->getStruxDocHandle(),3);                
                     fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pL);
                     bool bResult = pTL->bl_doclistener_insertBlock(NULL,pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionTable: // insert table after a table this is valid
            {
                     // The immediately prior strux is a EndTable.  
                     // This isnerts a Table after that. Thus we we have two tables
                     // in a row.
                     UT_DEBUGMSG(("Insert Table after Table/EndTable \n"));
                     fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pL);
                     bool bResult = pTL->bl_doclistener_insertTable(pcrx, FL_SECTION_TABLE,sdh,lid,pfnBindHandles);
                     return bResult;
            }
            case PTX_EndCell:                   // we are inserting an endcell.
            {
                     // The immediately prior strux is a Table. This can happen
                  // if were pasting an endcell after a nested table. We get the
                  // the enclosing cell of the table and close it.


                     UT_DEBUGMSG(("Insert endCell into (hopefully) nested table \n"));
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     fl_CellLayout* pCLSL = (fl_CellLayout *) pCL->myContainingLayout();
//
// This gets us a fl_SectionCell.
//
                     if(pCLSL->getContainerType() != FL_CONTAINER_CELL)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                           UT_DEBUGMSG(("Pasting endcell into non nested table %d \n",pcrx->getStruxType()));
                           UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                           return false;
                     }
                     UT_DEBUGMSG(("Doing Insert Strux EndCell Into Cell containing table \n"));
                     bool bResult = pCLSL->bl_doclistener_insertEndCell(pCLSL, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionTOC:                      // we are inserting a TOC.
            {
                     // The immediately prior strux is a Table. This can happen
                  // if were inserting a TOC after an EndTable Strux.
            // We have write specal code to deal with it.

                     fl_ContainerLayout * pCL = static_cast<fl_SectionLayout *>(pL);
                     fl_SectionLayout * pCLSL = static_cast<fl_SectionLayout *>(pCL->myContainingLayout());
                     bool bResult = pCLSL->bl_doclistener_insertSection(pCL, FL_SECTION_TOC, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
            }
            default:
               {
                     UT_DEBUGMSG(("Illegal strux type after table %d \n",pcrx->getStruxType()));
                     m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                     return false;
               }
            }
      }
//
// Actually this should never becalle because we bind the endcell strux to cell container
//
    case PTX_EndCell:                                 // The immediately prior strux is a end cell.
    {
            switch (pcrx->getStruxType()) // see what we are inserting.
            {
            case PTX_SectionCell:                     // we are inserting a cell. This is valid
              {
                     // The immediately prior strux is a endCell.  
                     // OK this creates a table in the document.
                     // The end cell layout is actually a pointer to the cell it ends.

                     UT_DEBUGMSG(("Insert Cell into EndCell \n"));
                    fl_ContainerLayout * pConL = static_cast<fl_ContainerLayout *>(pL);
                     if(pConL->getContainerType() != FL_CONTAINER_CELL)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }
                    UT_ASSERT(pConL->getContainerType() == FL_CONTAINER_CELL);
                    fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pConL->myContainingLayout());
                    UT_ASSERT(pTL->getContainerType() == FL_CONTAINER_TABLE);
                    fl_CellLayout * pCL = static_cast<fl_CellLayout *>(pConL);
                    UT_DEBUGMSG(("Doing Insert Cell after endcell Correctly \n"));
                    bool bResult = pTL->bl_doclistener_insertCell(pCL, pcrx,sdh,lid,pfnBindHandles);
                    return bResult;
              }
            case PTX_EndTable:                        // we are inserting an endTable cell. This is valid
              {
                     // The immediately prior strux is a endTable.  
                     // OK this creates a table in the document.
                     // The end cell layout

                     UT_DEBUGMSG(("Insert EndTable into EndCell \n"));

                    fl_ContainerLayout * pConL = static_cast<fl_ContainerLayout *>(pL);
                     if(pConL->getContainerType() != FL_CONTAINER_CELL)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }

                    UT_ASSERT(pConL->getContainerType() == FL_CONTAINER_CELL);
                    fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pConL->myContainingLayout());
                    UT_ASSERT(pTL->getContainerType() == FL_CONTAINER_TABLE);
                    fl_CellLayout * pCL = static_cast<fl_CellLayout *>(pL);
                    UT_DEBUGMSG(("Doing Insert Cell after EndTable Correctly \n"));
                     bool bResult = pTL->bl_doclistener_insertEndTable(pCL,pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            default:
               {
                     UT_DEBUGMSG(("Illegal strux type after endcell %d \n",pcrx->getStruxType()));
                     m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                     return false;
               }
            }
      }
    case PTX_SectionCell:                                   // The immediately prior strux is a cell.
    {
            switch (pcrx->getStruxType()) // see what we are inserting.
            {
            case PTX_Block:                     // we are inserting a cell. This is valid
              {
                     // The immediately prior strux is a section.  So, this
                     // will become the first block of the section and have no
                     // text.
                    UT_DEBUGMSG(("Inserting block into CEll \n"));
                    fl_SectionLayout * pSL = static_cast<fl_SectionLayout *>(pL);
                    UT_ASSERT(pSL->getContainerType() == FL_CONTAINER_CELL);
                    bool bResult = pSL->bl_doclistener_insertBlock(NULL, pcrx,sdh,lid,pfnBindHandles);
                    return bResult;
               }
            case PTX_EndTable:                        // we are inserting an endTable cell. This is valid
              {
                     // The immediately prior strux is a cell. This actually valid since the
               // endCell strux actually points to the previous cell layout.
                     // OK this creates a table in the document.
                     // The end cell layout

                     UT_DEBUGMSG(("Insert EndTable into Cell/EndCell \n"));

                    fl_ContainerLayout * pConL = static_cast<fl_ContainerLayout *>(pL);
                    UT_ASSERT(pConL->getContainerType() == FL_CONTAINER_CELL);
                    fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pConL->myContainingLayout());
                     if(pTL->getContainerType() != FL_CONTAINER_TABLE)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }
                    UT_ASSERT(pTL->getContainerType() == FL_CONTAINER_TABLE);
                    fl_CellLayout * pCL = static_cast<fl_CellLayout *>(pL);
                    UT_DEBUGMSG(("Doing Insert EndTable Correctly \n"));
                     bool bResult = pTL->bl_doclistener_insertEndTable(pCL,pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionCell:                     // we are inserting a cell. This is valid
              {
                     // The immediately prior strux is a cell or endCell this happens
               // because the layout handle of the endcell points to cell layout.  
                     // OK this insertes a cell in the table.
                     // The end cell layout is actually a pointer to the cell it ends.

                     UT_DEBUGMSG(("Insert Cell into Cell/EndCell \n"));

                    fl_ContainerLayout * pConL = static_cast<fl_ContainerLayout *>(pL);
                     if(pConL->getContainerType() != FL_CONTAINER_CELL)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }
                    UT_ASSERT(pConL->getContainerType() == FL_CONTAINER_CELL);
                    fl_TableLayout * pTL = static_cast<fl_TableLayout *>(pConL->myContainingLayout());
                    UT_ASSERT(pTL->getContainerType() == FL_CONTAINER_TABLE);
                    fl_CellLayout * pCL = static_cast<fl_CellLayout *>(pConL);
                    UT_DEBUGMSG(("Doing Insert Cell Correctly \n"));
                    bool bResult = pTL->bl_doclistener_insertCell(pCL, pcrx,sdh,lid,pfnBindHandles);
                    return bResult;
              }
            default:
              {
                    m_pDoc->miniDump(pL->getStruxDocHandle(),3);
                    UT_DEBUGMSG(("Not Implemented \n"));
                    UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                    break;
              }
                  
            }

      }
    case PTX_SectionFrame:                                  // The immediately prior strux is a Frame
    {
            switch (pcrx->getStruxType()) // see what we are inserting.
            {
            case PTX_Block:                     // we are inserting a block into a frame. This is valid
              {
                     // The immediately prior strux is a Frame.  So, this
                     // will become the first block of the Frame.

                    UT_DEBUGMSG(("Inserting block into frame \n"));
//
// Actually the block could be being inserted right *after* the frame.
// We need to detect this and deal with this. We can do this in fl_FrameLayout
//
                    fl_SectionLayout * pSL = static_cast<fl_SectionLayout *>(pL);
                    UT_ASSERT(pSL->getContainerType() == FL_CONTAINER_FRAME);
                    fl_FrameLayout * pFL = static_cast<fl_FrameLayout *>(pL);
                    if(!pFL->isEndFrameIn())
                    {
                          bool bResult = pSL->bl_doclistener_insertBlock(NULL, pcrx,sdh,lid,pfnBindHandles);
                          return bResult;
                    }
                    PT_DocPosition posEnd = pFL->getPosition(true) + pFL->getLength()-1;
                    if(posEnd >= pcrx->getPosition())
                    {
                          bool bResult = pSL->bl_doclistener_insertBlock(NULL, pcrx,sdh,lid,pfnBindHandles);
                          return bResult;
                    }
                    else
                    {
                          bool bResult = pFL->insertBlockAfter(NULL, pcrx,sdh,lid,pfnBindHandles);
                          return bResult;

                    }
               }
            case PTX_SectionHdrFtr:
               {
                     UT_DEBUGMSG(("Inserting HdrFtr after Frame \n"));
                     fl_ContainerLayout * pCL = static_cast<fl_ContainerLayout *>(pL);
                     xxx_UT_DEBUGMSG(("Doing Insert Strux HdrFtr Into Prev Block \n"));
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                     bool bResult = pCLSL->bl_doclistener_insertSection(pCL, FL_SECTION_HDRFTR, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
                     
               }
            case PTX_EndFrame:
               {
                     UT_DEBUGMSG(("Inserting EndFrame immediately after Frame \n"));
//
// This gets us a fl_FrameLayout
//
                     fl_FrameLayout* pCLSL = static_cast<fl_FrameLayout *>( pL);
                     if(pCLSL->getContainerType() != FL_CONTAINER_FRAME)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }
                     UT_ASSERT(pCLSL->getContainerType() == FL_CONTAINER_FRAME);
                     bool bResult = pCLSL->bl_doclistener_insertEndFrame(NULL, pcrx,sdh,lid,pfnBindHandles);
                     return bResult;
               }
            case PTX_SectionFrame:
               {
                     UT_DEBUGMSG(("Inserting Frame immediately after Frame \n"));
//
// This gets us a fl_FrameLayout
//
                     fl_ContainerLayout* pCL = static_cast<fl_ContainerLayout *>( pL);
                     if(pCL->getContainerType() != FL_CONTAINER_FRAME)
                     {
                           m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     }
                     UT_ASSERT(pCL->getContainerType() == FL_CONTAINER_FRAME);
//
// Loop back for the block
//
                     while(pCL && pCL->getContainerType() != FL_CONTAINER_BLOCK)
                     {
                           pCL = pCL->getPrev();
                     }
                     UT_return_val_if_fail(pCL != NULL,false); 
                     UT_DEBUGMSG(("Doing Insert Strux Frame Into Prev Looped Block \n"));
                     fl_SectionLayout* pCLSL = pCL->getSectionLayout();
                     bool bResult = (pCLSL->bl_doclistener_insertFrame(pCL,FL_SECTION_FRAME, pcrx,sdh,lid,pfnBindHandles) != 0);
                     return bResult;
               }
            default:
               {
                     UT_DEBUGMSG(("Illegal strux type after frame %d \n",pcrx->getStruxType()));
                     m_pDoc->miniDump(pL->getStruxDocHandle(),6);
                     UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
                     return false;
               }
            }
      }
//
// todo might have to handle endTable
//
      default:
      {     
            m_pDoc->miniDump(pL->getStruxDocHandle(),6);
            UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
            return false;
      } // finish the overall switch
      }
      /*NOTREACHED*/
      UT_ASSERT(0);
      return false;
}

/*!
 */
bool fl_DocListener::signal(UT_uint32 iSignal)
{
      FV_View* pView = m_pLayout->getView();

      switch (iSignal)
      {
      case PD_SIGNAL_UPDATE_LAYOUT:
#ifdef UPDATE_LAYOUT_ON_SIGNAL
            m_pLayout->updateLayout();
#endif
            pView->updateScreen();
            break;
      case PD_SIGNAL_REFORMAT_LAYOUT:
            m_pLayout->formatAll();
            break;
      case PD_SIGNAL_REVISION_MODE_CHANGED:
            pView->updateRevisionMode();
            // fall through ...
            
      case PD_SIGNAL_DOCPROPS_CHANGED_REBUILD:
            m_pLayout->updatePropsRebuild();
            break;
      case PD_SIGNAL_DOCPROPS_CHANGED_NO_REBUILD:
            m_pLayout->updatePropsNoRebuild();
            break;
      case PD_SIGNAL_DOCNAME_CHANGED:
            m_pLayout->notifyListeners(AV_CHG_FILENAME);
            break;
      case PD_SIGNAL_DOCDIRTY_CHANGED:
            m_pLayout->notifyListeners(AV_CHG_DIRTY);
            break;

      default:
            UT_ASSERT(UT_SHOULD_NOT_HAPPEN);
            break;
      }

      return true;
}

/*! Helper method to convert hf strings to HdrFtrType */
static HdrFtrType s_convertToHdrFtrType(const XML_Char * pszHFType)
{
      if (!pszHFType)
            return FL_HDRFTR_NONE;

      if (UT_strcmp(pszHFType,"header") == 0)
            return FL_HDRFTR_HEADER;

      if (UT_strcmp(pszHFType,"header-even") == 0)
            return FL_HDRFTR_HEADER_EVEN;

      if (UT_strcmp(pszHFType,"header-first") == 0)
            return FL_HDRFTR_HEADER_FIRST;

      if (UT_strcmp(pszHFType,"header-last") == 0)
            return FL_HDRFTR_HEADER_LAST;

      if (UT_strcmp(pszHFType,"footer") == 0)
            return FL_HDRFTR_FOOTER;

      if (UT_strcmp(pszHFType,"footer-even") == 0)
            return FL_HDRFTR_FOOTER_EVEN;

      if (UT_strcmp(pszHFType,"footer-first") == 0)
            return FL_HDRFTR_FOOTER_FIRST;

      if (UT_strcmp(pszHFType,"footer-last") == 0)
          return FL_HDRFTR_FOOTER_LAST;

      return FL_HDRFTR_NONE;
}

Generated by  Doxygen 1.6.0   Back to index