diff options
Diffstat (limited to 'sw/source/core/edit/autofmt.cxx')
-rw-r--r-- | sw/source/core/edit/autofmt.cxx | 2770 |
1 files changed, 2770 insertions, 0 deletions
diff --git a/sw/source/core/edit/autofmt.cxx b/sw/source/core/edit/autofmt.cxx new file mode 100644 index 000000000000..38053c0ce0ee --- /dev/null +++ b/sw/source/core/edit/autofmt.cxx @@ -0,0 +1,2770 @@ +/************************************************************************* + * + * $RCSfile: autofmt.cxx,v $ + * + * $Revision: 1.1.1.1 $ + * + * last change: $Author: hr $ $Date: 2000-09-19 00:08:18 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#ifdef PRECOMPILED +#include "core_pch.hxx" +#endif + +#pragma hdrstop + +#define ITEMID_BOXINFO SID_ATTR_BORDER_INNER +#define _SVSTDARR_LONGS +#define _SVSTDARR_USHORTS + +#include <ctype.h> +#ifndef _HINTIDS_HXX +#include <hintids.hxx> +#endif + +#ifndef _INTN_HXX //autogen +#include <tools/intn.hxx> +#endif +#ifndef _WORDSEL_HXX +#include <svtools/wordsel.hxx> +#endif +#include <svtools/svstdarr.hxx> +#ifndef _SVX_BOXITEM_HXX //autogen +#include <svx/boxitem.hxx> +#endif +#ifndef _SVX_LRSPITEM_HXX //autogen +#include <svx/lrspitem.hxx> +#endif +#ifndef _SVX_BRKITEM_HXX //autogen +#include <svx/brkitem.hxx> +#endif +#ifndef _SVX_ADJITEM_HXX //autogen +#include <svx/adjitem.hxx> +#endif +#ifndef _SVX_TSTPITEM_HXX //autogen +#include <svx/tstpitem.hxx> +#endif +#ifndef _SVX_FONTITEM_HXX //autogen +#include <svx/fontitem.hxx> +#endif +#ifndef _SVX_LANGITEM_HXX //autogen +#include <svx/langitem.hxx> +#endif +#ifndef _SVX_CSCOITEM_HXX +#include <svx/cscoitem.hxx> +#endif +#ifndef _OFF_APP_HXX //autogen +#include <offmgr/app.hxx> +#endif + +#ifndef _SWWAIT_HXX +#include <swwait.hxx> +#endif +#ifndef _FMTPDSC_HXX //autogen +#include <fmtpdsc.hxx> +#endif +#ifndef _FMTANCHR_HXX //autogen +#include <fmtanchr.hxx> +#endif +#ifndef _DOC_HXX +#include <doc.hxx> +#endif +#ifndef _DOCARY_HXX +#include <docary.hxx> +#endif +#ifndef _EDITSH_HXX +#include <editsh.hxx> +#endif +#ifndef _INDEX_HXX +#include <index.hxx> +#endif +#ifndef _PAM_HXX +#include <pam.hxx> +#endif +#ifndef _EDIMP_HXX +#include <edimp.hxx> +#endif +#ifndef _FESH_HXX +#include <fesh.hxx> +#endif +#ifndef _SWUNDO_HXX +#include <swundo.hxx> // fuer die UndoIds +#endif +#ifndef _POOLFMT_HXX +#include <poolfmt.hxx> +#endif +#ifndef _NDTXT_HXX +#include <ndtxt.hxx> +#endif +#ifndef _TXTFRM_HXX +#include <txtfrm.hxx> +#endif +#ifndef _FRMINF_HXX +#include <frminf.hxx> +#endif +#ifndef _PAGEDESC_HXX +#include <pagedesc.hxx> +#endif +#ifndef _PARATR_HXX +#include <paratr.hxx> +#endif +#ifndef _SWTABLE_HXX +#include <swtable.hxx> +#endif +#ifndef _ACORRECT_HXX +#include <acorrect.hxx> +#endif +#ifndef _SHELLRES_HXX +#include <shellres.hxx> +#endif +#ifndef _ITABENUM_HXX +#include <itabenum.hxx> +#endif +#ifndef _SECTION_HXX //autogen +#include <section.hxx> +#endif +#ifndef _FMTHBSH_HXX //autogen +#include <fmthbsh.hxx> +#endif +#ifndef _FRMATR_HXX +#include <frmatr.hxx> +#endif + +#ifndef _MDIEXP_HXX +#include <mdiexp.hxx> +#endif +#ifndef _STATSTR_HRC +#include <statstr.hrc> +#endif +#ifndef _COMCORE_HRC +#include <comcore.hrc> +#endif + +//------------------------------------------------------------------- + +//JP 16.12.99: definition: +// from pos cPosEnDash to cPosEmDash all chars changed to endashes, +// from pos cPosEmDash to cPosEnd all chars changed to emdashes +// all other chars are changed to the user configuration + +// ---> Unicode En-/Emdash?? +#ifdef MAC +const sal_Char* pBulletChar = "+*-\xD0\xD1"; // plus endash & emdash +const int cnPosEnDash = 2, cnPosEmDash = 4, cnPosEnd = 5; +#else +#if defined(PM2 ) || defined(UNX) +const sal_Char* pBulletChar = "+*-"; +const int cnPosEnDash = 2, cnPosEmDash = 3, cnPosEnd = 3; +#else +const sal_Char* pBulletChar = "+*-\x96\x97"; // plus endash & emdash +const int cnPosEnDash = 2, cnPosEmDash = 4, cnPosEnd = 5; +#endif // PM2 / UNX +#endif // MAC +const sal_Char cStartBatsEnDash = '\x96'; +const sal_Char cStartBatsEmDash = '\x97'; + + +SvxSwAutoFmtFlags* SwEditShell::pAutoFmtFlags = 0; + +// Anzahl von Num-/Bullet-Absatzvorlagen. MAXLEVEL wird demnaechst auf +// x erhoeht, die Anzahl Vorlagen aber nicht (Ueberbleibsel aus <= 4.0) +const USHORT cnNumBullColls = 4; + +class SwAutoFormat +{ + SvxSwAutoFmtFlags aFlags; + SwPaM aDelPam; // ein Pam der benutzt werden kann + SwNodeIndex aNdIdx; // der Index auf den akt. TextNode + SwNodeIndex aEndNdIdx; // Index auf das Ende vom Bereich + + SwEditShell* pEditShell; + SwDoc* pDoc; + SwTxtNode* pAktTxtNd; // der akt. TextNode + SwTxtFrm* pAktTxtFrm; // Frame vom akt. TextNode + ULONG nEndNdIdx; // fuer die Prozent-Anzeige + + enum + { + NONE = 0, + DELIM = 1, + DIGIT = 2, + CHG = 4, + LOWER_ALPHA = 8, + UPPER_ALPHA = 16, + LOWER_ROMAN = 32, + UPPER_ROMAN = 64, + NO_DELIM = (DIGIT|LOWER_ALPHA|UPPER_ALPHA|LOWER_ROMAN|UPPER_ROMAN) + }; + + enum Format_Status + { + READ_NEXT_PARA, + TST_EMPTY_LINE, + TST_ALPHA_LINE, + GET_ALL_INFO, + IS_ONE_LINE, + TST_ENUMERIC, + TST_IDENT, + TST_NEG_IDENT, + TST_TXT_BODY, + HAS_FMTCOLL, + IS_ENDE + } eStat; + + BOOL bEnde : 1; + BOOL bEmptyLine : 1; + BOOL bMoreLines : 1; + + USHORT nLastHeadLvl, nLastCalcHeadLvl; + USHORT nLastEnumLvl, nLastCalcEnumLvl; + USHORT nRedlAutoFmtSeqId; + + BOOL IsSpace( const sal_Unicode c ) const + { return (' ' == c || '\t' == c || 0x0a == c) ? TRUE : FALSE; } + + void SetColl( USHORT nId, BOOL bHdLineOrText = FALSE ); + String GoNextPara(); + BOOL HasObjects( const SwNode& rNd ); + + // TxtNode Methoden + const SwTxtNode* GetNextNode() const; + BOOL IsEmptyLine( const SwTxtNode& rNd ) const + { return 0 == rNd.GetTxt().Len() || + rNd.GetTxt().Len() == GetLeadingBlanks( rNd.GetTxt() ); } + + BOOL IsOneLine( const SwTxtNode& ) const; + BOOL IsFastFullLine( const SwTxtNode& ) const; + BOOL IsNoAlphaLine( const SwTxtNode&) const; + BOOL IsEnumericChar( const SwTxtNode&) const; + BOOL IsBlanksInString( const SwTxtNode&) const; + USHORT CalcLevel( const SwTxtNode&, USHORT *pDigitLvl = 0 ) const; + xub_StrLen GetBigIndent( xub_StrLen& rAktSpacePos ) const; + + String& DelLeadingBlanks( String& rStr ) const; + String& DelTrailingBlanks( String& rStr ) const; + xub_StrLen GetLeadingBlanks( const String& rStr ) const; + xub_StrLen GetTrailingBlanks( const String& rStr ) const; + + const sal_Unicode GetFirstChar( const String& rStr, + BOOL bSkipDigit = TRUE ) const; + USHORT GetDigitLevel( const sal_Unicode** ppStr, String* pPreFix = 0, + String* pPostFix = 0, String* pNumTypes = 0 ) const; + // hole den FORMATIERTEN TextFrame + SwTxtFrm* GetFrm( const SwTxtNode& rTxtNd ) const; + + void BuildIndent(); + void BuildText(); + void BuildTextIndent(); + void BuildEnum( USHORT nLvl, USHORT nDigitLevel ); + void BuildNegIndent( SwTwips nSpaces ); + void BuildHeadLine( USHORT nLvl ); + + BOOL HasSelBlanks( SwPaM& rPam ) const; + BOOL HasBreakAttr( const SwTxtNode& ) const; + void DeleteSel( SwPaM& rPam ); + BOOL DeleteAktNxtPara( const String& rNxtPara ); + // loesche im Node Anfang oder/und Ende + void DeleteAktPara( BOOL bStart = TRUE, BOOL nEnd = TRUE ); + void DelEmptyLine(); + // loesche bei mehrzeiligen Absaetzen die "linken" und/oder + // "rechten" Raender + void DelMoreLinesBlanks( BOOL bWithLineBreaks = FALSE ); + // loesche den vorherigen Absatz + void DelPrevPara(); + // dann lasse doch mal das AutoCorrect auf den akt. TextNode los + void AutoCorrect( xub_StrLen nSttPos = 0 ); + + BOOL CanJoin( const SwTxtNode* pTxtNd ) const + { + return !bEnde && pTxtNd && + !IsEmptyLine( *pTxtNd ) && + !IsNoAlphaLine( *pTxtNd) && + !IsEnumericChar( *pTxtNd ) && + ((STRING_MAXLEN - 50 - pTxtNd->GetTxt().Len()) > + pAktTxtNd->GetTxt().Len()) && + !HasBreakAttr( *pTxtNd ); + } + + // ist ein Punkt am Ende ?? + BOOL IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const; + + BOOL DoUnderline(); + BOOL DoTable(); + + void _SetRedlineTxt( USHORT nId ); + BOOL SetRedlineTxt( USHORT nId ) + { if( aFlags.bWithRedlining ) _SetRedlineTxt( nId ); return TRUE; } + BOOL ClearRedlineTxt() + { if( aFlags.bWithRedlining ) pDoc->SetAutoFmtRedlineComment(0); return TRUE; } + +public: + SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFmtFlags& rFlags, + SwNodeIndex* pSttNd = 0, SwNodeIndex* pEndNd = 0 ); +}; + + +SwTxtFrm* SwAutoFormat::GetFrm( const SwTxtNode& rTxtNd ) const +{ + // besorge mal den Frame + const SwCntntFrm *pFrm = rTxtNd.GetFrm(); + ASSERT( pFrm, "zum Autoformat muss das Layout vorhanden sein" ); + if( aFlags.bAFmtByInput && !pFrm->IsValid() ) + { + SwRect aTmpFrm( pFrm->Frm() ); + SwRect aTmpPrt( pFrm->Prt() ); + pFrm->Calc(); + if( pFrm->Frm() != aTmpFrm || pFrm->Prt() != aTmpPrt || + ( pFrm->IsTxtFrm() && !((SwTxtFrm*)pFrm)->Paint().IsEmpty() ) ) + pFrm->SetCompletePaint(); + } + return ((SwTxtFrm*)pFrm)->GetFormatted(); +} + +void SwAutoFormat::_SetRedlineTxt( USHORT nActionId ) +{ + String sTxt; + USHORT nSeqNo = 0; + if( STR_AUTOFMTREDL_END > nActionId ) + { + sTxt = *ViewShell::GetShellRes()->GetAutoFmtNameLst()[ nActionId ]; + switch( nActionId ) + { + case STR_AUTOFMTREDL_SET_NUMBULET: + case STR_AUTOFMTREDL_DEL_MORELINES: + + // AutoCorrect-Actions + case STR_AUTOFMTREDL_USE_REPLACE: + case STR_AUTOFMTREDL_CPTL_STT_WORD: + case STR_AUTOFMTREDL_CPTL_STT_SENT: + case STR_AUTOFMTREDL_TYPO: + case STR_AUTOFMTREDL_UNDER: + case STR_AUTOFMTREDL_BOLD: + case STR_AUTOFMTREDL_FRACTION: + case STR_AUTOFMTREDL_DASH: + case STR_AUTOFMTREDL_ORDINAL: + nSeqNo = ++nRedlAutoFmtSeqId; + break; + } + } +#ifdef DEBUG + else + sTxt = String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "Action-Text fehlt" )); +#endif + + pDoc->SetAutoFmtRedlineComment( &sTxt, nSeqNo ); +} + +String SwAutoFormat::GoNextPara() +{ + SwNode* pNewNd = 0; + do { + aNdIdx++; + if( aNdIdx.GetIndex() >= aEndNdIdx.GetIndex() ) + { + bEnde = TRUE; + return aEmptyStr; + } + else + pNewNd = &aNdIdx.GetNode(); + + // kein TextNode -> + // TableNode : Tabelle ueberspringen + // NoTxtNode : Nodes ueberspringen + // EndNode : Ende erreicht, beenden + if( pNewNd->IsEndNode() ) + { + bEnde = TRUE; + return aEmptyStr; + } + else if( pNewNd->IsTableNode() ) + aNdIdx = *pNewNd->EndOfSectionNode(); + else if( pNewNd->IsSectionNode() ) + { + const SwSection& rSect = pNewNd->GetSectionNode()->GetSection(); + if( rSect.IsHiddenFlag() || rSect.IsProtectFlag() ) + aNdIdx = *pNewNd->EndOfSectionNode(); + } + } while( !pNewNd->IsTxtNode() ); + + if( !aFlags.bAFmtByInput ) + ::SetProgressState( aNdIdx.GetIndex() + nEndNdIdx - aEndNdIdx.GetIndex(), + pDoc->GetDocShell() ); + + pAktTxtNd = (SwTxtNode*)pNewNd; + pAktTxtFrm = GetFrm( *pAktTxtNd ); + return pAktTxtNd->GetTxt(); +} + +BOOL SwAutoFormat::HasObjects( const SwNode& rNd ) +{ + // haengt irgend etwas absatzgebundenes am Absatz? + // z.B. Rahmen, DrawObjecte, .. + BOOL bRet = FALSE; + const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts(); + for( USHORT n = 0; n < rFmts.Count(); ++n ) + { + const SwFmtAnchor& rAnchor = rFmts[ n ]->GetAnchor(); + if( FLY_PAGE != rAnchor.GetAnchorId() && + rAnchor.GetCntntAnchor() && + &rAnchor.GetCntntAnchor()->nNode.GetNode() == &rNd ) + { + bRet = TRUE; + break; + } + } + return bRet; +} + +const SwTxtNode* SwAutoFormat::GetNextNode() const +{ + if( aNdIdx.GetIndex()+1 >= aEndNdIdx.GetIndex() ) + return 0; + return pDoc->GetNodes()[ aNdIdx.GetIndex() + 1 ]->GetTxtNode(); +} + + +BOOL SwAutoFormat::IsOneLine( const SwTxtNode& rNd ) const +{ + SwTxtFrmInfo aFInfo( GetFrm( rNd ) ); + return aFInfo.IsOneLine(); +} + + +BOOL SwAutoFormat::IsFastFullLine( const SwTxtNode& rNd ) const +{ + BOOL bRet = aFlags.bRightMargin; + if( bRet ) + { + SwTxtFrmInfo aFInfo( GetFrm( rNd ) ); + bRet = aFInfo.IsFilled( aFlags.nRightMargin ); + } + return bRet; +} + + +BOOL SwAutoFormat::IsEnumericChar( const SwTxtNode& rNd ) const +{ + String sTmp( rNd.GetTxt() ); + xub_StrLen nBlnks = GetLeadingBlanks( sTmp ); + xub_StrLen nLen = rNd.GetTxt().Len() - nBlnks; + if( !nLen ) + return FALSE; + + // -, +, * getrennt durch Blank ?? + const sal_Unicode *pTmp = sTmp.GetBuffer() + nBlnks; + if( 2 < nLen && IsSpace( *(pTmp+1) ) ) + { + if( *pTmp < 256 && strchr( pBulletChar, *pTmp ) ) + return TRUE; + // sollte an der Position ein Symbolfont existieren ? + SwTxtFrmInfo aFInfo( GetFrm( rNd ) ); + if( aFInfo.IsBullet( nBlnks )) + return TRUE; + } + + // 1.) / 1. / 1.1.1 / (1). / (1) / .... + return USHRT_MAX != GetDigitLevel( &pTmp ); +} + + +BOOL SwAutoFormat::IsBlanksInString( const SwTxtNode& rNd ) const +{ + // suche im String mehr als 5 Blanks/Tabs + String sTmp( rNd.GetTxt() ); + DelTrailingBlanks( DelLeadingBlanks( sTmp )); + const sal_Unicode* pTmp = sTmp.GetBuffer(); + while( *pTmp ) + { + if( IsSpace( *pTmp ) ) + { + if( IsSpace( *++pTmp )) // 2 Space nach einander + { + const sal_Unicode* pStt = pTmp; + while( *pTmp && IsSpace( *++pTmp )) + ; + if( 5 <= pTmp - pStt ) + return TRUE; + } + else + ++pTmp; + } + else + ++pTmp; + } + return FALSE; +} + + +USHORT SwAutoFormat::CalcLevel( const SwTxtNode& rNd, USHORT *pDigitLvl ) const +{ + USHORT nLvl = 0, nBlnk = 0; + const sal_Unicode* pTmp = rNd.GetTxt().GetBuffer(); + if( pDigitLvl ) + *pDigitLvl = USHRT_MAX; + + if( RES_POOLCOLL_TEXT_MOVE == rNd.GetTxtColl()->GetPoolFmtId() ) + { + if( aFlags.bAFmtByInput ) + { + nLvl = rNd.GetAutoFmtLvl(); + ((SwTxtNode&)rNd).SetAutoFmtLvl( 0 ); + if( nLvl ) + return nLvl; + } + ++nLvl; + } + + while( *pTmp ) + { + switch( *pTmp ) + { + case ' ': if( 3 == ++nBlnk ) ++nLvl, nBlnk = 0; + break; + case '\t': ++nLvl, nBlnk = 0; + break; + default: + if( pDigitLvl ) + // Teste auf 1.) / 1. / 1.1.1 / (1). / (1) / .... + *pDigitLvl = GetDigitLevel( &pTmp ); + return nLvl; + } + ++pTmp; + } + return nLvl; +} + + + +xub_StrLen SwAutoFormat::GetBigIndent( xub_StrLen& rAktSpacePos ) const +{ + SwTxtFrmInfo aFInfo( GetFrm( *pAktTxtNd ) ); + const SwTxtFrm* pNxtFrm = 0; + + if( !bMoreLines ) + { + const SwTxtNode* pNxtNd = GetNextNode(); + if( !CanJoin( pNxtNd ) || !IsOneLine( *pNxtNd ) ) + return 0; + + pNxtFrm = GetFrm( *pNxtNd ); + } + + return aFInfo.GetBigIndent( rAktSpacePos, pNxtFrm ); +} + + +BOOL SwAutoFormat::IsNoAlphaLine( const SwTxtNode& rNd ) const +{ + const String& rStr = rNd.GetTxt(); + if( !rStr.Len() ) + return FALSE; + // oder besser: ueber die Anzahl von Alpha/Num- und !AN-Zeichen + // bestimmen. + xub_StrLen nANChar = 0, nBlnk = 0; + + const International& rInter = Application::GetAppInternational(); + for( const sal_Unicode* pTmp = rStr.GetBuffer(); *pTmp; ++pTmp ) + if( IsSpace( *pTmp ) ) + ++nBlnk; + else if( rInter.IsAlphaNumeric( *pTmp )) + ++nANChar; + // sind zu 75% keine Alpha-Nummerische-Zeichen, dann TRUE + ULONG nLen = rStr.Len() - nBlnk; + nLen = ( nLen * 3 ) / 4; // long overflow, if the strlen > USHORT + return xub_StrLen(nLen) < (rStr.Len() - nANChar - nBlnk); +} + + + +BOOL SwAutoFormat::DoUnderline() +{ + if( !aFlags.bSetBorder ) + return FALSE; + + const sal_Unicode* pStr = pAktTxtNd->GetTxt().GetBuffer(); + int eState = 0; + xub_StrLen nCnt = 0; + while( *pStr ) + { +//JP 29.03.96: Spaces unterbrechen die Umrandung! +// if( !IsSpace( *pStr ) ) + { + int eTmp = 0; + switch( *pStr ) + { + case '-': eTmp = 1; break; + case '_': eTmp = 2; break; + case '=': eTmp = 3; break; + case '*': eTmp = 4; break; + case '~': eTmp = 5; break; + case '#': eTmp = 6; break; + default: + return FALSE; + } + if( 0 == eState ) + eState = eTmp; + else if( eState != eTmp ) + return FALSE; + ++nCnt; + } + ++pStr; + } + + if( 2 < nCnt ) + { + // dann unterstreiche mal den vorherigen Absatz, wenn es diesen gibt! + DelEmptyLine(); + aDelPam.SetMark(); + aDelPam.GetMark()->nContent = 0; +//JP 19.03.96: kein Underline sondern eine Umrandung setzen! +// pDoc->Insert( aDelPam, SvxUnderlineItem( eState ) ); + + SvxBorderLine aLine; + switch( eState ) + { + case 1: // einfach, 0,05 pt + aLine.SetOutWidth( DEF_LINE_WIDTH_0 ); + break; + case 2: // einfach, 1,0 pt + aLine.SetOutWidth( DEF_LINE_WIDTH_1 ); + break; + case 3: // doppelt, 1,1 pt + aLine.SetOutWidth( DEF_DOUBLE_LINE0_OUT ); + aLine.SetInWidth( DEF_DOUBLE_LINE0_IN ); + aLine.SetDistance( DEF_DOUBLE_LINE0_DIST ); + break; + case 4: // doppelt, 4,5 pt + aLine.SetOutWidth( DEF_DOUBLE_LINE4_OUT ); + aLine.SetInWidth( DEF_DOUBLE_LINE4_IN ); + aLine.SetDistance( DEF_DOUBLE_LINE4_DIST ); + break; + case 5: // doppelt, 6,0 pt + aLine.SetOutWidth( DEF_DOUBLE_LINE5_OUT ); + aLine.SetInWidth( DEF_DOUBLE_LINE5_IN ); + aLine.SetDistance( DEF_DOUBLE_LINE5_DIST ); + break; + case 6: // doppelt, 9,0 pt + aLine.SetOutWidth( DEF_DOUBLE_LINE6_OUT ); + aLine.SetInWidth( DEF_DOUBLE_LINE6_IN ); + aLine.SetDistance( DEF_DOUBLE_LINE6_DIST ); + break; + } + + SvxBoxItem aBox; + aBox.SetLine( &aLine, BOX_LINE_BOTTOM ); + aBox.SetDistance( 42 ); // ~0,75 mm + pDoc->Insert( aDelPam, aBox ); + + aDelPam.DeleteMark(); + } + return 2 < nCnt; +} + + +BOOL SwAutoFormat::DoTable() +{ + if( !aFlags.bCreateTable || !aFlags.bAFmtByInput || + pAktTxtNd->FindTableNode() ) + return FALSE; + + const String& rTmp = pAktTxtNd->GetTxt(); + xub_StrLen nSttPlus = GetLeadingBlanks( rTmp ); + xub_StrLen nEndPlus = GetTrailingBlanks( rTmp ); + sal_Unicode cChar; + + if( 2 > nEndPlus - nSttPlus || + ( '+' != ( cChar = rTmp.GetChar( nSttPlus )) && '|' != cChar ) || + ( '+' != ( cChar = rTmp.GetChar( nEndPlus - 1)) && '|' != cChar )) + return FALSE; + + SwTxtFrmInfo aInfo( pAktTxtFrm ); + + xub_StrLen n = nSttPlus; + const sal_Unicode* pStr = rTmp.GetBuffer() + n; + SvUShorts aPosArr( 5, 5 ); + + while( *pStr ) + { + switch( *pStr ) + { + case '-': + case '_': + case '=': + case ' ': + case '\t': + break; + + case '+': + case '|': + aPosArr.Insert( aInfo.GetCharPos(n), aPosArr.Count() ); + break; + + default: + return FALSE; + } + if( ++n == nEndPlus ) + break; + + ++pStr; + } + + if( 1 < aPosArr.Count() ) + { + // Ausrichtung vom Textnode besorgen: + USHORT nColCnt = aPosArr.Count() - 1; + SwTwips nSttPos = aPosArr[ 0 ]; + SwHoriOrient eHori; + switch( pAktTxtNd->GetSwAttrSet().GetAdjust().GetAdjust() ) + { + case SVX_ADJUST_CENTER: eHori = HORI_CENTER; break; + case SVX_ADJUST_RIGHT: eHori = HORI_RIGHT; break; + + default: + if( nSttPos ) + { + eHori = HORI_NONE; + // dann muss als letztes noch die akt. FrameBreite + // ins Array + aPosArr.Insert( pAktTxtFrm->Frm().Width(), aPosArr.Count() ); + } + else + eHori = HORI_LEFT; + break; + } + + // dann erzeuge eine Tabelle, die den Zeichen entspricht + DelEmptyLine(); + SwNodeIndex aIdx( aDelPam.GetPoint()->nNode ); + aDelPam.Move( fnMoveForward ); + pDoc->InsertTable( *aDelPam.GetPoint(), 1, nColCnt, eHori, ALL_TBL_INS_ATTR, + 0, &aPosArr ); + aDelPam.GetPoint()->nNode = aIdx; + } + return 1 < aPosArr.Count(); +} + + +String& SwAutoFormat::DelLeadingBlanks( String& rStr ) const +{ + for( xub_StrLen nL = rStr.Len(), n = 0; + n < nL && IsSpace( rStr.GetChar(n) ); ++n ) + ; + if( n ) // keine Spaces + rStr.Erase( 0, n ); + return rStr; +} + + +String& SwAutoFormat::DelTrailingBlanks( String& rStr ) const +{ + xub_StrLen nL = rStr.Len(), n = nL; + if( !nL ) + return rStr; + + while( --n && IsSpace( rStr.GetChar( n ) ) ) + ; + if( n+1 != nL ) // keine Spaces + rStr.Erase( n+1 ); + return rStr; +} + + +xub_StrLen SwAutoFormat::GetLeadingBlanks( const String& rStr ) const +{ + for( xub_StrLen nL = rStr.Len(), n = 0; + n < nL && IsSpace( rStr.GetChar( n ) ); ++n ) + ; + return n; +} + + +xub_StrLen SwAutoFormat::GetTrailingBlanks( const String& rStr ) const +{ + xub_StrLen nL = rStr.Len(), n = nL; + if( !nL ) + return 0; + + while( --n && IsSpace( rStr.GetChar( n ) ) ) + ; + return ++n; +} + + +const sal_Unicode SwAutoFormat::GetFirstChar( const String& rStr, + BOOL bSkipDigit ) const +{ + const sal_Unicode* pTmp = rStr.GetBuffer(); + BOOL bFirstNo = FALSE; + while( *pTmp ) + { + if( !IsSpace( *pTmp )) + { + // Teste auf 1.) / 1. / 1.1.1 / (1). / (1) / .... + if( bSkipDigit || bFirstNo || + USHRT_MAX == GetDigitLevel( &pTmp ) ) + return *pTmp; + bFirstNo = TRUE; + } + ++pTmp; + } + return *pTmp; +} + + +USHORT SwAutoFormat::GetDigitLevel( const sal_Unicode** ppStr, + String* pPreFix, String* pPostFix, String* pNumTypes ) const +{ + // Teste auf 1.) / 1. / 1.1.1 / (1). / (1) / .... + const sal_Unicode* pTmp = *ppStr; + int eScan = NONE; + + USHORT nStart = 0; + BYTE nDigitLvl = 0, nDigitCnt = 0; + const International& rInter = Application::GetAppInternational(); + while( *pTmp ) + { + if( rInter.IsNumeric( *pTmp ) ) + { + if( eScan & DELIM ) + { + if( eScan & CHG ) // nicht wenns mit einer Zahl beginnt + { + ++nDigitLvl; + if( pPostFix ) + *pPostFix += (sal_Unicode)1; + } + + if( pNumTypes ) + *pNumTypes += (sal_Unicode)('0' + SVX_NUM_ARABIC); + + eScan = eScan | CHG; + } + else if( pNumTypes && !(eScan & DIGIT) ) + *pNumTypes += (sal_Unicode)('0' + SVX_NUM_ARABIC); + + eScan &= ~DELIM; // Delim raus + if( 0 != (eScan & ~CHG) && DIGIT != (eScan & ~CHG)) + return USHRT_MAX; + + eScan |= DIGIT; // Digit rein + if( 3 == ++nDigitCnt ) // mehr als 2 Nummern sind kein Enum mehr + return USHRT_MAX; + + nStart *= 10; nStart += USHORT( *pTmp - '0' ); + } + else if( rInter.IsAlpha( *pTmp ) ) + { + BOOL bIsUpper = rInter.IsUpper( *pTmp ); + sal_Unicode cLow = rInter.Lower( *pTmp ), cNumTyp; + int eTmpScan; + + // roemische Zeichen sind "mdclxvi". Da man aber eher mal eine + // Numerierung mit c oder d anfangen will, werden diese erstmal + // zu chars und spaeter ggfs. zu romischen Zeichen! +// if( strchr( "mdclxvi", cLow )) + if( 256 > cLow &&( (eScan & (LOWER_ROMAN|UPPER_ROMAN)) + ? strchr( "mdclxvi", cLow ) + : strchr( "mlxvi", cLow ) )) + { + if( bIsUpper ) + cNumTyp = '0' + SVX_NUM_ROMAN_UPPER, eTmpScan = UPPER_ROMAN; + else + cNumTyp = '0' + SVX_NUM_ROMAN_LOWER, eTmpScan = LOWER_ROMAN; + } + else if( bIsUpper ) + cNumTyp = '0' + SVX_NUM_CHARS_UPPER_LETTER, eTmpScan = UPPER_ALPHA; + else + cNumTyp = '0' + SVX_NUM_CHARS_LOWER_LETTER, eTmpScan = LOWER_ALPHA; + + + //ggfs. auf roemische Zeichen umschalten (nur bei c/d!)? + if( 1 == nDigitCnt && ( eScan & (UPPER_ALPHA|LOWER_ALPHA) ) && + ( 3 == nStart || 4 == nStart) && 256 > cLow && + strchr( "mdclxvi", cLow ) && + (( eScan & UPPER_ALPHA ) ? (eTmpScan & (UPPER_ALPHA|UPPER_ROMAN)) + : (eTmpScan & (LOWER_ALPHA|LOWER_ROMAN))) ) + { + sal_Unicode c = '0'; + nStart = 3 == nStart ? 100 : 500; + if( UPPER_ALPHA == eTmpScan ) + eTmpScan = UPPER_ROMAN, c += SVX_NUM_ROMAN_UPPER; + else + eTmpScan = LOWER_ROMAN, c += SVX_NUM_ROMAN_LOWER; + +#ifndef MAC + ( eScan &= ~(UPPER_ALPHA|LOWER_ALPHA)) |= eTmpScan; +#else + eScan &= ~(UPPER_ALPHA|LOWER_ALPHA); + eScan |= eTmpScan; +#endif + if( pNumTypes ) + pNumTypes->SetChar( pNumTypes->Len() - 1, c ); + } + + if( eScan & DELIM ) + { + if( eScan & CHG ) // nicht wenns mit einer Zahl beginnt + { + ++nDigitLvl; + if( pPostFix ) + *pPostFix += (sal_Unicode)1; + } + + if( pNumTypes ) + *pNumTypes += cNumTyp; + eScan = eScan | CHG; + } + else if( pNumTypes && !(eScan & eTmpScan) ) + *pNumTypes += cNumTyp; + + eScan &= ~DELIM; // Delim raus + + // falls ein andere Type gesetzt ist, brechen wir ab + if( 0 != ( eScan & ~CHG ) && eTmpScan != ( eScan & ~CHG )) + return USHRT_MAX; + + if( eTmpScan & (UPPER_ALPHA | LOWER_ALPHA) ) + { + // Buchstaben nur zulassen, wenn sie einmalig vorkommen +#ifdef WITH_ALPHANUM_AS_NUMFMT +//JP 17.06.98: um Abkuerzungen wie P.S. oder Z.b. am Absatzanfang nicht zu +// Numerierungen zu expandieren, hier erstmal bei erkannten +// ALPHA keinen gueltigen DigitLevel returnen. + if( nDigitCnt ) +#endif + return USHRT_MAX; + nStart = (USHORT)(cLow - 'a') + 1; + } + else + { + // roemische Zahlen: checke ob das gueltige Zeichen sind + USHORT nVal; + BOOL bError = FALSE; + switch( cLow ) + { + case 'm': nVal = 1000; goto CHECK_ROMAN_1; + case 'd': nVal = 500; goto CHECK_ROMAN_5; + case 'c': nVal = 100; goto CHECK_ROMAN_1; + case 'l': nVal = 50; goto CHECK_ROMAN_5; + case 'x': nVal = 10; goto CHECK_ROMAN_1; + case 'v': nVal = 5; goto CHECK_ROMAN_5; + +CHECK_ROMAN_1: + { + int nMod5 = nStart % (nVal * 5); + int nLast = nStart % nVal; + int n10 = nVal / 10; + + if( nMod5 == ((3 * nVal) + n10 ) || + nMod5 == ((4 * nVal) + n10 ) || + nLast == n10 ) + nStart += n10 * 8; + else if( nMod5 == 0 || + nMod5 == (1 * nVal) || + nMod5 == (2 * nVal) ) + nStart += nVal; + else + bError = TRUE; + } + break; + +CHECK_ROMAN_5: + { + if( ( nStart / nVal ) & 1 ) + bError = TRUE; + else + { + int nMod = nStart % nVal; + int n10 = nVal / 5; + if( n10 == nMod ) + nStart += 3 * n10; + else if( 0 == nMod ) + nStart += nVal; + else + bError = TRUE; + } + } + break; + + case 'i': + if( nStart % 5 >= 3 ) + bError = TRUE; + else + nStart += 1; + break; + + default: + bError = TRUE; + } + + if( bError ) + return USHRT_MAX; + } + eScan |= eTmpScan; // Digit rein + ++nDigitCnt; + } + else if( 256 > *pTmp && strchr( /*".,)([]{}"*/ ".,)(<>", *pTmp ) ) + { + // nur wenn noch keine Zahlen gelesen wurden! + if( pPreFix && !( eScan & ( NO_DELIM | CHG )) ) + *pPreFix += *pTmp; + else if( pPostFix ) + *pPostFix += *pTmp; + + if( NO_DELIM & eScan ) + { + eScan |= CHG; + if( pPreFix ) + (*pPreFix += (sal_Unicode)1) + += String::CreateFromInt32( nStart ); + } + eScan &= ~NO_DELIM; // Delim raus + eScan |= DELIM; // Digit rein + nDigitCnt = 0; + nStart = 0; + } + else + break; + ++pTmp; + } + if( !( CHG & eScan ) || *ppStr == pTmp || !*pTmp || !IsSpace( *pTmp )) + return USHRT_MAX; + + if( (NO_DELIM & eScan) && pPreFix ) // den letzen nicht vergessen + (*pPreFix += (sal_Unicode)1) += String::CreateFromInt32( nStart ); + + *ppStr = pTmp; + return nDigitLvl; // von 0 .. 5 +} + + +void SwAutoFormat::SetColl( USHORT nId, BOOL bHdLineOrText ) +{ + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); + + // behalte harte Tabs, Ausrichtung, Sprache, Silbentrennung, + // DropCaps und fast alle Frame-Attribute + SfxItemSet aSet( pDoc->GetAttrPool(), + RES_PARATR_ADJUST, RES_PARATR_ADJUST, + RES_PARATR_TABSTOP, RES_PARATR_DROP, + RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE, + RES_BACKGROUND, RES_SHADOW, + 0 ); + + if( pAktTxtNd->GetpSwAttrSet() ) + { + aSet.Put( *pAktTxtNd->GetpSwAttrSet() ); + // einige Sonderbedingungen: + // HeaderLine/Textkoerper: nur zentriert oder rechts mitnehmem + // sonst nur den Blocksatz + SvxAdjustItem* pAdj; + if( SFX_ITEM_SET == aSet.GetItemState( RES_PARATR_ADJUST, + FALSE, (const SfxPoolItem**)&pAdj )) + { + SvxAdjust eAdj = pAdj->GetAdjust(); + if( bHdLineOrText ? (SVX_ADJUST_RIGHT != eAdj && + SVX_ADJUST_CENTER != eAdj) + : SVX_ADJUST_BLOCK != eAdj ) + aSet.ClearItem( RES_PARATR_ADJUST ); + } + } + + pDoc->SetTxtFmtCollByAutoFmt( *aDelPam.GetPoint(), nId, &aSet ); +} + + +BOOL SwAutoFormat::HasSelBlanks( SwPaM& rPam ) const +{ + // noch ein Blank am Anfang oder Ende ? + // nicht loeschen, wird wieder eingefuegt. + SwPosition * pPos = rPam.End(); + xub_StrLen nBlnkPos = pPos->nContent.GetIndex(); + SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode(); + if( nBlnkPos && nBlnkPos-- < pTxtNd->GetTxt().Len() && + ( ' ' == pTxtNd->GetTxt().GetChar( nBlnkPos ) )) +// JP 23.08.95: keine Tabs stehen lassen, diese in Blanks wandeln +// ( ' ' == ( cCh = pTxtNd->GetTxt()[ nBlnkPos ] ) || '\t' == cCh )) + pPos->nContent--; + else + { + pPos = rPam.GetPoint() == pPos ? rPam.GetMark() : rPam.GetPoint(); + nBlnkPos = pPos->nContent.GetIndex(); + pTxtNd = pPos->nNode.GetNode().GetTxtNode(); + if( nBlnkPos < pTxtNd->GetTxt().Len() && + ( ' ' == pTxtNd->GetTxt().GetChar( nBlnkPos ))) +// JP 23.08.95: keine Tabs stehen lassen, diese in Blanks wandeln +// ( ' ' == ( cCh = pTxtNd->GetTxt()[ nBlnkPos ] ) || '\t' == cCh )) + pPos->nContent++; + else + return FALSE; + } + return TRUE; +} + + +BOOL SwAutoFormat::HasBreakAttr( const SwTxtNode& rTxtNd ) const +{ + const SwAttrSet* pSet = rTxtNd.GetpSwAttrSet(); + if( !pSet ) + return FALSE; + + const SfxPoolItem* pItem; + if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, FALSE, &pItem ) + && SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() ) + return TRUE; + + if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, FALSE, &pItem ) + && ((SwFmtPageDesc*)pItem)->GetPageDesc() + && PD_NONE != ((SwFmtPageDesc*)pItem)->GetPageDesc()->GetUseOn() ) + return TRUE; + return FALSE; +} + + +// ist ein Punkt am Ende ?? +BOOL SwAutoFormat::IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const +{ + const String& rStr = rTxtNd.GetTxt(); + xub_StrLen n = rStr.Len(); + if( !n ) + return TRUE; + + while( --n && IsSpace( rStr.GetChar( n ) ) ) + ; + return '.' == rStr.GetChar( n ); +} + + +// loesche im Node Anfang oder/und Ende +void SwAutoFormat::DeleteAktPara( BOOL bStart, BOOL bEnd ) +{ + if( aFlags.bAFmtByInput + ? aFlags.bAFmtByInpDelSpacesAtSttEnd + : aFlags.bAFmtDelSpacesAtSttEnd ) + { + // Loesche Blanks am Ende vom akt. und am Anfang vom naechsten + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + xub_StrLen nPos; + if( bStart && 0 != ( nPos = GetLeadingBlanks( pAktTxtNd->GetTxt() ))) + { + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); + aDelPam.SetMark(); + aDelPam.GetPoint()->nContent = nPos; + DeleteSel( aDelPam ); + aDelPam.DeleteMark(); + } + if( bEnd && pAktTxtNd->GetTxt().Len() != + ( nPos = GetTrailingBlanks( pAktTxtNd->GetTxt() )) ) + { + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, pAktTxtNd->GetTxt().Len() ); + aDelPam.SetMark(); + aDelPam.GetPoint()->nContent = nPos; + DeleteSel( aDelPam ); + aDelPam.DeleteMark(); + } + } +} + +void SwAutoFormat::DeleteSel( SwPaM& rDelPam ) +{ + if( aFlags.bWithRedlining ) + { + // damit der DelPam auch verschoben wird, in den Shell-Cursr-Ring + // mit aufnehmen !! + SwPaM* pShCrsr = pEditShell->_GetCrsr(); + SwPaM aTmp( *pAktTxtNd, 0, pShCrsr ); + + Ring *pPrev = rDelPam.GetPrev(); + rDelPam.MoveRingTo( pShCrsr ); + + pEditShell->DeleteSel( rDelPam ); + + // und den Pam wieder herausnehmen: + Ring *p, *pNext = (Ring*)&rDelPam; + do { + p = pNext; + pNext = p->GetNext(); + p->MoveTo( &rDelPam ); + } while( p != pPrev ); + + aNdIdx = aTmp.GetPoint()->nNode; + pAktTxtNd = aNdIdx.GetNode().GetTxtNode(); + } + else + pEditShell->DeleteSel( rDelPam ); +} + +BOOL SwAutoFormat::DeleteAktNxtPara( const String& rNxtPara ) +{ + // Loesche Blanks am Ende vom akt. und am Anfang vom naechsten + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, + GetTrailingBlanks( pAktTxtNd->GetTxt() ) ); + aDelPam.SetMark(); + + aDelPam.GetPoint()->nNode++; + SwTxtNode* pTNd = aDelPam.GetNode()->GetTxtNode(); + if( !pTNd ) + { + // dann nur bis zum Ende von Absatz loeschen + aDelPam.GetPoint()->nNode--; + aDelPam.GetPoint()->nContent = pAktTxtNd->GetTxt().Len(); + } + else + aDelPam.GetPoint()->nContent.Assign( pTNd, + GetLeadingBlanks( rNxtPara )); + + // noch ein Blank am Anfang oder Ende ? + // nicht loeschen, wird wieder eingefuegt. + BOOL bHasBlnks = HasSelBlanks( aDelPam ); + + if( *aDelPam.GetPoint() != *aDelPam.GetMark() ) + DeleteSel( aDelPam ); + aDelPam.DeleteMark(); + + return !bHasBlnks; +} + + +void SwAutoFormat::DelEmptyLine() +{ + SetRedlineTxt( STR_AUTOFMTREDL_DEL_EMPTY_PARA ); + // Loesche Blanks den leeren Absatz + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, pAktTxtNd->GetTxt().Len() ); + aDelPam.SetMark(); + + aDelPam.GetMark()->nNode--; + SwTxtNode* pTNd = aDelPam.GetNode( FALSE )->GetTxtNode(); + if( pTNd ) + // erstmal den vorherigen Textnode benutzen. + aDelPam.GetMark()->nContent.Assign( pTNd, pTNd->GetTxt().Len() ); + else + { + // dann versuche den naechsten (am Anfang vom Dok, Tabellen-Zellen, + // Rahmen, ... + aDelPam.GetMark()->nNode += 2; + pTNd = aDelPam.GetNode( FALSE )->GetTxtNode(); + if( pTNd ) + { + aDelPam.GetMark()->nContent.Assign( pTNd, 0 ); + aDelPam.GetPoint()->nContent = 0; + } + } + if( pTNd ) + DeleteSel( aDelPam ); + + aDelPam.DeleteMark(); + ClearRedlineTxt(); +} + + +void SwAutoFormat::DelMoreLinesBlanks( BOOL bWithLineBreaks ) +{ + if( aFlags.bAFmtByInput + ? aFlags.bAFmtByInpDelSpacesBetweenLines + : aFlags.bAFmtDelSpacesBetweenLines ) + { + // loesche alle "Blanks" Links und Rechts vom Einzug + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); + + SwTxtFrmInfo aFInfo( pAktTxtFrm ); + aFInfo.GetSpaces( aDelPam, !aFlags.bAFmtByInput || bWithLineBreaks ); + + SwPaM* pNxt; + do { + pNxt = (SwPaM*)aDelPam.GetNext(); + if( pNxt->HasMark() && *pNxt->GetPoint() != *pNxt->GetMark() ) + { + BOOL bHasBlnks = HasSelBlanks( *pNxt ); + DeleteSel( *pNxt ); + if( !bHasBlnks ) + pDoc->Insert( *pNxt, ' ' ); + } + + if( pNxt == &aDelPam ) + break; + delete pNxt; + } while( TRUE ); + + aDelPam.DeleteMark(); + } +} + + + // loesche den vorherigen Absatz +void SwAutoFormat::DelPrevPara() +{ + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); + aDelPam.SetMark(); + + aDelPam.GetPoint()->nNode--; + SwTxtNode* pTNd = aDelPam.GetNode()->GetTxtNode(); + if( pTNd ) + { + // erstmal den vorherigen Textnode benutzen. + aDelPam.GetPoint()->nContent.Assign( pTNd, pTNd->GetTxt().Len() ); + DeleteSel( aDelPam ); + } + aDelPam.DeleteMark(); +} + + +void SwAutoFormat::BuildIndent() +{ + SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_INDENT ); + + // lese alle nachfolgenden Absaetze die zu diesem Einzug gehoeren + BOOL bBreak = TRUE; + if( bMoreLines ) + DelMoreLinesBlanks( TRUE ); + else + bBreak = !IsFastFullLine( *pAktTxtNd ) || + IsBlanksInString( *pAktTxtNd ) || + IsSentenceAtEnd( *pAktTxtNd ); + SetColl( RES_POOLCOLL_TEXT_IDENT ); + if( !bBreak ) + { + SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES ); + const SwTxtNode* pNxtNd = GetNextNode(); + if( pNxtNd && !bEnde ) + { + do { + bBreak = !IsFastFullLine( *pNxtNd ) || + IsBlanksInString( *pNxtNd ) || + IsSentenceAtEnd( *pNxtNd ); + if( DeleteAktNxtPara( pNxtNd->GetTxt() )) + pDoc->Insert( aDelPam, ' ' ); + if( bBreak ) + break; + pNxtNd = GetNextNode(); + } while( CanJoin( pNxtNd ) && + !CalcLevel( *pNxtNd ) ); + } + } + DeleteAktPara( TRUE, TRUE ); + AutoCorrect(); +} + + +void SwAutoFormat::BuildTextIndent() +{ + SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT_INDENT); + // lese alle nachfolgenden Absaetze die zu diesem Einzug gehoeren + BOOL bBreak = TRUE; + if( bMoreLines ) + DelMoreLinesBlanks( TRUE ); + else + bBreak = !IsFastFullLine( *pAktTxtNd ) || + IsBlanksInString( *pAktTxtNd ) || + IsSentenceAtEnd( *pAktTxtNd ); + + if( aFlags.bAFmtByInput ) + pAktTxtNd->SetAutoFmtLvl( (BYTE)CalcLevel( *pAktTxtNd ) ); + + SetColl( RES_POOLCOLL_TEXT_MOVE ); + if( !bBreak ) + { + SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES ); + const SwTxtNode* pNxtNd = GetNextNode(); + while( CanJoin( pNxtNd ) && + CalcLevel( *pNxtNd ) ) + { + bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) || + IsSentenceAtEnd( *pNxtNd ); + if( DeleteAktNxtPara( pNxtNd->GetTxt() ) ) + pDoc->Insert( aDelPam, ' ' ); + if( bBreak ) + break; + pNxtNd = GetNextNode(); + } + } + DeleteAktPara( TRUE, TRUE ); + AutoCorrect(); +} + + +void SwAutoFormat::BuildText() +{ + SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT ); + // lese alle nachfolgenden Absaetze die zu diesem Text + // ohne Einzug gehoeren + BOOL bBreak = TRUE; + if( bMoreLines ) + DelMoreLinesBlanks(); + else + bBreak = !IsFastFullLine( *pAktTxtNd ) || + IsBlanksInString( *pAktTxtNd ) || + IsSentenceAtEnd( *pAktTxtNd ); + SetColl( RES_POOLCOLL_TEXT, TRUE ); + if( !bBreak ) + { + SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES ); + const SwTxtNode* pNxtNd = GetNextNode(); + while( CanJoin( pNxtNd ) && + !CalcLevel( *pNxtNd ) ) + { + bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) || + IsSentenceAtEnd( *pNxtNd ); + if( DeleteAktNxtPara( pNxtNd->GetTxt() ) ) + pDoc->Insert( aDelPam, ' ' ); + if( bBreak ) + break; + pNxtNd = GetNextNode(); + } + } + DeleteAktPara( TRUE, TRUE ); + AutoCorrect(); +} + + +void SwAutoFormat::BuildEnum( USHORT nLvl, USHORT nDigitLevel ) +{ + SetRedlineTxt( STR_AUTOFMTREDL_SET_NUMBULET ); + + BOOL bBreak = TRUE; + + // als erstes den akt. Einzug bestimmen und die Framebreite bestimmen + SwTwips nFrmWidth = pAktTxtFrm->Prt().Width();; + SwTwips nLeftTxtPos; + { + const sal_Unicode* pTxt = pAktTxtNd->GetTxt().GetBuffer(), *pSav = pTxt; + while( IsSpace( *pTxt ) ) + ++pTxt; + + SwTxtFrmInfo aInfo( pAktTxtFrm ); + nLeftTxtPos = aInfo.GetCharPos( pTxt - pSav ); +#ifdef NUM_RELSPACE + nLeftTxtPos -= pAktTxtNd->GetSwAttrSet().GetLRSpace().GetLeft(); +#endif + } + + if( bMoreLines ) + DelMoreLinesBlanks(); + else + bBreak = !IsFastFullLine( *pAktTxtNd ) || + IsBlanksInString( *pAktTxtNd ) || + IsSentenceAtEnd( *pAktTxtNd ); + +// SetColl( RES_POOLCOLL_NUM_LEVEL1 + ( nLvl * 4 ) ); + DeleteAktPara( TRUE, TRUE ); + + BOOL bChgBullet = FALSE, bChgEnum = FALSE; + xub_StrLen nAutoCorrPos = 0; + + // falls die Numerierung gesetzt werden, die akt. besorgen + SwNumRule aRule( pDoc->GetUniqueNumRuleName() ); + const SwNumRule* pCur; + if( aFlags.bSetNumRule && 0 != (pCur = pAktTxtNd->GetNumRule()) ) + aRule = *pCur; + + // ersetze das Bullet-Zeichen mit dem definiertem + const sal_Unicode* pStt = pAktTxtNd->GetTxt().GetBuffer(), *pOrigStt = pStt; + const sal_Char* pFndBulletChr; +// if( aFlags.bAFmtByInput ? aFlags.bSetNumRule : aFlags.bChgEnumNum && + if( aFlags.bChgEnumNum && + 2 < pAktTxtNd->GetTxt().Len() && 256 > *pStt && + 0 != ( pFndBulletChr = strchr( pBulletChar, *pStt )) && + IsSpace( *(pStt+1) ) ) + { + if( aFlags.bAFmtByInput ) + { + if( aFlags.bSetNumRule ) + { + SwCharFmt* pCFmt = pDoc->GetCharFmtFromPool( + RES_POOLCHR_BUL_LEVEL ); + bChgBullet = TRUE; + // wurde das Format schon mal angepasst? + if( !aRule.GetNumFmt( nLvl ) ) + { + int nBulletPos = pFndBulletChr - pBulletChar; + sal_Char cBullChar; + const Font* pBullFnt; + if( nBulletPos < cnPosEnDash ) + { + cBullChar = aFlags.cBullet; + pBullFnt = &aFlags.aBulletFont; + } + else + { + cBullChar = nBulletPos < cnPosEmDash + ? cStartBatsEnDash + : cStartBatsEmDash; + pBullFnt = &SwNumRule::GetDefBulletFont(); + } + + USHORT nAbsPos = lBullIndent; + USHORT nSpaceSteps = nLvl + ? USHORT(nLeftTxtPos / nLvl) + : lBullIndent; + for( BYTE n = 0; n < MAXLEVEL; ++n, nAbsPos += nSpaceSteps ) + { + SwNumFmt aFmt( aRule.Get( n ) ); + aFmt.SetBulletFont( pBullFnt ); + aFmt.SetBulletChar( cBullChar ); + aFmt.eType = SVX_NUM_CHAR_SPECIAL; + aFmt.SetRelLSpace( FALSE ); + aFmt.SetFirstLineOffset( lBullFirstLineOffset ); + aFmt.SetAbsLSpace( nAbsPos ); + aRule.Set( n, aFmt ); + + if( !aFmt.GetCharFmt() ) + aFmt.SetCharFmt( pCFmt ); + + if( n == nLvl && + nFrmWidth < ( nSpaceSteps * MAXLEVEL ) ) + nSpaceSteps = ( nFrmWidth - nLeftTxtPos ) / + ( MAXLEVEL - nLvl ); + } + } + } + } + else + { + bChgBullet = TRUE; + SetColl( RES_POOLCOLL_BUL_LEVEL1 + ( Min( nLvl, cnNumBullColls ) * 4 ) ); + } + } + else + { + // dann ist das eine Nummerierung + + //JP 21.11.97: Der NumLevel wird entweder der DigitLevel oder + // wenn der nicht vorhanden oder 0 ist, durch den + // (Einrueckungs-)Level. + + String aPostFix, aPreFix, aNumTypes; + if( USHRT_MAX != ( nDigitLevel = GetDigitLevel( + &pStt, &aPreFix, &aPostFix, &aNumTypes )) ) + { + bChgEnum = TRUE; + + // Ebene 0 und Einrueckung dann wird die Ebene durch den linken + // Einzug und der default NumEinrueckung bestimmt. + if( !nDigitLevel && nLeftTxtPos ) + nLvl = Min( USHORT( nLeftTxtPos / lNumIndent ), + USHORT( MAXLEVEL - 1 ) ); + else + nLvl = nDigitLevel; + } + + if( bChgEnum && aFlags.bSetNumRule ) + { + if( !pCur ) // NumRule anpassen, wenn sie neu ist + { + SwCharFmt* pCFmt = pDoc->GetCharFmtFromPool( + RES_POOLCHR_NUM_LEVEL ); + if( !nDigitLevel ) + { + SwNumFmt aFmt( aRule.Get( nLvl ) ); + aFmt.SetStartValue( aPreFix.GetToken( 1, + (sal_Unicode)1 ).ToInt32()); + aFmt.SetPrefix( aPreFix.GetToken( 0, (sal_Unicode)1 )); + aFmt.SetPostfix( aPostFix.GetToken( 0, (sal_Unicode)1 )); + aFmt.SetInclUpperLevel( FALSE ); + + if( !aFmt.GetCharFmt() ) + aFmt.SetCharFmt( pCFmt ); + + if( aNumTypes.Len() ) + aFmt.eType = (SvxExtNumType)(aNumTypes.GetChar( 0 ) - '0'); + + aRule.Set( nLvl, aFmt ); + } + else + { + USHORT nSpaceSteps = nLvl ? USHORT(nLeftTxtPos / nLvl) : 0; + for( BYTE n = 0; n <= nLvl; ++n ) + { + SwNumFmt aFmt( aRule.Get( n ) ); + + aFmt.SetStartValue( aPreFix.GetToken( n+1, + (sal_Unicode)1 ).ToInt32() ); + if( !n ) + aFmt.SetPrefix( aPreFix.GetToken( n, (sal_Unicode)1 )); + aFmt.SetPostfix( aPostFix.GetToken( n, (sal_Unicode)1 )); + aFmt.SetInclUpperLevel( TRUE ); + if( n < aNumTypes.Len() ) + aFmt.eType = (SvxExtNumType)(aNumTypes.GetChar( n ) - '0'); + + aFmt.SetRelLSpace( FALSE ); + aFmt.SetAbsLSpace( USHORT( nSpaceSteps * n ) + + lNumIndent ); + + if( !aFmt.GetCharFmt() ) + aFmt.SetCharFmt( pCFmt ); + + aRule.Set( n, aFmt ); + } + + // passt alles vollstaendig in den Frame? + BOOL bDefStep = nFrmWidth < (nSpaceSteps * MAXLEVEL); + for( ; n < MAXLEVEL; ++n ) + { + SwNumFmt aFmt( aRule.Get( n ) ); + aFmt.SetInclUpperLevel( TRUE ); + aFmt.SetRelLSpace( FALSE ); + if( bDefStep ) + aFmt.SetAbsLSpace( USHORT( (nLeftTxtPos + + SwNumRule::GetNumIndent( n - nLvl )))); + else + aFmt.SetAbsLSpace( USHORT( nSpaceSteps * n ) + + lNumIndent ); + aRule.Set( n, aFmt ); + } + } + } + } + else if( !aFlags.bAFmtByInput ) + SetColl( RES_POOLCOLL_NUM_LEVEL1 + ( Min( nLvl, cnNumBullColls ) * 4 ) ); + else + bChgEnum = FALSE; + } + + if( bChgEnum || bChgBullet ) + { + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + + if( aFlags.bSetNumRule ) + { + if( aFlags.bAFmtByInput ) + { + aDelPam.SetMark(); + aDelPam.GetMark()->nNode++; + aDelPam.GetNode(FALSE)->GetTxtNode()->UpdateNum( SwNodeNum( (BYTE)nLvl ) ); + } + + pAktTxtNd->UpdateNum( SwNodeNum( (BYTE)nLvl ) ); + pAktTxtNd->SetNumLSpace( TRUE ); + + pDoc->SetNumRule( aDelPam, aRule ); + aDelPam.DeleteMark(); + + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); + } + else + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, + bChgEnum ? (pStt - pOrigStt) : 0 ); + aDelPam.SetMark(); + + if( bChgBullet ) + pStt += 2; + + while( IsSpace( *pStt )) + pStt++; + + aDelPam.GetPoint()->nContent = USHORT( pStt - pOrigStt ); + DeleteSel( aDelPam ); + + if( !aFlags.bSetNumRule ) + { + String sChgStr( '\t' ); + if( bChgBullet ) + sChgStr.Insert( aFlags.cBullet, 0 ); + pDoc->Insert( aDelPam, sChgStr ); + + if( bChgBullet ) + { + aDelPam.GetPoint()->nContent = 0; + aDelPam.SetMark(); + aDelPam.GetMark()->nContent = 1; + SvxFontItem aFnt( aFlags.aBulletFont.GetFamily(), + aFlags.aBulletFont.GetName(), + aFlags.aBulletFont.GetStyleName(), + aFlags.aBulletFont.GetPitch(), + aFlags.aBulletFont.GetCharSet() ); + pDoc->SetFmtItemByAutoFmt( aDelPam, aFnt ); + aDelPam.DeleteMark(); + nAutoCorrPos = 2; + } + SvxTabStopItem aTStops; aTStops.Insert( SvxTabStop( 0 )); + pDoc->SetFmtItemByAutoFmt( aDelPam, aTStops ); + } + } + + if( bBreak ) + { + AutoCorrect( nAutoCorrPos ); /* Offset wegen Bullet + Tab */ + return; + } + + const SwTxtNode* pNxtNd = GetNextNode(); + while( CanJoin( pNxtNd ) && + nLvl == CalcLevel( *pNxtNd ) ) + { + SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES ); + bBreak = !IsFastFullLine( *pNxtNd ) || IsBlanksInString( *pNxtNd ) || + IsSentenceAtEnd( *pNxtNd ); + if( DeleteAktNxtPara( pNxtNd->GetTxt() ) ) + pDoc->Insert( aDelPam, ' ' ); + if( bBreak ) + break; + pNxtNd = GetNextNode(); + } + DeleteAktPara( FALSE, TRUE ); + AutoCorrect( nAutoCorrPos ); +} + + +void SwAutoFormat::BuildNegIndent( SwTwips nSpaces ) +{ + SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_NEG_INDENT ); + // Test auf Gegenueberstellung: + // (n Worte, durch Space/Tabs getrennt, mit gleicher + // Einrueckung in der 2.Zeile) + + // lese alle nachfolgenden Absaetze die zu dieser Aufzaehlung gehoeren + BOOL bBreak = TRUE; + xub_StrLen nSpacePos, nTxtPos = GetBigIndent( nSpacePos ); + if( bMoreLines ) + DelMoreLinesBlanks( TRUE ); + else + bBreak = !IsFastFullLine( *pAktTxtNd ) || + ( !nTxtPos && IsBlanksInString( *pAktTxtNd )) || + IsSentenceAtEnd( *pAktTxtNd ); + + SetColl( nTxtPos + ? RES_POOLCOLL_CONFRONTATION + : RES_POOLCOLL_TEXT_NEGIDENT ); + + if( nTxtPos ) + { + const String& rStr = pAktTxtNd->GetTxt(); + BOOL bInsTab = TRUE; + + if( '\t' == rStr.GetChar( nSpacePos+1 )) // ein Tab, das belassen wir + { + --nSpacePos; + bInsTab = FALSE; + } + + xub_StrLen nSpaceStt = nSpacePos; + while( nSpaceStt && IsSpace( rStr.GetChar( --nSpaceStt ) ) ) + ; + ++nSpaceStt; + + if( bInsTab && '\t' == rStr.GetChar( nSpaceStt ) ) // ein Tab, das belassen wir + { + ++nSpaceStt; + bInsTab = FALSE; + } + + + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, nSpacePos ); + +#if 0 +// nicht auf den akt. Einzug setzen, sondern Vorlagen benutzen + // das Attr. setzen + // hier sollte die richtige Vorlage benutzt werden !!! + SvxLRSpaceItem aLSpace; + aLSpace.SetTxtFirstLineOfst( -(SwTwips)nTxtPos ); + aLSpace.SetTxtLeft( nTxtPos ); + pDoc->Insert( aDelPam, aLSpace ); +#endif + // alten Spaces, usw. loeschen + if( nSpaceStt < nSpacePos ) + { + aDelPam.SetMark(); + aDelPam.GetMark()->nContent = nSpaceStt; + DeleteSel( aDelPam ); + if( bInsTab ) + pDoc->Insert( aDelPam, '\t' ); + } + } + + if( !bBreak ) + { + SetRedlineTxt( STR_AUTOFMTREDL_DEL_MORELINES ); + SwTxtFrmInfo aFInfo( pAktTxtFrm ); + const SwTxtNode* pNxtNd = GetNextNode(); + while( CanJoin( pNxtNd ) && + 20 < Abs( (long)(nSpaces - aFInfo.SetFrm( + GetFrm( *pNxtNd ) ).GetLineStart() )) + ) + { + bBreak = !IsFastFullLine( *pNxtNd ) || + IsBlanksInString( *pNxtNd ) || + IsSentenceAtEnd( *pNxtNd ); + if( DeleteAktNxtPara( pNxtNd->GetTxt() ) ) + pDoc->Insert( aDelPam, ' ' ); + if( bBreak ) + break; + pNxtNd = GetNextNode(); + } + } + DeleteAktPara( TRUE, TRUE ); + AutoCorrect(); +} + + +void SwAutoFormat::BuildHeadLine( USHORT nLvl ) +{ + if( aFlags.bWithRedlining ) + { + String sTxt( *ViewShell::GetShellRes()->GetAutoFmtNameLst()[ + STR_AUTOFMTREDL_SET_TMPL_HEADLINE ] ); + sTxt.SearchAndReplace( String::CreateFromAscii( + RTL_CONSTASCII_STRINGPARAM( "$(ARG1)" )), + String::CreateFromInt32( nLvl + 1 ) ); + pDoc->SetAutoFmtRedlineComment( &sTxt ); + } + + SetColl( RES_POOLCOLL_HEADLINE1 + nLvl, TRUE ); + if( aFlags.bAFmtByInput ) + { + SwTxtFmtColl& rNxtColl = pAktTxtNd->GetTxtColl()->GetNextTxtFmtColl(); + + DelPrevPara(); + + DeleteAktPara( TRUE, FALSE ); + DeleteAktNxtPara( aEmptyStr ); + + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx.GetIndex() + 1; + aDelPam.GetPoint()->nContent.Assign( aDelPam.GetCntntNode(), 0 ); + pDoc->SetTxtFmtColl( aDelPam, &rNxtColl ); + } + else + { + DeleteAktPara( TRUE, TRUE ); + AutoCorrect(); + } +} + + + // dann lasse doch mal das AutoCorrect auf den akt. TextNode los +void SwAutoFormat::AutoCorrect( xub_StrLen nPos ) +{ + if( aFlags.bAFmtByInput || + (!aFlags.bAutoCorrect && !aFlags.bReplaceQuote && + !aFlags.bCptlSttSntnc && !aFlags.bCptlSttWrd && + !aFlags.bChgFracionSymbol && !aFlags.bChgOrdinalNumber && + !aFlags.bChgToEnEmDash && !aFlags.bSetINetAttr && + !aFlags.bChgWeightUnderl) ) + return; + + const String* pTxt = &pAktTxtNd->GetTxt(); + if( nPos >= pTxt->Len() ) + return; + + aDelPam.DeleteMark(); + aDelPam.GetPoint()->nNode = aNdIdx; + aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); + + SwAutoCorrDoc aACorrDoc( *pEditShell, aDelPam ); + SvxAutoCorrect* pATst = OFF_APP()->GetAutoCorrect(); + + SwTxtFrmInfo aFInfo( 0 ); + + xub_StrLen nSttPos, nLastBlank = nPos; + BOOL bFirst = aFlags.bCptlSttSntnc, bFirstSent = bFirst; + sal_Unicode cChar; + + do { + while( nPos < pTxt->Len() && IsSpace( cChar = pTxt->GetChar( nPos ) )) + ++nPos; + if( nPos == pTxt->Len() ) + break; // das wars + + if( aFlags.bReplaceQuote && + ( '\"' == cChar || '\'' == cChar ) && + ( !nPos || ' ' == pTxt->GetChar( nPos-1 ) ) ) + { + // -------------------------------------- + // beachte: Sonderfall Symbolfonts !!! + if( !aFInfo.GetFrm() ) + aFInfo.SetFrm( GetFrm( *pAktTxtNd ) ); + if( !aFInfo.IsBullet( nPos )) + { + SetRedlineTxt( STR_AUTOFMTREDL_TYPO ); + aDelPam.GetPoint()->nContent = nPos; + BOOL bSetHardBlank = FALSE; + + String sReplace( pATst->GetQuote( aACorrDoc, + nPos, cChar, TRUE )); + + aDelPam.SetMark(); + aDelPam.GetPoint()->nContent = nPos+1; + if( 2 == sReplace.Len() && ' ' == sReplace.GetChar( 1 )) + { + sReplace.Erase( 1 ); + bSetHardBlank = TRUE; + } + pDoc->Replace( aDelPam, sReplace, FALSE ); + + if( aFlags.bWithRedlining ) + { + aNdIdx = aDelPam.GetPoint()->nNode; + pAktTxtNd = aNdIdx.GetNode().GetTxtNode(); + pTxt = &pAktTxtNd->GetTxt(); + aDelPam.SetMark(); + aFInfo.SetFrm( 0 ); + } + + nPos += sReplace.Len() - 1; + aDelPam.DeleteMark(); + if( bSetHardBlank ) + { + pDoc->Insert( aDelPam, CHAR_HARDBLANK ); + ++nPos; + } + } + } + + int bCallACorr = FALSE; + int bBreak = 0; + if( nPos && IsSpace( pTxt->GetChar( nPos-1 ))) + nLastBlank = nPos; + for( nSttPos = nPos; !bBreak && nPos < pTxt->Len(); ++nPos ) + switch( cChar = pTxt->GetChar( nPos ) ) + { + case '\"': + case '\'': + if( aFlags.bReplaceQuote ) + { + // -------------------------------------- + // beachte: Sonderfall Symbolfonts !!! + if( !aFInfo.GetFrm() ) + aFInfo.SetFrm( GetFrm( *pAktTxtNd ) ); + if( !aFInfo.IsBullet( nPos )) + { + SetRedlineTxt( STR_AUTOFMTREDL_TYPO ); + BOOL bSetHardBlank = FALSE; + aDelPam.GetPoint()->nContent = nPos; + String sReplace( pATst->GetQuote( aACorrDoc, + nPos, cChar, FALSE )); + + if( 2 == sReplace.Len() && ' ' == sReplace.GetChar( 0 )) + { + sReplace.Erase( 0, 1 ); + bSetHardBlank = TRUE; + } + + aDelPam.SetMark(); + aDelPam.GetPoint()->nContent = nPos+1; + pDoc->Replace( aDelPam, sReplace, FALSE ); + + if( aFlags.bWithRedlining ) + { + aNdIdx = aDelPam.GetPoint()->nNode; + pAktTxtNd = aNdIdx.GetNode().GetTxtNode(); + pTxt = &pAktTxtNd->GetTxt(); + aDelPam.SetMark(); + aDelPam.DeleteMark(); + aFInfo.SetFrm( 0 ); + } + + nPos += sReplace.Len() - 1; + aDelPam.DeleteMark(); + + if( bSetHardBlank ) + { + aDelPam.GetPoint()->nContent = nPos; + pDoc->Insert( aDelPam, CHAR_HARDBLANK ); + aDelPam.GetPoint()->nContent = ++nPos; + } + } + } + break; + case '*': + case '_': + if( aFlags.bChgWeightUnderl ) + { + // -------------------------------------- + // beachte: Sonderfall Symbolfonts !!! + if( !aFInfo.GetFrm() ) + aFInfo.SetFrm( GetFrm( *pAktTxtNd ) ); + if( !aFInfo.IsBullet( nPos )) + { + SetRedlineTxt( '*' == cChar + ? STR_AUTOFMTREDL_BOLD + : STR_AUTOFMTREDL_UNDER ); + + sal_Unicode cBlank = nSttPos ? pTxt->GetChar(nSttPos - 1) : 0; + aDelPam.GetPoint()->nContent = nPos; + + if( pATst->FnChgWeightUnderl( aACorrDoc, *pTxt, + nSttPos, nPos )) + { + nPos = aDelPam.GetPoint()->nContent.GetIndex() - 1; + // wurde vorm Start ein Zeichen entfernt? + if( cBlank && cBlank != pTxt->GetChar(nSttPos - 1) ) + --nSttPos; + } + } + } + break; + + case '.': + case '!': + case '?': + if( aFlags.bCptlSttSntnc ) + bFirstSent = TRUE; +//alle Wortrenner loesen die Autokorrektur aus! +// break; + + default: +//alle Wortrenner loesen die Autokorrektur aus! +// case ' ': +// case '\t': + if( !WordSelection::IsNormalChar( cChar )) + { + --nPos; // ++nPos von dem for ungueltig machen ! + ++bBreak; + } + break; + } + + if( nPos == nSttPos ) + { + if( ++nPos == pTxt->Len() ) + bCallACorr = TRUE; + } + else + bCallACorr = TRUE; + + + if( bCallACorr ) + { + bCallACorr = FALSE; + aDelPam.GetPoint()->nContent = nPos; + SetRedlineTxt( STR_AUTOFMTREDL_USE_REPLACE ); + if( aFlags.bAutoCorrect && + aACorrDoc.ChgAutoCorrWord( nSttPos, nPos, *pATst, 0 ) ) + { + nPos = aDelPam.GetPoint()->nContent.GetIndex(); + + if( aFlags.bWithRedlining ) + { + aNdIdx = aDelPam.GetPoint()->nNode; + pAktTxtNd = aNdIdx.GetNode().GetTxtNode(); + pTxt = &pAktTxtNd->GetTxt(); + aDelPam.SetMark(); + aDelPam.DeleteMark(); + } + + continue; // nichts weiter mehr abpruefen + } + + if( ( aFlags.bChgFracionSymbol && + SetRedlineTxt( STR_AUTOFMTREDL_FRACTION ) && + pATst->FnChgFractionSymbol( aACorrDoc, *pTxt, nSttPos, nPos ) ) || + ( aFlags.bChgOrdinalNumber && + SetRedlineTxt( STR_AUTOFMTREDL_ORDINAL ) && + pATst->FnChgOrdinalNumber( aACorrDoc, *pTxt, nSttPos, nPos ) ) || + ( aFlags.bChgToEnEmDash && + SetRedlineTxt( STR_AUTOFMTREDL_DASH ) && + pATst->FnChgToEnEmDash( aACorrDoc, *pTxt, nSttPos, nPos ) ) || + ( aFlags.bSetINetAttr && + ( nPos == pTxt->Len() || IsSpace( pTxt->GetChar( nPos )) ) && + SetRedlineTxt( STR_AUTOFMTREDL_DETECT_URL ) && + pATst->FnSetINetAttr( aACorrDoc, *pTxt, nLastBlank, nPos ) ) ) + nPos = aDelPam.GetPoint()->nContent.GetIndex(); + else + { + LanguageType eLang = LANGUAGE_SYSTEM; + if( pAktTxtNd ) + { + SfxItemSet aSet( pEditShell->GetDoc()->GetAttrPool(), + RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE ); + if( pAktTxtNd->GetAttr( aSet, nPos, nPos )) + eLang = ((const SvxLanguageItem&)aSet.Get( RES_CHRATR_LANGUAGE )) + .GetLanguage(); + } + + // Zwei Grossbuchstaben am Wort-Anfang ?? + if( aFlags.bCptlSttWrd ) + { + SetRedlineTxt( STR_AUTOFMTREDL_CPTL_STT_WORD ); + pATst->FnCptlSttWrd( aACorrDoc, *pTxt, nSttPos, nPos, eLang ); + } + // Grossbuchstabe am Satz-Anfang ?? + if( aFlags.bCptlSttSntnc && bFirst ) + { + SetRedlineTxt( STR_AUTOFMTREDL_CPTL_STT_SENT ); + pATst->FnCptlSttSntnc( aACorrDoc, *pTxt, TRUE, nSttPos, nPos, eLang); + bFirst = FALSE; + } + + bFirst = bFirstSent; + bFirstSent = FALSE; + + if( aFlags.bWithRedlining ) + { + aNdIdx = aDelPam.GetPoint()->nNode; + pAktTxtNd = aNdIdx.GetNode().GetTxtNode(); + pTxt = &pAktTxtNd->GetTxt(); + aDelPam.SetMark(); + aDelPam.DeleteMark(); + } + } + } + } while( nPos < pTxt->Len() ); + ClearRedlineTxt(); +} + + +SwAutoFormat::SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFmtFlags& rFlags, + SwNodeIndex* pSttNd, SwNodeIndex* pEndNd ) + : aFlags( rFlags ), + aDelPam( pEdShell->GetDoc()->GetNodes().GetEndOfExtras() ), + aNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfExtras(), +1 ), + aEndNdIdx( pEdShell->GetDoc()->GetNodes().GetEndOfContent() ), + pEditShell( pEdShell ), + pDoc( pEdShell->GetDoc() ), + pAktTxtNd( 0 ), pAktTxtFrm( 0 ), + nRedlAutoFmtSeqId( 0 ) +{ + ASSERT( (pSttNd && pEndNd) || (!pSttNd && !pEndNd), + "Kein Bereich angegeben" ); + + if( aFlags.bSetNumRule && !aFlags.bAFmtByInput ) + aFlags.bSetNumRule = FALSE; + + BOOL bReplaceStyles = !aFlags.bAFmtByInput || aFlags.bReplaceStyles; + + const International& rInter = Application::GetAppInternational(); + + String aStr; + const SwTxtNode* pNxtNd; + BOOL bNxtEmpty, bNxtAlpha; + USHORT nNxtLevel; + + // setze den Bereich zum Autoformatieren + if( pSttNd ) + { + aNdIdx = *pSttNd; + aNdIdx--; // fuer GoNextPara, ein Absatz davor + aEndNdIdx = *pEndNd; + aEndNdIdx++; + + // teste den vorhergehenden TextNode + pNxtNd = aNdIdx.GetNode().GetTxtNode(); + bEmptyLine = !pNxtNd || + IsEmptyLine( *pNxtNd ) || + IsNoAlphaLine( *pNxtNd ); + } + else + bEmptyLine = TRUE; // am Dokument Anfang + + bEnde = FALSE; + + // setze die Werte fuer die Prozent-Anzeige + nEndNdIdx = aEndNdIdx.GetIndex(); + + if( !aFlags.bAFmtByInput ) + ::StartProgress( STR_STATSTR_AUTOFORMAT, aNdIdx.GetIndex(), + nEndNdIdx = aEndNdIdx.GetIndex(), + pDoc->GetDocShell() ); + + SwRedlineMode eRedlMode = pDoc->GetRedlineMode(), eOldMode = eRedlMode; + if( aFlags.bWithRedlining ) + { + pDoc->SetAutoFmtRedline( TRUE ); + eRedlMode = SwRedlineMode(REDLINE_ON | REDLINE_SHOW_INSERT ); + eOldMode = SwRedlineMode( eOldMode | REDLINE_SHOW_DELETE | REDLINE_SHOW_INSERT ); + } + else + eRedlMode = SwRedlineMode( REDLINE_SHOW_INSERT | REDLINE_IGNORE ); + pDoc->SetRedlineMode( eRedlMode ); + + // wenn mehrere Zeilen, dann erstmal nicht mit + // dem nachfolgenden Absatz zusammenfassen. + bMoreLines = FALSE; + + nLastCalcHeadLvl = nLastCalcEnumLvl = 0; + nLastHeadLvl = nLastEnumLvl = USHRT_MAX; + USHORT nLevel, nDigitLvl; + + // defaulten + SwTxtFrmInfo aFInfo( 0 ); + + // das ist unser Automat fuer die Auto-Formatierung + eStat = READ_NEXT_PARA; + while( !bEnde ) + { + switch( eStat ) + { + case READ_NEXT_PARA: + { + aStr = GoNextPara(); + eStat = bEnde ? IS_ENDE : TST_EMPTY_LINE; + } + break; + + case TST_EMPTY_LINE: + if( IsEmptyLine( *pAktTxtNd ) ) + { + if( aFlags.bDelEmptyNode && !HasObjects( *pAktTxtNd ) ) + { + bEmptyLine = TRUE; + ULONG nOldCnt = pDoc->GetNodes().Count(); + DelEmptyLine(); + // wurde wiklich ein Node geloescht ? + if( nOldCnt != pDoc->GetNodes().Count() ) + aNdIdx--; // nicht den naechsten Absatz ueberspringen + } + eStat = READ_NEXT_PARA; + } + else + eStat = TST_ALPHA_LINE; + break; + + case TST_ALPHA_LINE: + if( IsNoAlphaLine( *pAktTxtNd )) + { + // erkenne eine Tabellendefinition +---+---+ + if( aFlags.bAFmtByInput && aFlags.bCreateTable && DoTable() ) + { + //JP 30.09.96: das DoTable() verlaesst sich auf das + // Pop und Move - Crsr nach dem AutoFormat! + pEdShell->Pop( FALSE ); + *pEdShell->GetCrsr() = aDelPam; + pEdShell->Push(); + + eStat = IS_ENDE; + break; + } + + // dann teste mal auf 3 "---" oder "===". In dem Fall + // soll der vorherige Absatz unterstrichen und dieser + // geloescht werden! + if( !DoUnderline() && bReplaceStyles ) + { + SetColl( RES_POOLCOLL_STANDARD, TRUE ); + bEmptyLine = TRUE; + } + eStat = READ_NEXT_PARA; + } + else + eStat = GET_ALL_INFO; + break; + + case GET_ALL_INFO: + { + if( pAktTxtNd->GetNumRule() ) + { + // in Numerierung nichts machen, zum naechsten + bEmptyLine = FALSE; + eStat = READ_NEXT_PARA; + // loesche alle Blanks am Anfang/Ende + // und alle mitten drin + //JP 29.04.98: erstmal nur alle "mitten drin". + DelMoreLinesBlanks( FALSE ); + break; + } + + aFInfo.SetFrm( pAktTxtFrm ); + + // erstmal: wurden schon mal entsprechende Vorlagen + // vergeben, so behalte die bei, gehe zum + // naechsten Node. + USHORT nPoolId = pAktTxtNd->GetTxtColl()->GetPoolFmtId(); + if( IsPoolUserFmt( nPoolId ) + ? !aFlags.bChgUserColl + : ( RES_POOLCOLL_STANDARD != nPoolId && + ( !aFlags.bAFmtByInput || + (RES_POOLCOLL_TEXT_MOVE != nPoolId && + RES_POOLCOLL_TEXT != nPoolId )) )) + { + eStat = HAS_FMTCOLL; + break; + } + + // teste auf Harte oder aus Vorlagen gesetzte LRSpaces + if( IsPoolUserFmt( nPoolId ) || + RES_POOLCOLL_STANDARD == nPoolId ) + { + short nSz; + SvxLRSpaceItem* pLRSpace; + if( SFX_ITEM_SET == pAktTxtNd->GetSwAttrSet(). + GetItemState( RES_LR_SPACE, TRUE, + (const SfxPoolItem**)&pLRSpace ) && + ( 0 != (nSz = pLRSpace->GetTxtFirstLineOfst()) || + 0 != pLRSpace->GetTxtLeft() ) ) + { + // Ausnahme: Numerierun/Aufzaehlung kann mit Einzug + // existieren!! + if( IsEnumericChar( *pAktTxtNd )) + { + nLevel = CalcLevel( *pAktTxtNd, &nDigitLvl ); + if( nLevel >= MAXLEVEL ) + nLevel = MAXLEVEL-1; + BuildEnum( nLevel, nDigitLvl ); + eStat = READ_NEXT_PARA; + break; + } + + + // nie zusammenfassen, so belassen + // (Opt. vielleicht als Ausnahmen nur Einzug) + bMoreLines = TRUE; + + if( bReplaceStyles ) + { + // dann setze doch eine unserer Vorlagen + if( 0 < nSz ) // positiver 1. Zeileneinzug + BuildIndent(); + else if( 0 > nSz ) // negativer 1. Zeileneinzug + BuildNegIndent( aFInfo.GetLineStart() ); + else if( pLRSpace->GetTxtLeft() ) // ist ein Einzug + BuildTextIndent(); + } + eStat = READ_NEXT_PARA; + break; + } + } + + nLevel = CalcLevel( *pAktTxtNd, &nDigitLvl ); + bMoreLines = !IsOneLine( *pAktTxtNd ); + pNxtNd = GetNextNode(); + if( pNxtNd ) + { + bNxtEmpty = IsEmptyLine( *pNxtNd ); + bNxtAlpha = IsNoAlphaLine( *pNxtNd ); + nNxtLevel = CalcLevel( *pNxtNd ); + + if( !bEmptyLine && HasBreakAttr( *pAktTxtNd ) ) + bEmptyLine = TRUE; + if( !bNxtEmpty && HasBreakAttr( *pNxtNd ) ) + bNxtEmpty = TRUE; + + // fuer z.B. selbst definierte Einzuege oder + // rechts/zentierte Ausrichtung +// if( !nLevel && 0 != aFInfo.GetLineStart() ) +// nLevel = 1; + } + else + { + bNxtEmpty = FALSE; // TRUE; + bNxtAlpha = FALSE; + nNxtLevel = 0; + } + eStat = !bMoreLines ? IS_ONE_LINE : TST_ENUMERIC; + } + break; + + case IS_ONE_LINE: + { + eStat = TST_ENUMERIC; + if( !bReplaceStyles ) + break; + + String sClrStr( aStr ); + + if( !DelLeadingBlanks( sClrStr ).Len() ) + { + bEmptyLine = TRUE; + eStat = READ_NEXT_PARA; + break; // naechsten Absatz lesen + } + + // Teste auf Ueberschrift + if( !bEmptyLine || + ((INTN_CHAR_UPPER | INTN_CHAR_ALPHA) != rInter. + GetCharType( GetFirstChar( aStr ) )) || + IsBlanksInString( *pAktTxtNd ) ) + break; + + bEmptyLine = FALSE; + String sEndClrStr( sClrStr ); + xub_StrLen nLen = DelTrailingBlanks( sEndClrStr ).Len(); + + // nicht, dann teste auf Ueberschrift + if( ':' == sEndClrStr.GetChar( nLen - 1 ) ) + { +//--------------------------------------------------------------------------- +// Wie ist denn nun die Bedingung fuer die Ueberschrift auf Ebene 3 ?? +// Zur Zeit: generell wenn am Ende ein ':' ist. +// +// if( bNxtEmpty || bNxtAlpha ) +// !IsEnumericChar( *pNxtNd ) ) +//--------------------------------------------------------------------------- + { + BuildHeadLine( 2 ); + eStat = READ_NEXT_PARA; + break; + } + } + else if( 256 <= sEndClrStr.GetChar( nLen-1 ) || + !strchr( ",.;", sEndClrStr.GetChar( nLen-1 )) ) + { + if( bNxtEmpty || bNxtAlpha + || ( pNxtNd && IsEnumericChar( *pNxtNd )) + +//--------------------------------------------------------------------------- +// ist zum Verwechseln mit neg. Einzug !! + /*|| nLevel < nNxtLevel*/ +//--------------------------------------------------------------------------- + + ) + { + // wurde Level vom Text vorgegeben ? +// if( USHRT_MAX != nDigitLvl ) +// nLevel = nDigitLvl; + + // eine Ebene runter ? + if( nLevel >= MAXLEVEL ) + nLevel = MAXLEVEL-1; + + if( USHRT_MAX == nLastHeadLvl ) + nLastHeadLvl = 0; + else if( nLastCalcHeadLvl < nLevel ) + { + if( nLastHeadLvl+1 < MAXLEVEL ) + ++nLastHeadLvl; + } + // eine Ebene hoch ? + else if( nLastCalcHeadLvl > nLevel ) + { + if( nLastHeadLvl ) + --nLastHeadLvl; + } + nLastCalcHeadLvl = nLevel; + + if( aFlags.bAFmtByInput ) + BuildHeadLine( nLevel ); + else + BuildHeadLine( nLastHeadLvl ); + eStat = READ_NEXT_PARA; + break; + } + } + } + break; + + case TST_ENUMERIC: + { + bEmptyLine = FALSE; + if( IsEnumericChar( *pAktTxtNd )) + { + if( nLevel >= MAXLEVEL ) + nLevel = MAXLEVEL-1; + BuildEnum( nLevel, nDigitLvl ); + eStat = READ_NEXT_PARA; + } +//JP 25.03.96: Vorlagen fuer Einzug zulassen +// else if( aFlags.bAFmtByInput ) +// eStat = READ_NEXT_PARA; + else if( bReplaceStyles ) + eStat = nLevel ? TST_IDENT : TST_NEG_IDENT; + else + eStat = READ_NEXT_PARA; + } + break; + + case TST_IDENT: + // Spaces am Anfang, dann teste doch mal auf Einzuege + if( bMoreLines && nLevel ) + { + SwTwips nSz = aFInfo.GetFirstIndent(); + if( 0 < nSz ) // positiver 1. Zeileneinzug + BuildIndent(); + else if( 0 > nSz ) // negativer 1. Zeileneinzug + BuildNegIndent( aFInfo.GetLineStart() ); + else // ist ein Einzug + BuildTextIndent(); + eStat = READ_NEXT_PARA; + } + else if( nLevel && pNxtNd && !bEnde && + !bNxtEmpty && !bNxtAlpha && !nNxtLevel && + !IsEnumericChar( *pNxtNd ) ) + { + // ist ein Einzug + BuildIndent(); + eStat = READ_NEXT_PARA; + } + else + eStat = TST_TXT_BODY; + break; + + case TST_NEG_IDENT: + // keine Spaces am Anfang, dann teste doch mal auf neg. Einzuege + { + if( bMoreLines && !nLevel ) + { + SwTwips nSz = aFInfo.GetFirstIndent(); + if( 0 < nSz ) // positiver 1. Zeileneinzug + BuildIndent(); + else if( 0 > nSz ) // negativer 1. Zeileneinzug + BuildNegIndent( aFInfo.GetLineStart() ); + else // ist ein kein Einzug + BuildText(); + eStat = READ_NEXT_PARA; + } + else if( !nLevel && pNxtNd && !bEnde && + !bNxtEmpty && !bNxtAlpha && nNxtLevel && + !IsEnumericChar( *pNxtNd ) ) + { + // ist ein neg. Einzug + BuildNegIndent( aFInfo.GetLineStart() ); + eStat = READ_NEXT_PARA; + } + else + eStat = TST_TXT_BODY; + } + break; + + case TST_TXT_BODY: + { + if( bMoreLines ) + { + SwTwips nSz = aFInfo.GetFirstIndent(); + if( 0 < nSz ) // positiver 1. Zeileneinzug + BuildIndent(); + else if( 0 > nSz ) // negativer 1. Zeileneinzug + BuildNegIndent( aFInfo.GetLineStart() ); + else if( nLevel ) // ist ein Einzug + BuildTextIndent(); + else + BuildText(); + } + else if( nLevel ) + BuildTextIndent(); + else + BuildText(); + eStat = READ_NEXT_PARA; + } + break; + + case HAS_FMTCOLL: + { + // erstmal: wurden schon mal entsprechende Vorlagen + // vergeben, so behalte die bei, gehe zum + // naechsten Node. + bEmptyLine = FALSE; + eStat = READ_NEXT_PARA; + // loesche alle Blanks am Anfang/Ende + // und alle mitten drin + //JP 29.04.98: erstmal nur alle "mitten drin". + DelMoreLinesBlanks( FALSE ); + + // behandel die harte Attributierung + if( pAktTxtNd->GetpSwAttrSet() ) + { + short nSz; + SvxLRSpaceItem* pLRSpace; + if( SFX_ITEM_SET == pAktTxtNd->GetpSwAttrSet()-> + GetItemState( RES_LR_SPACE, FALSE, + (const SfxPoolItem**)&pLRSpace ) && + ( 0 != (nSz = pLRSpace->GetTxtFirstLineOfst()) || + 0 != pLRSpace->GetTxtLeft() ) ) + { + // dann setze doch eine unserer Vorlagen + if( 0 < nSz ) // positiver 1. Zeileneinzug + BuildIndent(); + else if( 0 > nSz ) // negativer 1. Zeileneinzug + { + BuildNegIndent( aFInfo.GetLineStart() ); + } + else if( pLRSpace->GetTxtLeft() ) // ist ein Einzug + BuildTextIndent(); + else + BuildText(); + } + } + } + break; + + case IS_ENDE: + bEnde = TRUE; + break; + } + } + + if( aFlags.bWithRedlining ) + pDoc->SetAutoFmtRedline( FALSE ); + pDoc->SetRedlineMode( eOldMode ); + + // Prozent-Anzeige wieder abschalten + if( !aFlags.bAFmtByInput ) + ::EndProgress( pDoc->GetDocShell() ); +} + +void SwEditShell::AutoFormat( const SvxSwAutoFmtFlags* pAFlags ) +{ + SwWait* pWait = 0; + + SET_CURR_SHELL( this ); + StartAllAction(); + StartUndo( UNDO_AUTOFORMAT ); + + SvxSwAutoFmtFlags aAFFlags; // erst mal default - Werte + if( pAFlags ) // oder doch angegeben ?? + { + aAFFlags = *pAFlags; + if( !aAFFlags.bAFmtByInput ) + pWait = new SwWait( *GetDoc()->GetDocShell(), TRUE ); + } + + SwPaM* pCrsr = GetCrsr(); + // es gibt mehr als einen oder ist eine Selektion offen + if( pCrsr->GetNext() != pCrsr || pCrsr->HasMark() ) + { + FOREACHPAM_START(this) + if( PCURCRSR->HasMark() ) + { + SwAutoFormat aFmt( this, aAFFlags, &PCURCRSR->Start()->nNode, + &PCURCRSR->End()->nNode ); + } + FOREACHPAM_END() + } + else + { + SwAutoFormat aFmt( this, aAFFlags ); + } + + EndUndo( UNDO_AUTOFORMAT ); + EndAllAction(); + + delete pWait; +} + + +void SwEditShell::AutoFmtBySplitNode() +{ + SET_CURR_SHELL( this ); + SwPaM* pCrsr = GetCrsr(); + if( pCrsr->GetNext() == pCrsr && pCrsr->Move( fnMoveBackward, fnGoNode ) ) + { + StartAllAction(); + StartUndo( UNDO_AUTOFORMAT ); + + BOOL bRange = FALSE; + pCrsr->SetMark(); + SwIndex* pCntnt = &pCrsr->GetMark()->nContent; + if( pCntnt->GetIndex() ) + { + *pCntnt = 0; + bRange = TRUE; + } + else + { + // dann einen Node zurueckspringen + SwNodeIndex aNdIdx( pCrsr->GetMark()->nNode, -1 ); + SwTxtNode* pTxtNd = aNdIdx.GetNode().GetTxtNode(); + if( pTxtNd && pTxtNd->GetTxt().Len() ) + { + pCntnt->Assign( pTxtNd, 0 ); + pCrsr->GetMark()->nNode = aNdIdx; + bRange = TRUE; + } + } + + if( bRange ) + { + Push(); // Cursor sichern + + SvxSwAutoFmtFlags aAFFlags = *GetAutoFmtFlags(); // erst mal default - Werte + + SwAutoFormat aFmt( this, aAFFlags, &pCrsr->GetMark()->nNode, + &pCrsr->GetPoint()->nNode ); + + //JP 30.09.96: das DoTable() verlaesst sich auf das PopCrsr + // und MoveCrsr! + Pop( FALSE ); + pCrsr = GetCrsr(); + } + pCrsr->DeleteMark(); + pCrsr->Move( fnMoveForward, fnGoNode ); + + EndUndo( UNDO_AUTOFORMAT ); + EndAllAction(); + } +} + +SvxSwAutoFmtFlags* SwEditShell::GetAutoFmtFlags() +{ + if (!pAutoFmtFlags) + pAutoFmtFlags = new SvxSwAutoFmtFlags; + + return pAutoFmtFlags; +} + +void SwEditShell::SetAutoFmtFlags(SvxSwAutoFmtFlags * pFlags) +{ + SvxSwAutoFmtFlags* pEditFlags = GetAutoFmtFlags(); + + pEditFlags->bSetNumRule = pFlags->bSetNumRule; + pEditFlags->bChgEnumNum = pFlags->bChgEnumNum; + pEditFlags->bSetBorder = pFlags->bSetBorder; + pEditFlags->bCreateTable = pFlags->bCreateTable; + pEditFlags->bReplaceStyles = pFlags->bReplaceStyles; + pEditFlags->bAFmtByInpDelSpacesAtSttEnd = + pFlags->bAFmtByInpDelSpacesAtSttEnd; + pEditFlags->bAFmtByInpDelSpacesBetweenLines = + pFlags->bAFmtByInpDelSpacesBetweenLines; + + //JP 15.12.98: BulletZeichen und Font in die "normalen" kopieren, + // weil beim Autoformat nur mit diesen gearbeitet wird! + pEditFlags->cBullet = pFlags->cByInputBullet; + pEditFlags->aBulletFont = pFlags->aByInputBulletFont; + pEditFlags->cByInputBullet = pFlags->cByInputBullet; + pEditFlags->aByInputBulletFont = pFlags->aByInputBulletFont; +} + |