| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sw.hxx" |
| |
| |
| #define _SVSTDARR_LONGS |
| #define _SVSTDARR_USHORTS |
| |
| #include <ctype.h> |
| #include <hintids.hxx> |
| |
| #include <svl/svstdarr.hxx> |
| |
| #include <unotools/charclass.hxx> |
| |
| #include <vcl/msgbox.hxx> |
| |
| #include <editeng/boxitem.hxx> |
| #include <editeng/lrspitem.hxx> |
| #include <editeng/brkitem.hxx> |
| #include <editeng/adjitem.hxx> |
| #include <editeng/tstpitem.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <editeng/langitem.hxx> |
| #include <editeng/cscoitem.hxx> |
| #include <editeng/unolingu.hxx> |
| #include <editeng/acorrcfg.hxx> |
| |
| #include <swwait.hxx> |
| #include <fmtpdsc.hxx> |
| #include <fmtanchr.hxx> |
| #include <doc.hxx> |
| #include <IDocumentUndoRedo.hxx> |
| #include <docary.hxx> |
| #include <editsh.hxx> |
| #include <index.hxx> |
| #include <pam.hxx> |
| #include <edimp.hxx> |
| #include <fesh.hxx> |
| #include <swundo.hxx> // fuer die UndoIds |
| #include <poolfmt.hxx> |
| #include <ndtxt.hxx> |
| #include <txtfrm.hxx> |
| #include <frminf.hxx> |
| #include <pagedesc.hxx> |
| #include <paratr.hxx> |
| #include <swtable.hxx> |
| #include <acorrect.hxx> |
| #include <shellres.hxx> |
| #include <section.hxx> |
| #include <frmatr.hxx> |
| #include <charatr.hxx> |
| #include <mdiexp.hxx> |
| #include <statstr.hrc> |
| #include <comcore.hrc> |
| #include <numrule.hxx> |
| |
| using namespace ::com::sun::star; |
| |
| //------------------------------------------------------------------- |
| |
| //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 |
| |
| const sal_Unicode pBulletChar[6] = { '+', '*', '-', 0x2013, 0x2014, 0 }; |
| const int cnPosEnDash = 2, cnPosEmDash = 4, cnPosEnd = 5; |
| |
| const sal_Unicode cStarSymbolEnDash = 0x2013; |
| const sal_Unicode cStarSymbolEmDash = 0x2014; |
| |
| |
| 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 sal_uInt16 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 |
| CharClass* pCharClass; // Character classification |
| sal_uLong nEndNdIdx; // fuer die Prozent-Anzeige |
| LanguageType eCharClassLang; |
| |
| sal_uInt16 nLastHeadLvl, nLastCalcHeadLvl; |
| sal_uInt16 nLastEnumLvl, nLastCalcEnumLvl; |
| sal_uInt16 nRedlAutoFmtSeqId; |
| |
| 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; |
| |
| sal_Bool bEnde : 1; |
| sal_Bool bEmptyLine : 1; |
| sal_Bool bMoreLines : 1; |
| |
| static sal_Bool m_bAskForCancelUndoWhileBufferOverflow; |
| static short m_nActionWhileAutoformatUndoBufferOverflow; |
| |
| |
| // ------------- private methods ----------------------------- |
| void _GetCharClass( LanguageType eLang ); |
| CharClass& GetCharClass( LanguageType eLang ) const |
| { |
| if( !pCharClass || eLang != eCharClassLang ) |
| { |
| SwAutoFormat* pThis = (SwAutoFormat*)this; |
| pThis->_GetCharClass( eLang ); |
| } |
| return *pCharClass; |
| } |
| |
| |
| sal_Bool IsSpace( const sal_Unicode c ) const |
| { return (' ' == c || '\t' == c || 0x0a == c|| 0x3000 == c /* Jap. space */) ? sal_True : sal_False; } |
| |
| void SetColl( sal_uInt16 nId, sal_Bool bHdLineOrText = sal_False ); |
| String GoNextPara(); |
| sal_Bool HasObjects( const SwNode& rNd ); |
| |
| // TxtNode Methoden |
| const SwTxtNode* GetNextNode() const; |
| sal_Bool IsEmptyLine( const SwTxtNode& rNd ) const |
| { return 0 == rNd.GetTxt().Len() || |
| rNd.GetTxt().Len() == GetLeadingBlanks( rNd.GetTxt() ); } |
| |
| sal_Bool IsOneLine( const SwTxtNode& ) const; |
| sal_Bool IsFastFullLine( const SwTxtNode& ) const; |
| sal_Bool IsNoAlphaLine( const SwTxtNode&) const; |
| sal_Bool IsEnumericChar( const SwTxtNode&) const; |
| sal_Bool IsBlanksInString( const SwTxtNode&) const; |
| sal_uInt16 CalcLevel( const SwTxtNode&, sal_uInt16 *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; |
| |
| sal_Bool IsFirstCharCapital( const SwTxtNode& rNd ) const; |
| sal_uInt16 GetDigitLevel( const SwTxtNode& rTxtNd, xub_StrLen& rPos, |
| 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( sal_uInt16 nLvl, sal_uInt16 nDigitLevel ); |
| void BuildNegIndent( SwTwips nSpaces ); |
| void BuildHeadLine( sal_uInt16 nLvl ); |
| |
| sal_Bool HasSelBlanks( SwPaM& rPam ) const; |
| sal_Bool HasBreakAttr( const SwTxtNode& ) const; |
| void DeleteSel( SwPaM& rPam ); |
| sal_Bool DeleteAktNxtPara( const String& rNxtPara ); |
| // loesche im Node Anfang oder/und Ende |
| void DeleteAktPara( sal_Bool bStart = sal_True, sal_Bool nEnd = sal_True ); |
| void DelEmptyLine( sal_Bool bTstNextPara = sal_True ); |
| // loesche bei mehrzeiligen Absaetzen die "linken" und/oder |
| // "rechten" Raender |
| void DelMoreLinesBlanks( sal_Bool bWithLineBreaks = sal_False ); |
| // loesche den vorherigen Absatz |
| void DelPrevPara(); |
| // dann lasse doch mal das AutoCorrect auf den akt. TextNode los |
| void AutoCorrect( xub_StrLen nSttPos = 0 ); |
| |
| sal_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 ?? |
| sal_Bool IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const; |
| |
| sal_Bool DoUnderline(); |
| sal_Bool DoTable(); |
| |
| void _SetRedlineTxt( sal_uInt16 nId ); |
| sal_Bool SetRedlineTxt( sal_uInt16 nId ) |
| { if( aFlags.bWithRedlining ) _SetRedlineTxt( nId ); return sal_True; } |
| sal_Bool ClearRedlineTxt() |
| { if( aFlags.bWithRedlining ) pDoc->SetAutoFmtRedlineComment(0); return sal_True; } |
| |
| public: |
| SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFmtFlags& rFlags, |
| SwNodeIndex* pSttNd = 0, SwNodeIndex* pEndNd = 0 ); |
| ~SwAutoFormat() { |
| delete pCharClass; |
| } |
| }; |
| |
| sal_Bool SwAutoFormat::m_bAskForCancelUndoWhileBufferOverflow = sal_True; |
| short SwAutoFormat::m_nActionWhileAutoformatUndoBufferOverflow = RET_YES; |
| |
| const sal_Unicode* StrChr( const sal_Unicode* pSrc, sal_Unicode c ) |
| { |
| while( *pSrc && *pSrc != c ) |
| ++pSrc; |
| return *pSrc ? pSrc : 0; |
| } |
| |
| SwTxtFrm* SwAutoFormat::GetFrm( const SwTxtNode& rTxtNd ) const |
| { |
| // besorge mal den Frame |
| const SwCntntFrm *pFrm = rTxtNd.getLayoutFrm( pEditShell->GetLayout() ); |
| 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::_GetCharClass( LanguageType eLang ) |
| { |
| delete pCharClass; |
| pCharClass = new CharClass( SvxCreateLocale( eLang )); |
| eCharClassLang = eLang; |
| } |
| |
| void SwAutoFormat::_SetRedlineTxt( sal_uInt16 nActionId ) |
| { |
| String sTxt; |
| sal_uInt16 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: |
| case STR_AUTOFMTREDL_NON_BREAK_SPACE: |
| nSeqNo = ++nRedlAutoFmtSeqId; |
| break; |
| } |
| } |
| #if OSL_DEBUG_LEVEL > 1 |
| else |
| sTxt = String::CreateFromAscii( |
| RTL_CONSTASCII_STRINGPARAM( "Action-Text fehlt" )); |
| #endif |
| |
| pDoc->SetAutoFmtRedlineComment( &sTxt, nSeqNo ); |
| } |
| |
| String SwAutoFormat::GoNextPara() |
| { |
| SwNode* pNewNd = 0; |
| do { |
| //has to be checed twice before and after incrementation |
| if( aNdIdx.GetIndex() >= aEndNdIdx.GetIndex() ) |
| { |
| bEnde = sal_True; |
| return aEmptyStr; |
| } |
| |
| aNdIdx++; |
| if( aNdIdx.GetIndex() >= aEndNdIdx.GetIndex() ) |
| { |
| bEnde = sal_True; |
| return aEmptyStr; |
| } |
| else |
| pNewNd = &aNdIdx.GetNode(); |
| |
| // kein TextNode -> |
| // TableNode : Tabelle ueberspringen |
| // NoTxtNode : Nodes ueberspringen |
| // EndNode : Ende erreicht, beenden |
| if( pNewNd->IsEndNode() ) |
| { |
| bEnde = sal_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(); |
| } |
| |
| sal_Bool SwAutoFormat::HasObjects( const SwNode& rNd ) |
| { |
| // haengt irgend etwas absatzgebundenes am Absatz? |
| // z.B. Rahmen, DrawObjecte, .. |
| sal_Bool bRet = sal_False; |
| const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts(); |
| for( sal_uInt16 n = 0; n < rFmts.Count(); ++n ) |
| { |
| const SwFmtAnchor& rAnchor = rFmts[ n ]->GetAnchor(); |
| if ((FLY_AT_PAGE != rAnchor.GetAnchorId()) && |
| rAnchor.GetCntntAnchor() && |
| &rAnchor.GetCntntAnchor()->nNode.GetNode() == &rNd ) |
| { |
| bRet = sal_True; |
| break; |
| } |
| } |
| return bRet; |
| } |
| |
| const SwTxtNode* SwAutoFormat::GetNextNode() const |
| { |
| if( aNdIdx.GetIndex()+1 >= aEndNdIdx.GetIndex() ) |
| return 0; |
| return pDoc->GetNodes()[ aNdIdx.GetIndex() + 1 ]->GetTxtNode(); |
| } |
| |
| |
| sal_Bool SwAutoFormat::IsOneLine( const SwTxtNode& rNd ) const |
| { |
| SwTxtFrmInfo aFInfo( GetFrm( rNd ) ); |
| return aFInfo.IsOneLine(); |
| } |
| |
| |
| sal_Bool SwAutoFormat::IsFastFullLine( const SwTxtNode& rNd ) const |
| { |
| sal_Bool bRet = aFlags.bRightMargin; |
| if( bRet ) |
| { |
| SwTxtFrmInfo aFInfo( GetFrm( rNd ) ); |
| bRet = aFInfo.IsFilled( aFlags.nRightMargin ); |
| } |
| return bRet; |
| } |
| |
| |
| sal_Bool SwAutoFormat::IsEnumericChar( const SwTxtNode& rNd ) const |
| { |
| const String& rTxt = rNd.GetTxt(); |
| String sTmp( rTxt ); |
| xub_StrLen nBlnks = GetLeadingBlanks( sTmp ); |
| xub_StrLen nLen = rTxt.Len() - nBlnks; |
| if( !nLen ) |
| return sal_False; |
| |
| // -, +, * getrennt durch Blank ?? |
| if( 2 < nLen && IsSpace( rTxt.GetChar( nBlnks + 1 ) ) ) |
| { |
| if( StrChr( pBulletChar, rTxt.GetChar( nBlnks ) ) ) |
| return sal_True; |
| // sollte an der Position ein Symbolfont existieren ? |
| SwTxtFrmInfo aFInfo( GetFrm( rNd ) ); |
| if( aFInfo.IsBullet( nBlnks )) |
| return sal_True; |
| } |
| |
| // 1.) / 1. / 1.1.1 / (1). / (1) / .... |
| return USHRT_MAX != GetDigitLevel( rNd, nBlnks ); |
| } |
| |
| |
| sal_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 sal_True; |
| } |
| else |
| ++pTmp; |
| } |
| else |
| ++pTmp; |
| } |
| return sal_False; |
| } |
| |
| |
| sal_uInt16 SwAutoFormat::CalcLevel( const SwTxtNode& rNd, sal_uInt16 *pDigitLvl ) const |
| { |
| sal_uInt16 nLvl = 0, nBlnk = 0; |
| const String& rTxt = rNd.GetTxt(); |
| 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; |
| } |
| |
| |
| for( xub_StrLen n = 0, nEnd = rTxt.Len(); n < nEnd; ++n ) |
| { |
| switch( rTxt.GetChar( n ) ) |
| { |
| 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( rNd, n ); |
| return nLvl; |
| } |
| } |
| 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 ); |
| } |
| |
| |
| sal_Bool SwAutoFormat::IsNoAlphaLine( const SwTxtNode& rNd ) const |
| { |
| const String& rStr = rNd.GetTxt(); |
| if( !rStr.Len() ) |
| return sal_False; |
| // oder besser: ueber die Anzahl von Alpha/Num- und !AN-Zeichen |
| // bestimmen. |
| xub_StrLen nANChar = 0, nBlnk = 0; |
| |
| CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().GetLanguage().GetLanguage() ); |
| for( xub_StrLen n = 0, nEnd = rStr.Len(); n < nEnd; ++n ) |
| if( IsSpace( rStr.GetChar( n ) ) ) |
| ++nBlnk; |
| else if( rCC.isLetterNumeric( rStr, n )) |
| ++nANChar; |
| |
| // sind zu 75% keine Alpha-Nummerische-Zeichen, dann sal_True |
| sal_uLong nLen = rStr.Len() - nBlnk; |
| nLen = ( nLen * 3 ) / 4; // long overflow, if the strlen > sal_uInt16 |
| return xub_StrLen(nLen) < (rStr.Len() - nANChar - nBlnk); |
| } |
| |
| |
| |
| sal_Bool SwAutoFormat::DoUnderline() |
| { |
| if( !aFlags.bSetBorder ) |
| return sal_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 sal_False; |
| } |
| if( 0 == eState ) |
| eState = eTmp; |
| else if( eState != eTmp ) |
| return sal_False; |
| ++nCnt; |
| } |
| ++pStr; |
| } |
| |
| if( 2 < nCnt ) |
| { |
| // dann unterstreiche mal den vorherigen Absatz, wenn es diesen gibt! |
| DelEmptyLine( sal_False ); |
| 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; |
| } |
| SfxItemSet aSet(pDoc->GetAttrPool(), |
| RES_PARATR_CONNECT_BORDER, RES_PARATR_CONNECT_BORDER, |
| RES_BOX, RES_BOX, |
| 0); |
| aSet.Put( SwParaConnectBorderItem( sal_False ) ); |
| SvxBoxItem aBox( RES_BOX ); |
| aBox.SetLine( &aLine, BOX_LINE_BOTTOM ); |
| aBox.SetDistance( 42 ); // ~0,75 mm |
| aSet.Put(aBox); |
| pDoc->InsertItemSet( aDelPam, aSet, 0 ); |
| |
| aDelPam.DeleteMark(); |
| } |
| return 2 < nCnt; |
| } |
| |
| |
| sal_Bool SwAutoFormat::DoTable() |
| { |
| if( !aFlags.bCreateTable || !aFlags.bAFmtByInput || |
| pAktTxtNd->FindTableNode() ) |
| return sal_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 sal_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( static_cast<sal_uInt16>(aInfo.GetCharPos(n)), aPosArr.Count() ); |
| break; |
| |
| default: |
| return sal_False; |
| } |
| if( ++n == nEndPlus ) |
| break; |
| |
| ++pStr; |
| } |
| |
| if( 1 < aPosArr.Count() ) |
| { |
| // Ausrichtung vom Textnode besorgen: |
| sal_uInt16 nColCnt = aPosArr.Count() - 1; |
| SwTwips nSttPos = aPosArr[ 0 ]; |
| sal_Int16 eHori; |
| switch( pAktTxtNd->GetSwAttrSet().GetAdjust().GetAdjust() ) |
| { |
| case SVX_ADJUST_CENTER: eHori = text::HoriOrientation::CENTER; break; |
| case SVX_ADJUST_RIGHT: eHori = text::HoriOrientation::RIGHT; break; |
| |
| default: |
| if( nSttPos ) |
| { |
| eHori = text::HoriOrientation::NONE; |
| // dann muss als letztes noch die akt. FrameBreite |
| // ins Array |
| aPosArr.Insert( static_cast<sal_uInt16>(pAktTxtFrm->Frm().Width()), aPosArr.Count() ); |
| } |
| else |
| eHori = text::HoriOrientation::LEFT; |
| break; |
| } |
| |
| // dann erzeuge eine Tabelle, die den Zeichen entspricht |
| DelEmptyLine(); |
| SwNodeIndex aIdx( aDelPam.GetPoint()->nNode ); |
| aDelPam.Move( fnMoveForward ); |
| pDoc->InsertTable( SwInsertTableOptions( tabopts::ALL_TBL_INS_ATTR , 1 ), |
| *aDelPam.GetPoint(), 1, nColCnt, eHori, |
| 0, &aPosArr ); |
| aDelPam.GetPoint()->nNode = aIdx; |
| } |
| return 1 < aPosArr.Count(); |
| } |
| |
| |
| String& SwAutoFormat::DelLeadingBlanks( String& rStr ) const |
| { |
| xub_StrLen nL; |
| xub_StrLen n; |
| |
| for( 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 |
| { |
| xub_StrLen nL; |
| xub_StrLen n; |
| |
| for( 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; |
| } |
| |
| |
| sal_Bool SwAutoFormat::IsFirstCharCapital( const SwTxtNode& rNd ) const |
| { |
| const String& rTxt = rNd.GetTxt(); |
| for( xub_StrLen n = 0, nEnd = rTxt.Len(); n < nEnd; ++n ) |
| if( !IsSpace( rTxt.GetChar( n ) ) ) |
| { |
| CharClass& rCC = GetCharClass( rNd.GetSwAttrSet(). |
| GetLanguage().GetLanguage() ); |
| sal_Int32 nCharType = rCC.getCharacterType( rTxt, n ); |
| return CharClass::isLetterType( nCharType ) && |
| 0 != ( i18n::KCharacterType::UPPER & |
| nCharType ); |
| } |
| return sal_False; |
| } |
| |
| |
| sal_uInt16 SwAutoFormat::GetDigitLevel( const SwTxtNode& rNd, xub_StrLen& rPos, |
| String* pPreFix, String* pPostFix, String* pNumTypes ) const |
| { |
| // Teste auf 1.) / 1. / 1.1.1 / (1). / (1) / .... |
| const String& rTxt = rNd.GetTxt(); |
| xub_StrLen nPos = rPos; |
| int eScan = NONE; |
| |
| sal_uInt16 nStart = 0; |
| sal_uInt8 nDigitLvl = 0, nDigitCnt = 0; |
| //count number of parenthesis to assure a sensible order is found |
| sal_uInt16 nOpeningParentheses = 0; |
| sal_uInt16 nClosingParentheses = 0; |
| |
| CharClass& rCC = GetCharClass( rNd.GetSwAttrSet().GetLanguage().GetLanguage() ); |
| |
| while( nPos < rTxt.Len() && nDigitLvl < MAXLEVEL - 1) |
| { |
| const sal_Unicode cCurrentChar = rTxt.GetChar( nPos ); |
| if( ('0' <= cCurrentChar && '9' >= cCurrentChar) || |
| (0xff10 <= cCurrentChar && 0xff19 >= cCurrentChar) ) |
| { |
| 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 += cCurrentChar <= '9' ? cCurrentChar - '0' : cCurrentChar - 0xff10; |
| } |
| else if( rCC.isAlpha( rTxt, nPos ) ) |
| { |
| sal_Bool bIsUpper = |
| 0 != ( i18n::KCharacterType::UPPER & |
| rCC.getCharacterType( rTxt, nPos )); |
| sal_Unicode cLow = rCC.toLower( rTxt, nPos, 1 ).GetChar(0), 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 )) |
| #ifdef WITH_ALPHANUM_AS_NUMFMT |
| //detection of 'c' and 'd' a ROMAN numbering should not be done here |
| if( 256 > cLow &&( (eScan & (LOWER_ROMAN|UPPER_ROMAN)) |
| ? strchr( "mdclxvi", cLow ) |
| : strchr( "mlxvi", cLow ) )) |
| #else |
| if( 256 > cLow && ( strchr( "mdclxvi", cLow ) )) |
| #endif |
| { |
| 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; |
| |
| ( eScan &= ~(UPPER_ALPHA|LOWER_ALPHA)) |= eTmpScan; |
| 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 |
| return USHRT_MAX; |
| } |
| else |
| { |
| // roemische Zahlen: checke ob das gueltige Zeichen sind |
| sal_uInt16 nVal; |
| sal_Bool bError = sal_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 = static_cast<sal_uInt16>(nStart + (n10 * 8)); |
| else if( nMod5 == 0 || |
| nMod5 == (1 * nVal) || |
| nMod5 == (2 * nVal) ) |
| nStart = nStart + nVal; |
| else |
| bError = sal_True; |
| } |
| break; |
| |
| CHECK_ROMAN_5: |
| { |
| if( ( nStart / nVal ) & 1 ) |
| bError = sal_True; |
| else |
| { |
| int nMod = nStart % nVal; |
| int n10 = nVal / 5; |
| if( n10 == nMod ) |
| nStart = static_cast<sal_uInt16>(nStart + (3 * n10)); |
| else if( 0 == nMod ) |
| nStart = nStart + nVal; |
| else |
| bError = sal_True; |
| } |
| } |
| break; |
| |
| case 'i': |
| if( nStart % 5 >= 3 ) |
| bError = sal_True; |
| else |
| nStart += 1; |
| break; |
| |
| default: |
| bError = sal_True; |
| } |
| |
| if( bError ) |
| return USHRT_MAX; |
| } |
| eScan |= eTmpScan; // Digit rein |
| ++nDigitCnt; |
| } |
| else if( (256 > cCurrentChar && |
| strchr( ".)(", cCurrentChar )) || |
| 0x3002 == cCurrentChar /* Chinese trad. dot */|| |
| 0xff0e == cCurrentChar /* Japanese dot */|| |
| 0xFF08 == cCurrentChar /* opening bracket Chin./Jap.*/|| |
| 0xFF09 == cCurrentChar )/* closing bracket Chin./Jap. */ |
| { |
| if(cCurrentChar == '(' || cCurrentChar == 0xFF09) |
| nOpeningParentheses++; |
| else if(cCurrentChar == ')'|| cCurrentChar == 0xFF08) |
| nClosingParentheses++; |
| // nur wenn noch keine Zahlen gelesen wurden! |
| if( pPreFix && !( eScan & ( NO_DELIM | CHG )) ) |
| *pPreFix += rTxt.GetChar( nPos ); |
| else if( pPostFix ) |
| *pPostFix += rTxt.GetChar( nPos ); |
| |
| 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; |
| ++nPos; |
| } |
| if( !( CHG & eScan ) || rPos == nPos || |
| nPos == rTxt.Len() || !IsSpace( rTxt.GetChar( nPos ) ) || |
| (nOpeningParentheses > nClosingParentheses)) |
| return USHRT_MAX; |
| |
| if( (NO_DELIM & eScan) && pPreFix ) // den letzen nicht vergessen |
| (*pPreFix += (sal_Unicode)1) += String::CreateFromInt32( nStart ); |
| |
| rPos = nPos; |
| return nDigitLvl; // 0 .. 9 (MAXLEVEL - 1) |
| } |
| |
| |
| void SwAutoFormat::SetColl( sal_uInt16 nId, sal_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->HasSwAttrSet() ) |
| { |
| 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, |
| sal_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 ); |
| } |
| |
| |
| sal_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 sal_False; |
| } |
| return sal_True; |
| } |
| |
| |
| sal_Bool SwAutoFormat::HasBreakAttr( const SwTxtNode& rTxtNd ) const |
| { |
| const SfxItemSet* pSet = rTxtNd.GetpSwAttrSet(); |
| if( !pSet ) |
| return sal_False; |
| |
| const SfxPoolItem* pItem; |
| if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) |
| && SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() ) |
| return sal_True; |
| |
| if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, sal_False, &pItem ) |
| && ((SwFmtPageDesc*)pItem)->GetPageDesc() |
| && nsUseOnPage::PD_NONE != ((SwFmtPageDesc*)pItem)->GetPageDesc()->GetUseOn() ) |
| return sal_True; |
| return sal_False; |
| } |
| |
| |
| // ist ein Punkt am Ende ?? |
| sal_Bool SwAutoFormat::IsSentenceAtEnd( const SwTxtNode& rTxtNd ) const |
| { |
| const String& rStr = rTxtNd.GetTxt(); |
| xub_StrLen n = rStr.Len(); |
| if( !n ) |
| return sal_True; |
| |
| while( --n && IsSpace( rStr.GetChar( n ) ) ) |
| ; |
| return '.' == rStr.GetChar( n ); |
| } |
| |
| |
| // loesche im Node Anfang oder/und Ende |
| void SwAutoFormat::DeleteAktPara( sal_Bool bStart, sal_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 ); |
| } |
| |
| sal_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. |
| sal_Bool bHasBlnks = HasSelBlanks( aDelPam ); |
| |
| if( *aDelPam.GetPoint() != *aDelPam.GetMark() ) |
| DeleteSel( aDelPam ); |
| aDelPam.DeleteMark(); |
| |
| return !bHasBlnks; |
| } |
| |
| |
| void SwAutoFormat::DelEmptyLine( sal_Bool bTstNextPara ) |
| { |
| 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( sal_False )->GetTxtNode(); |
| if( pTNd ) |
| // erstmal den vorherigen Textnode benutzen. |
| aDelPam.GetMark()->nContent.Assign( pTNd, pTNd->GetTxt().Len() ); |
| else if( bTstNextPara ) |
| { |
| // dann versuche den naechsten (am Anfang vom Dok, Tabellen-Zellen, |
| // Rahmen, ... |
| aDelPam.GetMark()->nNode += 2; |
| pTNd = aDelPam.GetNode( sal_False )->GetTxtNode(); |
| if( pTNd ) |
| { |
| aDelPam.GetMark()->nContent.Assign( pTNd, 0 ); |
| aDelPam.GetPoint()->nContent = 0; |
| } |
| } |
| else |
| { |
| aDelPam.GetMark()->nNode = aNdIdx; |
| aDelPam.GetMark()->nContent = 0; |
| pTNd = pAktTxtNd; |
| } |
| if( pTNd ) |
| DeleteSel( aDelPam ); |
| |
| aDelPam.DeleteMark(); |
| ClearRedlineTxt(); |
| } |
| |
| |
| void SwAutoFormat::DelMoreLinesBlanks( sal_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() ) |
| { |
| sal_Bool bHasBlnks = HasSelBlanks( *pNxt ); |
| DeleteSel( *pNxt ); |
| if( !bHasBlnks ) |
| { |
| pDoc->InsertString( *pNxt, sal_Unicode(' ') ); |
| } |
| } |
| |
| if( pNxt == &aDelPam ) |
| break; |
| delete pNxt; |
| } while( sal_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 |
| sal_Bool bBreak = sal_True; |
| if( bMoreLines ) |
| DelMoreLinesBlanks( sal_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->InsertString( aDelPam, sal_Unicode(' ') ); |
| } |
| if( bBreak ) |
| break; |
| pNxtNd = GetNextNode(); |
| } while( CanJoin( pNxtNd ) && |
| !CalcLevel( *pNxtNd ) ); |
| } |
| } |
| DeleteAktPara( sal_True, sal_True ); |
| AutoCorrect(); |
| } |
| |
| |
| void SwAutoFormat::BuildTextIndent() |
| { |
| SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT_INDENT); |
| // lese alle nachfolgenden Absaetze die zu diesem Einzug gehoeren |
| sal_Bool bBreak = sal_True; |
| if( bMoreLines ) |
| DelMoreLinesBlanks( sal_True ); |
| else |
| bBreak = !IsFastFullLine( *pAktTxtNd ) || |
| IsBlanksInString( *pAktTxtNd ) || |
| IsSentenceAtEnd( *pAktTxtNd ); |
| |
| if( aFlags.bAFmtByInput ) |
| pAktTxtNd->SetAutoFmtLvl( (sal_uInt8)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->InsertString( aDelPam, sal_Unicode(' ') ); |
| } |
| if( bBreak ) |
| break; |
| pNxtNd = GetNextNode(); |
| } |
| } |
| DeleteAktPara( sal_True, sal_True ); |
| AutoCorrect(); |
| } |
| |
| |
| void SwAutoFormat::BuildText() |
| { |
| SetRedlineTxt( STR_AUTOFMTREDL_SET_TMPL_TEXT ); |
| // lese alle nachfolgenden Absaetze die zu diesem Text |
| // ohne Einzug gehoeren |
| sal_Bool bBreak = sal_True; |
| if( bMoreLines ) |
| DelMoreLinesBlanks(); |
| else |
| bBreak = !IsFastFullLine( *pAktTxtNd ) || |
| IsBlanksInString( *pAktTxtNd ) || |
| IsSentenceAtEnd( *pAktTxtNd ); |
| SetColl( RES_POOLCOLL_TEXT, sal_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->InsertString( aDelPam, sal_Unicode(' ') ); |
| } |
| if( bBreak ) |
| break; |
| const SwTxtNode* pCurrNode = pNxtNd; |
| pNxtNd = GetNextNode(); |
| if(!pNxtNd || pCurrNode == pNxtNd) |
| break; |
| } |
| } |
| DeleteAktPara( sal_True, sal_True ); |
| AutoCorrect(); |
| } |
| |
| |
| void SwAutoFormat::BuildEnum( sal_uInt16 nLvl, sal_uInt16 nDigitLevel ) |
| { |
| SetRedlineTxt( STR_AUTOFMTREDL_SET_NUMBULET ); |
| |
| sal_Bool bBreak = sal_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( static_cast<xub_StrLen>(pTxt - pSav) ); |
| nLeftTxtPos -= pAktTxtNd->GetSwAttrSet().GetLRSpace().GetLeft(); |
| } |
| |
| if( bMoreLines ) |
| DelMoreLinesBlanks(); |
| else |
| bBreak = !IsFastFullLine( *pAktTxtNd ) || |
| IsBlanksInString( *pAktTxtNd ) || |
| IsSentenceAtEnd( *pAktTxtNd ); |
| sal_Bool bRTL = pEditShell->IsInRightToLeftText(); |
| // SetColl( RES_POOLCOLL_NUM_LEVEL1 + ( nLvl * 4 ) ); |
| DeleteAktPara( sal_True, sal_True ); |
| |
| sal_Bool bChgBullet = sal_False, bChgEnum = sal_False; |
| xub_StrLen nAutoCorrPos = 0; |
| |
| // falls die Numerierung gesetzt werden, die akt. besorgen |
| // --> OD 2008-02-11 #newlistlevelattrs# |
| SwNumRule aRule( pDoc->GetUniqueNumRuleName(), |
| // --> OD 2008-06-06 #i89178# |
| numfunc::GetDefaultPositionAndSpaceMode() ); |
| // <-- |
| // <-- |
| const SwNumRule* pCur = 0; |
| if( aFlags.bSetNumRule && 0 != (pCur = pAktTxtNd->GetNumRule()) ) |
| aRule = *pCur; |
| |
| // ersetze das Bullet-Zeichen mit dem definiertem |
| const String& rStr = pAktTxtNd->GetTxt(); |
| xub_StrLen nTxtStt = 0, nOrigTxtStt = 0; |
| const sal_Unicode* pFndBulletChr; |
| // if( aFlags.bAFmtByInput ? aFlags.bSetNumRule : aFlags.bChgEnumNum && |
| if( aFlags.bChgEnumNum && |
| 2 < rStr.Len() && |
| 0 != ( pFndBulletChr = StrChr( pBulletChar, rStr.GetChar( nTxtStt ) )) |
| && IsSpace( rStr.GetChar( nTxtStt + 1 ) ) ) |
| { |
| if( aFlags.bAFmtByInput ) |
| { |
| if( aFlags.bSetNumRule ) |
| { |
| SwCharFmt* pCFmt = pDoc->GetCharFmtFromPool( |
| RES_POOLCHR_BUL_LEVEL ); |
| bChgBullet = sal_True; |
| // wurde das Format schon mal angepasst? |
| if( !aRule.GetNumFmt( nLvl ) ) |
| { |
| int nBulletPos = pFndBulletChr - pBulletChar; |
| sal_Unicode cBullChar; |
| const Font* pBullFnt( 0 ); |
| if( nBulletPos < cnPosEnDash ) |
| { |
| cBullChar = aFlags.cBullet; |
| pBullFnt = &aFlags.aBulletFont; |
| } |
| else |
| { |
| cBullChar = nBulletPos < cnPosEmDash |
| ? cStarSymbolEnDash |
| : cStarSymbolEmDash; |
| // --> OD 2008-06-03 #i63395# |
| // Only apply user defined default bullet font |
| if ( numfunc::IsDefBulletFontUserDefined() ) |
| { |
| pBullFnt = &numfunc::GetDefBulletFont(); |
| } |
| // <-- |
| } |
| |
| sal_uInt16 nAbsPos = lBullIndent; |
| sal_uInt16 nSpaceSteps = nLvl |
| ? sal_uInt16(nLeftTxtPos / nLvl) |
| : lBullIndent; |
| for( sal_uInt8 n = 0; n < MAXLEVEL; ++n, nAbsPos = nAbsPos + nSpaceSteps ) |
| { |
| SwNumFmt aFmt( aRule.Get( n ) ); |
| aFmt.SetBulletFont( pBullFnt ); |
| aFmt.SetBulletChar( cBullChar ); |
| aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL); |
| // #i93908# clear suffix for bullet lists |
| aFmt.SetPrefix(::rtl::OUString()); |
| aFmt.SetSuffix(::rtl::OUString()); |
| aFmt.SetFirstLineOffset( lBullFirstLineOffset ); |
| aFmt.SetAbsLSpace( nAbsPos ); |
| if( !aFmt.GetCharFmt() ) |
| aFmt.SetCharFmt( pCFmt ); |
| if( bRTL ) |
| aFmt.SetNumAdjust( SVX_ADJUST_RIGHT ); |
| |
| aRule.Set( n, aFmt ); |
| |
| if( n == nLvl && |
| nFrmWidth < ( nSpaceSteps * MAXLEVEL ) ) |
| nSpaceSteps = static_cast<sal_uInt16>(( nFrmWidth - nLeftTxtPos ) / |
| ( MAXLEVEL - nLvl )); |
| } |
| } |
| } |
| } |
| else |
| { |
| bChgBullet = sal_True; |
| SetColl( static_cast<sal_uInt16>(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( *pAktTxtNd, nTxtStt, |
| &aPreFix, &aPostFix, &aNumTypes )) ) |
| { |
| bChgEnum = sal_True; |
| |
| // Ebene 0 und Einrueckung dann wird die Ebene durch den linken |
| // Einzug und der default NumEinrueckung bestimmt. |
| if( !nDigitLevel && nLeftTxtPos ) |
| nLvl = Min( sal_uInt16( nLeftTxtPos / lNumIndent ), |
| sal_uInt16( 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.SetStart( static_cast<sal_uInt16>(aPreFix.GetToken( 1, |
| (sal_Unicode)1 ).ToInt32())); |
| aFmt.SetPrefix( aPreFix.GetToken( 0, (sal_Unicode)1 )); |
| aFmt.SetSuffix( aPostFix.GetToken( 0, (sal_Unicode)1 )); |
| aFmt.SetIncludeUpperLevels( 0 ); |
| |
| if( !aFmt.GetCharFmt() ) |
| aFmt.SetCharFmt( pCFmt ); |
| |
| if( aNumTypes.Len() ) |
| aFmt.SetNumberingType(aNumTypes.GetChar( 0 ) - '0'); |
| |
| if( bRTL ) |
| aFmt.SetNumAdjust( SVX_ADJUST_RIGHT ); |
| aRule.Set( nLvl, aFmt ); |
| } |
| else |
| { |
| sal_uInt16 nSpaceSteps = nLvl ? sal_uInt16(nLeftTxtPos / nLvl) : 0; |
| sal_uInt8 n; |
| for( n = 0; n <= nLvl; ++n ) |
| { |
| SwNumFmt aFmt( aRule.Get( n ) ); |
| |
| aFmt.SetStart( static_cast<sal_uInt16>(aPreFix.GetToken( n+1, |
| (sal_Unicode)1 ).ToInt32() )); |
| if( !n ) |
| aFmt.SetPrefix( aPreFix.GetToken( n, (sal_Unicode)1 )); |
| aFmt.SetSuffix( aPostFix.GetToken( n, (sal_Unicode)1 )); |
| aFmt.SetIncludeUpperLevels( MAXLEVEL ); |
| if( n < aNumTypes.Len() ) |
| aFmt.SetNumberingType((aNumTypes.GetChar( n ) - '0')); |
| |
| aFmt.SetAbsLSpace( sal_uInt16( nSpaceSteps * n ) |
| + lNumIndent ); |
| |
| if( !aFmt.GetCharFmt() ) |
| aFmt.SetCharFmt( pCFmt ); |
| if( bRTL ) |
| aFmt.SetNumAdjust( SVX_ADJUST_RIGHT ); |
| |
| aRule.Set( n, aFmt ); |
| } |
| |
| // passt alles vollstaendig in den Frame? |
| sal_Bool bDefStep = nFrmWidth < (nSpaceSteps * MAXLEVEL); |
| for( ; n < MAXLEVEL; ++n ) |
| { |
| SwNumFmt aFmt( aRule.Get( n ) ); |
| aFmt.SetIncludeUpperLevels( MAXLEVEL ); |
| if( bDefStep ) |
| aFmt.SetAbsLSpace( sal_uInt16( (nLeftTxtPos + |
| SwNumRule::GetNumIndent(static_cast<sal_uInt8>(n-nLvl))))); |
| else |
| aFmt.SetAbsLSpace( sal_uInt16( nSpaceSteps * n ) |
| + lNumIndent ); |
| aRule.Set( n, aFmt ); |
| } |
| } |
| } |
| } |
| else if( !aFlags.bAFmtByInput ) |
| SetColl( static_cast<sal_uInt16>(RES_POOLCOLL_NUM_LEVEL1 + ( Min( nLvl, cnNumBullColls ) * 4 ) )); |
| else |
| bChgEnum = sal_False; |
| } |
| |
| if( bChgEnum || bChgBullet ) |
| { |
| aDelPam.DeleteMark(); |
| aDelPam.GetPoint()->nNode = aNdIdx; |
| |
| if( aFlags.bSetNumRule ) |
| { |
| if( aFlags.bAFmtByInput ) |
| { |
| aDelPam.SetMark(); |
| aDelPam.GetMark()->nNode++; |
| aDelPam.GetNode(sal_False)->GetTxtNode()->SetAttrListLevel( nLvl ); |
| } |
| |
| pAktTxtNd->SetAttrListLevel(nLvl); |
| pAktTxtNd->SetNumLSpace( sal_True ); |
| |
| // --> OD 2008-03-17 #refactorlists# |
| // start new list |
| pDoc->SetNumRule( aDelPam, aRule, true ); |
| // <-- |
| aDelPam.DeleteMark(); |
| |
| aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); |
| } |
| else |
| aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, |
| bChgEnum ? (nTxtStt - nOrigTxtStt) : 0 ); |
| aDelPam.SetMark(); |
| |
| if( bChgBullet ) |
| nTxtStt += 2; |
| |
| while( nTxtStt < rStr.Len() && IsSpace( rStr.GetChar( nTxtStt ) )) |
| nTxtStt++; |
| |
| aDelPam.GetPoint()->nContent = nTxtStt - nOrigTxtStt; |
| DeleteSel( aDelPam ); |
| |
| if( !aFlags.bSetNumRule ) |
| { |
| String sChgStr( '\t' ); |
| if( bChgBullet ) |
| sChgStr.Insert( aFlags.cBullet, 0 ); |
| pDoc->InsertString( aDelPam, sChgStr ); |
| |
| SfxItemSet aSet( pDoc->GetAttrPool(), aTxtNodeSetRange ); |
| if( bChgBullet ) |
| { |
| aDelPam.GetPoint()->nContent = 0; |
| aDelPam.SetMark(); |
| aDelPam.GetMark()->nContent = 1; |
| SetAllScriptItem( aSet, |
| SvxFontItem( aFlags.aBulletFont.GetFamily(), |
| aFlags.aBulletFont.GetName(), |
| aFlags.aBulletFont.GetStyleName(), |
| aFlags.aBulletFont.GetPitch(), |
| aFlags.aBulletFont.GetCharSet(), |
| RES_CHRATR_FONT ) ); |
| pDoc->SetFmtItemByAutoFmt( aDelPam, aSet ); |
| aDelPam.DeleteMark(); |
| nAutoCorrPos = 2; |
| aSet.ClearItem(); |
| } |
| SvxTabStopItem aTStops( RES_PARATR_TABSTOP ); aTStops.Insert( SvxTabStop( 0 )); |
| aSet.Put( aTStops ); |
| pDoc->SetFmtItemByAutoFmt( aDelPam, aSet ); |
| } |
| } |
| |
| 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->InsertString( aDelPam, sal_Unicode(' ') ); |
| } |
| if( bBreak ) |
| break; |
| const SwTxtNode* pCurrNode = pNxtNd; |
| pNxtNd = GetNextNode(); |
| if(!pNxtNd || pCurrNode == pNxtNd) |
| break; |
| } |
| DeleteAktPara( sal_False, sal_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 |
| sal_Bool bBreak = sal_True; |
| xub_StrLen nSpacePos, nTxtPos = GetBigIndent( nSpacePos ); |
| if( bMoreLines ) |
| DelMoreLinesBlanks( sal_True ); |
| else |
| bBreak = !IsFastFullLine( *pAktTxtNd ) || |
| ( !nTxtPos && IsBlanksInString( *pAktTxtNd )) || |
| IsSentenceAtEnd( *pAktTxtNd ); |
| |
| SetColl( static_cast<sal_uInt16>( nTxtPos |
| ? RES_POOLCOLL_CONFRONTATION |
| : RES_POOLCOLL_TEXT_NEGIDENT ) ); |
| |
| if( nTxtPos ) |
| { |
| const String& rStr = pAktTxtNd->GetTxt(); |
| sal_Bool bInsTab = sal_True; |
| |
| if( '\t' == rStr.GetChar( nSpacePos+1 )) // ein Tab, das belassen wir |
| { |
| --nSpacePos; |
| bInsTab = sal_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 = sal_False; |
| } |
| |
| |
| aDelPam.DeleteMark(); |
| aDelPam.GetPoint()->nNode = aNdIdx; |
| aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, nSpacePos ); |
| |
| // alten Spaces, usw. loeschen |
| if( nSpaceStt < nSpacePos ) |
| { |
| aDelPam.SetMark(); |
| aDelPam.GetMark()->nContent = nSpaceStt; |
| DeleteSel( aDelPam ); |
| if( bInsTab ) |
| { |
| pDoc->InsertString( aDelPam, sal_Unicode('\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->InsertString( aDelPam, sal_Unicode(' ') ); |
| } |
| if( bBreak ) |
| break; |
| pNxtNd = GetNextNode(); |
| } |
| } |
| DeleteAktPara( sal_True, sal_True ); |
| AutoCorrect(); |
| } |
| |
| |
| void SwAutoFormat::BuildHeadLine( sal_uInt16 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( static_cast<sal_uInt16>(RES_POOLCOLL_HEADLINE1 + nLvl ), sal_True ); |
| if( aFlags.bAFmtByInput ) |
| { |
| SwTxtFmtColl& rNxtColl = pAktTxtNd->GetTxtColl()->GetNextTxtFmtColl(); |
| |
| DelPrevPara(); |
| |
| DeleteAktPara( sal_True, sal_False ); |
| DeleteAktNxtPara( aEmptyStr ); |
| |
| aDelPam.DeleteMark(); |
| aDelPam.GetPoint()->nNode = aNdIdx.GetIndex() + 1; |
| aDelPam.GetPoint()->nContent.Assign( aDelPam.GetCntntNode(), 0 ); |
| pDoc->SetTxtFmtColl( aDelPam, &rNxtColl ); |
| } |
| else |
| { |
| DeleteAktPara( sal_True, sal_True ); |
| AutoCorrect(); |
| } |
| } |
| |
| |
| // dann lasse doch mal das AutoCorrect auf den akt. TextNode los |
| void SwAutoFormat::AutoCorrect( xub_StrLen nPos ) |
| { |
| SvxAutoCorrect* pATst = SvxAutoCorrCfg::Get()->GetAutoCorrect(); |
| long aSvxFlags = pATst->GetFlags( ); |
| bool bReplaceQuote = ( aSvxFlags & ChgQuotes ) > 0; |
| bool bReplaceSglQuote = ( aSvxFlags & ChgSglQuotes ) > 0; |
| |
| if( aFlags.bAFmtByInput || |
| (!aFlags.bAutoCorrect && !bReplaceQuote && !bReplaceSglQuote && |
| !aFlags.bCptlSttSntnc && !aFlags.bCptlSttWrd && |
| !aFlags.bChgOrdinalNumber && |
| !aFlags.bChgToEnEmDash && !aFlags.bSetINetAttr && |
| !aFlags.bChgWeightUnderl && !aFlags.bAddNonBrkSpace) ) |
| return; |
| |
| const String* pTxt = &pAktTxtNd->GetTxt(); |
| if( nPos >= pTxt->Len() ) |
| return; |
| |
| sal_Bool bGetLanguage = aFlags.bChgOrdinalNumber || |
| aFlags.bChgToEnEmDash || aFlags.bSetINetAttr || |
| aFlags.bCptlSttWrd || aFlags.bCptlSttSntnc || |
| aFlags.bAddNonBrkSpace; |
| |
| |
| aDelPam.DeleteMark(); |
| aDelPam.GetPoint()->nNode = aNdIdx; |
| aDelPam.GetPoint()->nContent.Assign( pAktTxtNd, 0 ); |
| |
| SwAutoCorrDoc aACorrDoc( *pEditShell, aDelPam ); |
| |
| SwTxtFrmInfo aFInfo( 0 ); |
| |
| xub_StrLen nSttPos, nLastBlank = nPos; |
| sal_Bool bFirst = aFlags.bCptlSttSntnc, bFirstSent = bFirst; |
| sal_Unicode cChar = 0; |
| |
| CharClass& rAppCC = GetAppCharClass(); |
| |
| do { |
| while( nPos < pTxt->Len() && IsSpace( cChar = pTxt->GetChar( nPos ) )) |
| ++nPos; |
| if( nPos == pTxt->Len() ) |
| break; // das wars |
| |
| if( ( ( bReplaceQuote && '\"' == cChar ) || |
| ( bReplaceSglQuote && '\'' == 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; |
| sal_Bool bSetHardBlank = sal_False; |
| |
| String sReplace( pATst->GetQuote( aACorrDoc, |
| nPos, cChar, sal_True )); |
| |
| aDelPam.SetMark(); |
| aDelPam.GetPoint()->nContent = nPos+1; |
| if( 2 == sReplace.Len() && ' ' == sReplace.GetChar( 1 )) |
| { |
| sReplace.Erase( 1 ); |
| bSetHardBlank = sal_True; |
| } |
| pDoc->ReplaceRange( 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->InsertString( aDelPam, CHAR_HARDBLANK ); |
| ++nPos; |
| } |
| } |
| } |
| |
| int bCallACorr = sal_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( ( cChar == '\"' && bReplaceQuote ) || ( cChar == '\'' && bReplaceSglQuote ) ) |
| { |
| // -------------------------------------- |
| // beachte: Sonderfall Symbolfonts !!! |
| if( !aFInfo.GetFrm() ) |
| aFInfo.SetFrm( GetFrm( *pAktTxtNd ) ); |
| if( !aFInfo.IsBullet( nPos )) |
| { |
| SetRedlineTxt( STR_AUTOFMTREDL_TYPO ); |
| sal_Bool bSetHardBlank = sal_False; |
| aDelPam.GetPoint()->nContent = nPos; |
| String sReplace( pATst->GetQuote( aACorrDoc, |
| nPos, cChar, sal_False )); |
| |
| if( 2 == sReplace.Len() && ' ' == sReplace.GetChar( 0 )) |
| { |
| sReplace.Erase( 0, 1 ); |
| bSetHardBlank = sal_True; |
| } |
| |
| aDelPam.SetMark(); |
| aDelPam.GetPoint()->nContent = nPos+1; |
| pDoc->ReplaceRange( 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->InsertString( 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 )) |
| { |
| if( aFlags.bWithRedlining ) |
| { |
| aNdIdx = aDelPam.GetPoint()->nNode; |
| pAktTxtNd = aNdIdx.GetNode().GetTxtNode(); |
| pTxt = &pAktTxtNd->GetTxt(); |
| aDelPam.SetMark(); |
| aDelPam.DeleteMark(); |
| aFInfo.SetFrm( 0 ); |
| } |
| //#125102# in case of the mode REDLINE_SHOW_DELETE the ** are still contained in pTxt |
| if(0 == (pDoc->GetRedlineMode() & nsRedlineMode_t::REDLINE_SHOW_DELETE)) |
| nPos = aDelPam.GetPoint()->nContent.GetIndex() - 1; |
| // wurde vorm Start ein Zeichen entfernt? |
| if( cBlank && cBlank != pTxt->GetChar(nSttPos - 1) ) |
| --nSttPos; |
| } |
| } |
| } |
| break; |
| case '/': |
| if ( aFlags.bAddNonBrkSpace ) |
| { |
| LanguageType eLang = (bGetLanguage && pAktTxtNd) |
| ? pAktTxtNd->GetLang( nSttPos ) |
| : LANGUAGE_SYSTEM; |
| |
| SetRedlineTxt( STR_AUTOFMTREDL_NON_BREAK_SPACE ); |
| if ( pATst->FnAddNonBrkSpace( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) ) |
| --nPos; |
| } |
| break; |
| |
| case '.': |
| case '!': |
| case '?': |
| if( aFlags.bCptlSttSntnc ) |
| bFirstSent = sal_True; |
| //alle Wortrenner loesen die Autokorrektur aus! |
| // break; |
| default: |
| //alle Wortrenner loesen die Autokorrektur aus! |
| // case ' ': |
| // case '\t': |
| if( !( rAppCC.isLetterNumeric( *pTxt, nPos ) |
| || '/' == cChar )) // '/' should not be a word seperator (e.g. '1/2' needs to be handled as one word for replacement) |
| { |
| --nPos; // ++nPos von dem for ungueltig machen ! |
| ++bBreak; |
| } |
| break; |
| } |
| |
| if( nPos == nSttPos ) |
| { |
| if( ++nPos == pTxt->Len() ) |
| bCallACorr = sal_True; |
| } |
| else |
| bCallACorr = sal_True; |
| |
| |
| if( bCallACorr ) |
| { |
| bCallACorr = sal_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 |
| } |
| |
| LanguageType eLang = (bGetLanguage && pAktTxtNd) |
| ? pAktTxtNd->GetLang( nSttPos ) |
| : LANGUAGE_SYSTEM; |
| |
| if ( aFlags.bAddNonBrkSpace ) |
| { |
| SetRedlineTxt( STR_AUTOFMTREDL_NON_BREAK_SPACE ); |
| pATst->FnAddNonBrkSpace( aACorrDoc, *pTxt, nSttPos, nPos, eLang ); |
| } |
| |
| if( ( aFlags.bChgOrdinalNumber && |
| SetRedlineTxt( STR_AUTOFMTREDL_ORDINAL ) && |
| pATst->FnChgOrdinalNumber( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) ) || |
| ( aFlags.bChgToEnEmDash && |
| SetRedlineTxt( STR_AUTOFMTREDL_DASH ) && |
| pATst->FnChgToEnEmDash( aACorrDoc, *pTxt, nSttPos, nPos, eLang ) ) || |
| ( aFlags.bSetINetAttr && |
| ( nPos == pTxt->Len() || IsSpace( pTxt->GetChar( nPos )) ) && |
| SetRedlineTxt( STR_AUTOFMTREDL_DETECT_URL ) && |
| pATst->FnSetINetAttr( aACorrDoc, *pTxt, nLastBlank, nPos, eLang ) ) ) |
| nPos = aDelPam.GetPoint()->nContent.GetIndex(); |
| else |
| { |
| // 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, sal_True, nSttPos, nPos, eLang); |
| bFirst = sal_False; |
| } |
| |
| bFirst = bFirstSent; |
| bFirstSent = sal_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 ), |
| pCharClass( 0 ), |
| nRedlAutoFmtSeqId( 0 ) |
| { |
| ASSERT( (pSttNd && pEndNd) || (!pSttNd && !pEndNd), |
| "Kein Bereich angegeben" ); |
| |
| if( aFlags.bSetNumRule && !aFlags.bAFmtByInput ) |
| aFlags.bSetNumRule = sal_False; |
| |
| sal_Bool bReplaceStyles = !aFlags.bAFmtByInput || aFlags.bReplaceStyles; |
| |
| const SwTxtNode* pNxtNd = 0; |
| sal_Bool bNxtEmpty = sal_False; |
| sal_Bool bNxtAlpha = sal_False; |
| sal_uInt16 nNxtLevel = 0; |
| |
| // 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 = sal_True; // am Dokument Anfang |
| |
| bEnde = sal_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() ); |
| |
| RedlineMode_t eRedlMode = pDoc->GetRedlineMode(), eOldMode = eRedlMode; |
| if( aFlags.bWithRedlining ) |
| { |
| pDoc->SetAutoFmtRedline( sal_True ); |
| eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT); |
| } |
| else |
| eRedlMode = (RedlineMode_t)(nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_IGNORE); |
| pDoc->SetRedlineMode( eRedlMode ); |
| |
| // save undo state (might be turned off) |
| bool const bUndoState = pDoc->GetIDocumentUndoRedo().DoesUndo(); |
| |
| // wenn mehrere Zeilen, dann erstmal nicht mit |
| // dem nachfolgenden Absatz zusammenfassen. |
| bMoreLines = sal_False; |
| |
| nLastCalcHeadLvl = nLastCalcEnumLvl = 0; |
| nLastHeadLvl = nLastEnumLvl = USHRT_MAX; |
| sal_uInt16 nLevel = 0; |
| sal_uInt16 nDigitLvl = 0; |
| |
| // defaulten |
| SwTxtFrmInfo aFInfo( 0 ); |
| |
| // das ist unser Automat fuer die Auto-Formatierung |
| eStat = READ_NEXT_PARA; |
| while( !bEnde ) |
| { |
| switch( eStat ) |
| { |
| case READ_NEXT_PARA: |
| { |
| GoNextPara(); |
| eStat = bEnde ? IS_ENDE : TST_EMPTY_LINE; |
| } |
| break; |
| |
| case TST_EMPTY_LINE: |
| if( IsEmptyLine( *pAktTxtNd ) ) |
| { |
| if( aFlags.bDelEmptyNode && !HasObjects( *pAktTxtNd ) ) |
| { |
| bEmptyLine = sal_True; |
| sal_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( sal_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, sal_True ); |
| bEmptyLine = sal_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 = sal_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( sal_False ); |
| break; |
| } |
| |
| aFInfo.SetFrm( pAktTxtFrm ); |
| |
| // erstmal: wurden schon mal entsprechende Vorlagen |
| // vergeben, so behalte die bei, gehe zum |
| // naechsten Node. |
| sal_uInt16 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, sal_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 = sal_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 = sal_True; |
| if( !bNxtEmpty && HasBreakAttr( *pNxtNd ) ) |
| bNxtEmpty = sal_True; |
| |
| // fuer z.B. selbst definierte Einzuege oder |
| // rechts/zentierte Ausrichtung |
| // if( !nLevel && 0 != aFInfo.GetLineStart() ) |
| // nLevel = 1; |
| } |
| else |
| { |
| bNxtEmpty = sal_False; // sal_True; |
| bNxtAlpha = sal_False; |
| nNxtLevel = 0; |
| } |
| eStat = !bMoreLines ? IS_ONE_LINE : TST_ENUMERIC; |
| } |
| break; |
| |
| case IS_ONE_LINE: |
| { |
| eStat = TST_ENUMERIC; |
| if( !bReplaceStyles ) |
| break; |
| |
| String sClrStr( pAktTxtNd->GetTxt() ); |
| |
| if( !DelLeadingBlanks( sClrStr ).Len() ) |
| { |
| bEmptyLine = sal_True; |
| eStat = READ_NEXT_PARA; |
| break; // naechsten Absatz lesen |
| } |
| |
| // Teste auf Ueberschrift |
| if( !bEmptyLine || !IsFirstCharCapital( *pAktTxtNd ) || |
| IsBlanksInString( *pAktTxtNd ) ) |
| break; |
| |
| bEmptyLine = sal_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 = sal_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 = sal_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( sal_False ); |
| |
| // behandel die harte Attributierung |
| if( pAktTxtNd->HasSwAttrSet() ) |
| { |
| short nSz; |
| SvxLRSpaceItem* pLRSpace; |
| if( bReplaceStyles && |
| SFX_ITEM_SET == pAktTxtNd->GetSwAttrSet(). |
| GetItemState( RES_LR_SPACE, sal_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 = sal_True; |
| break; |
| } |
| } |
| |
| if( aFlags.bWithRedlining ) |
| pDoc->SetAutoFmtRedline( sal_False ); |
| pDoc->SetRedlineMode( eOldMode ); |
| |
| // restore undo (in case it has been changed) |
| pDoc->GetIDocumentUndoRedo().DoUndo(bUndoState); |
| |
| // 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 ); |
| |
| sal_Bool bRange = sal_False; |
| pCrsr->SetMark(); |
| SwIndex* pCntnt = &pCrsr->GetMark()->nContent; |
| if( pCntnt->GetIndex() ) |
| { |
| *pCntnt = 0; |
| bRange = sal_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 = sal_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( sal_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; |
| } |
| |